Reworks this to be a little cleaner, adding some testing

This commit is contained in:
Trenton H 2023-11-02 10:50:35 -07:00 committed by shamoon
parent 63d6213272
commit e418e0db88
6 changed files with 314 additions and 413 deletions

View File

@ -1,241 +0,0 @@
# Generated by Django 4.2.5 on 2023-10-31 17:28
import django.db.models.deletion
import django.utils.timezone
from django.conf import settings
from django.db import migrations
from django.db import models
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
("documents", "1039_consumptiontemplate"),
]
operations = [
migrations.CreateModel(
name="CustomField",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"created",
models.DateTimeField(
db_index=True,
default=django.utils.timezone.now,
verbose_name="created",
editable=False,
),
),
("name", models.CharField(max_length=128)),
(
"data_type",
models.CharField(
choices=[
("string", "String"),
("url", "URL"),
("date", "Date"),
("boolean", "Boolean"),
("integer", "Integer"),
],
max_length=50,
verbose_name="data type",
editable=False,
),
),
],
options={
"verbose_name": "custom field",
"verbose_name_plural": "custom fields",
"ordering": ("created",),
},
),
migrations.CreateModel(
name="CustomFieldInstance",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"created",
models.DateTimeField(
editable=False,
db_index=True,
default=django.utils.timezone.now,
verbose_name="created",
),
),
(
"document",
models.ForeignKey(
editable=False,
on_delete=django.db.models.deletion.CASCADE,
related_name="custom_fields",
to="documents.document",
),
),
(
"field",
models.ForeignKey(
editable=False,
on_delete=django.db.models.deletion.CASCADE,
related_name="fields",
to="documents.customfield",
),
),
],
options={
"verbose_name": "custom field instance",
"verbose_name_plural": "custom field instances",
"ordering": ("created",),
},
),
migrations.CreateModel(
name="CustomFieldBoolean",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("value", models.BooleanField()),
(
"parent",
models.OneToOneField(
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
related_name="boolean",
to="documents.customfieldinstance",
),
),
],
),
migrations.CreateModel(
name="CustomFieldDate",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("value", models.DateField()),
(
"parent",
models.OneToOneField(
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
related_name="date",
to="documents.customfieldinstance",
),
),
],
),
migrations.CreateModel(
name="CustomFieldInteger",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("value", models.IntegerField()),
(
"parent",
models.OneToOneField(
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
related_name="integer",
to="documents.customfieldinstance",
),
),
],
),
migrations.CreateModel(
name="CustomFieldShortText",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("value", models.CharField(max_length=128)),
(
"parent",
models.OneToOneField(
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
related_name="short_text",
to="documents.customfieldinstance",
),
),
],
),
migrations.CreateModel(
name="CustomFieldUrl",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("value", models.URLField()),
(
"parent",
models.OneToOneField(
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
related_name="url",
to="documents.customfieldinstance",
),
),
],
),
migrations.AddConstraint(
model_name="customfield",
constraint=models.UniqueConstraint(
fields=("name",),
name="documents_customfield_unique_name",
),
),
migrations.AddConstraint(
model_name="customfieldinstance",
constraint=models.UniqueConstraint(
fields=("document", "field"),
name="documents_customfieldinstance_unique_document_field",
),
),
]

View File

@ -0,0 +1,124 @@
# Generated by Django 4.2.6 on 2023-11-02 17:38
import django.db.models.deletion
import django.utils.timezone
from django.db import migrations
from django.db import models
class Migration(migrations.Migration):
dependencies = [
("documents", "1039_consumptiontemplate"),
]
operations = [
migrations.CreateModel(
name="CustomField",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"created",
models.DateTimeField(
db_index=True,
default=django.utils.timezone.now,
editable=False,
verbose_name="created",
),
),
("name", models.CharField(max_length=128)),
(
"data_type",
models.CharField(
choices=[
("string", "String"),
("url", "URL"),
("date", "Date"),
("boolean", "Boolean"),
("integer", "Integer"),
],
editable=False,
max_length=50,
verbose_name="data type",
),
),
],
options={
"verbose_name": "custom field",
"verbose_name_plural": "custom fields",
"ordering": ("created",),
},
),
migrations.CreateModel(
name="CustomFieldInstance",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"created",
models.DateTimeField(
db_index=True,
default=django.utils.timezone.now,
editable=False,
verbose_name="created",
),
),
("value_text", models.CharField(max_length=128, null=True)),
("value_bool", models.BooleanField(null=True)),
("value_url", models.URLField(null=True)),
("value_date", models.DateField(null=True)),
("value_int", models.IntegerField(null=True)),
(
"document",
models.ForeignKey(
editable=False,
on_delete=django.db.models.deletion.CASCADE,
related_name="custom_fields",
to="documents.document",
),
),
(
"field",
models.ForeignKey(
editable=False,
on_delete=django.db.models.deletion.CASCADE,
related_name="fields",
to="documents.customfield",
),
),
],
options={
"verbose_name": "custom field instance",
"verbose_name_plural": "custom field instances",
"ordering": ("created",),
},
),
migrations.AddConstraint(
model_name="customfield",
constraint=models.UniqueConstraint(
fields=("name",),
name="documents_customfield_unique_name",
),
),
migrations.AddConstraint(
model_name="customfieldinstance",
constraint=models.UniqueConstraint(
fields=("document", "field"),
name="documents_customfieldinstance_unique_document_field",
),
),
]

View File

@ -4,7 +4,6 @@ import os
import re import re
from collections import OrderedDict from collections import OrderedDict
from pathlib import Path from pathlib import Path
from typing import Any
from typing import Final from typing import Final
from typing import Optional from typing import Optional
@ -960,6 +959,17 @@ class CustomFieldInstance(models.Model):
editable=False, editable=False,
) )
# Actual data storage
value_text = models.CharField(max_length=128, null=True)
value_bool = models.BooleanField(null=True)
value_url = models.URLField(null=True)
value_date = models.DateField(null=True)
value_int = models.IntegerField(null=True)
class Meta: class Meta:
ordering = ("created",) ordering = ("created",)
verbose_name = _("custom field instance") verbose_name = _("custom field instance")
@ -978,134 +988,16 @@ class CustomFieldInstance(models.Model):
def value(self): def value(self):
""" """
Based on the data type, access the actual value the instance stores Based on the data type, access the actual value the instance stores
A little shorthand/quick way to get what is actually here
""" """
if self.field.data_type == CustomField.FieldDataType.STRING: if self.field.data_type == CustomField.FieldDataType.STRING:
return self.short_text.value return self.value_text
elif self.field.data_type == CustomField.FieldDataType.URL: elif self.field.data_type == CustomField.FieldDataType.URL:
return self.url.value return self.value_url
elif self.field.data_type == CustomField.FieldDataType.DATE: elif self.field.data_type == CustomField.FieldDataType.DATE:
return self.date.value return self.value_date
elif self.field.data_type == CustomField.FieldDataType.BOOL: elif self.field.data_type == CustomField.FieldDataType.BOOL:
return self.boolean.value return self.value_bool
elif self.field.data_type == CustomField.FieldDataType.INT: elif self.field.data_type == CustomField.FieldDataType.INT:
return self.integer.value return self.value_int
raise NotImplementedError(self.field.data_type) raise NotImplementedError(self.field.data_type)
@property
def field_type(self):
"""
Based on the data type, quick access to class for storing that value
"""
if self.field.data_type == CustomField.FieldDataType.STRING:
return CustomFieldShortText
elif self.field.data_type == CustomField.FieldDataType.URL:
return CustomFieldUrl
elif self.field.data_type == CustomField.FieldDataType.DATE:
return CustomFieldDate
elif self.field.data_type == CustomField.FieldDataType.BOOL:
return CustomFieldBoolean
elif self.field.data_type == CustomField.FieldDataType.INT:
return CustomFieldInteger
raise NotImplementedError(self.field.data_type)
@staticmethod
def from_json(
document: Document,
field: OrderedDict,
value: Any,
) -> "CustomFieldInstance":
instance, _ = CustomFieldInstance.objects.get_or_create(
document=document,
field=CustomField.objects.get(id=field["id"]),
)
instance.field_type.objects.update_or_create(
parent=instance,
defaults={"value": value},
)
return instance
class CustomFieldShortText(models.Model):
"""
Data storage for a short text custom field
"""
value = models.CharField(max_length=128)
parent = models.OneToOneField(
CustomFieldInstance,
on_delete=models.CASCADE,
related_name="short_text",
parent_link=True,
)
def __str__(self) -> str:
return f"{self.value}"
class CustomFieldBoolean(models.Model):
"""
Data storage for a boolean custom field
"""
value = models.BooleanField()
parent = models.OneToOneField(
CustomFieldInstance,
on_delete=models.CASCADE,
related_name="boolean",
parent_link=True,
)
def __str__(self) -> str:
return f"{self.value}"
class CustomFieldUrl(models.Model):
"""
Data storage for a URL custom field
"""
value = models.URLField()
parent = models.OneToOneField(
CustomFieldInstance,
on_delete=models.CASCADE,
related_name="url",
parent_link=True,
)
def __str__(self) -> str:
return f"{self.value}"
class CustomFieldDate(models.Model):
"""
Data storage for a date custom field
"""
value = models.DateField()
parent = models.OneToOneField(
CustomFieldInstance,
on_delete=models.CASCADE,
related_name="date",
parent_link=True,
)
def __str__(self) -> str:
return f"{self.value}"
class CustomFieldInteger(models.Model):
"""
Data storage for a date custom field
"""
value = models.IntegerField()
parent = models.OneToOneField(
CustomFieldInstance,
on_delete=models.CASCADE,
related_name="integer",
parent_link=True,
)
def __str__(self) -> str:
return f"{self.value}"

View File

@ -11,6 +11,7 @@ from django.contrib.auth.models import User
from django.utils.crypto import get_random_string from django.utils.crypto import get_random_string
from django.utils.text import slugify from django.utils.text import slugify
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from drf_writable_nested.serializers import NestedUpdateMixin
from guardian.core import ObjectPermissionChecker from guardian.core import ObjectPermissionChecker
from guardian.shortcuts import get_users_with_perms from guardian.shortcuts import get_users_with_perms
from rest_framework import fields from rest_framework import fields
@ -396,9 +397,6 @@ class StoragePathField(serializers.PrimaryKeyRelatedField):
return StoragePath.objects.all() return StoragePath.objects.all()
from drf_writable_nested.serializers import NestedUpdateMixin
class CustomFieldSerializer(serializers.ModelSerializer): class CustomFieldSerializer(serializers.ModelSerializer):
data_type = serializers.ChoiceField( data_type = serializers.ChoiceField(
choices=CustomField.FieldDataType, choices=CustomField.FieldDataType,
@ -426,41 +424,82 @@ class CustomFieldOnUpdateSerializer(serializers.ModelSerializer):
class CustomFieldInstanceSerializer(serializers.ModelSerializer): class CustomFieldInstanceSerializer(serializers.ModelSerializer):
field = serializers.PrimaryKeyRelatedField(queryset=CustomField.objects.all()) field = serializers.PrimaryKeyRelatedField(queryset=CustomField.objects.all())
value = serializers.JSONField() value = serializers.SerializerMethodField(read_only=True)
value_text = serializers.CharField(required=False, write_only=True)
value_bool = serializers.BooleanField(required=False, write_only=True)
value_url = serializers.URLField(required=False, write_only=True)
value_date = serializers.DateField(required=False, write_only=True)
value_int = serializers.IntegerField(required=False, write_only=True)
def validate(self, data):
"""
Check that start is before finish.
"""
# Let the normal validation run first
data = super().validate(data)
# This field must exist, as it is validated
parent_field = data["field"]
type_to_key_map = {
CustomField.FieldDataType.STRING: "value_text",
CustomField.FieldDataType.URL: "value_url",
CustomField.FieldDataType.DATE: "value_date",
CustomField.FieldDataType.BOOL: "value_bool",
CustomField.FieldDataType.INT: "value_int",
}
# For the given data type, a certain key must exist
expected_key = type_to_key_map[parent_field.data_type]
if expected_key not in data:
raise serializers.ValidationError(
(
f"Field of type {parent_field.data_type} must"
f' contain a "{expected_key}" key'
),
)
return data
def create(self, validated_data): def create(self, validated_data):
print("hello from create") type_to_key_map = {
from pprint import pprint CustomField.FieldDataType.STRING: "value_text",
CustomField.FieldDataType.URL: "value_url",
pprint(dict(validated_data)) CustomField.FieldDataType.DATE: "value_date",
CustomField.FieldDataType.BOOL: "value_bool",
CustomField.FieldDataType.INT: "value_int",
}
# An instance is attached to a document
document: Document = validated_data["document"] document: Document = validated_data["document"]
# And to a CustomField
custom_field: CustomField = validated_data["field"] custom_field: CustomField = validated_data["field"]
instance, _ = CustomFieldInstance.objects.get_or_create( # This key must exist, as it is validated
document=document, field=custom_field expected_key = type_to_key_map[custom_field.data_type]
)
instance_data_class = instance.field_type # Actually update or create the instance, providing the value
_, _ = instance_data_class.objects.update_or_create( instance, _ = CustomFieldInstance.objects.update_or_create(
parent=instance, defaults={"value": validated_data["value"]} document=document,
field=custom_field,
defaults={expected_key: validated_data[expected_key]},
) )
return instance return instance
def update(self, instance: CustomFieldInstance, validated_data):
print("hello from update")
from pprint import pprint
pprint(validated_data)
pprint(instance.id)
def get_value(self, obj: CustomFieldInstance): def get_value(self, obj: CustomFieldInstance):
return obj.value return obj.value
class Meta: class Meta:
model = CustomFieldInstance model = CustomFieldInstance
fields = ["value", "field"] fields = [
"value",
"value_text",
"value_bool",
"value_url",
"value_date",
"value_int",
"field",
]
class DocumentSerializer( class DocumentSerializer(
OwnedObjectSerializer, NestedUpdateMixin, DynamicFieldsModelSerializer OwnedObjectSerializer,
NestedUpdateMixin,
DynamicFieldsModelSerializer,
): ):
correspondent = CorrespondentField(allow_null=True) correspondent = CorrespondentField(allow_null=True)
tags = TagsField(many=True) tags = TagsField(many=True)

View File

@ -1,11 +1,14 @@
from datetime import date
from pprint import pprint
from django.contrib.auth.models import User from django.contrib.auth.models import User
from rest_framework import status from rest_framework import status
from rest_framework.test import APITestCase from rest_framework.test import APITestCase
from documents.models import CustomField, CustomFieldInstance, CustomFieldShortText from documents.models import CustomField
from documents.models import CustomFieldInstance
from documents.models import Document from documents.models import Document
from documents.tests.utils import DirectoriesMixin from documents.tests.utils import DirectoriesMixin
from pprint import pprint
class TestCustomField(DirectoriesMixin, APITestCase): class TestCustomField(DirectoriesMixin, APITestCase):
@ -76,38 +79,37 @@ class TestCustomField(DirectoriesMixin, APITestCase):
data_type=CustomField.FieldDataType.URL, data_type=CustomField.FieldDataType.URL,
) )
date_value = date.today()
resp = self.client.patch( resp = self.client.patch(
f"/api/documents/{doc.id}/", f"/api/documents/{doc.id}/",
data={ data={
"custom_fields": [ "custom_fields": [
{ {
"field": custom_field_string.id, "field": custom_field_string.id,
"value": "test value", "value_text": "test value",
}, },
{ {
"field": custom_field_date.id, "field": custom_field_date.id,
"value": "2023-10-31", "value_date": date_value.isoformat(),
}, },
{ {
"field": custom_field_int.id, "field": custom_field_int.id,
"value": "3", "value_int": 3,
}, },
{ {
"field": custom_field_boolean.id, "field": custom_field_boolean.id,
"value": "True", "value_bool": True,
}, },
{ {
"field": custom_field_url.id, "field": custom_field_url.id,
"value": "https://example.com", "value_url": "https://example.com",
}, },
], ],
}, },
format="json", format="json",
) )
from pprint import pprint
print("Response data")
pprint(resp.json())
self.assertEqual(resp.status_code, status.HTTP_200_OK) self.assertEqual(resp.status_code, status.HTTP_200_OK)
resp_data = resp.json()["custom_fields"] resp_data = resp.json()["custom_fields"]
@ -116,7 +118,7 @@ class TestCustomField(DirectoriesMixin, APITestCase):
resp_data, resp_data,
[ [
{"field": custom_field_string.id, "value": "test value"}, {"field": custom_field_string.id, "value": "test value"},
{"field": custom_field_date.id, "value": "2023-10-31"}, {"field": custom_field_date.id, "value": date_value.isoformat()},
{"field": custom_field_int.id, "value": 3}, {"field": custom_field_int.id, "value": 3},
{"field": custom_field_boolean.id, "value": True}, {"field": custom_field_boolean.id, "value": True},
{"field": custom_field_url.id, "value": "https://example.com"}, {"field": custom_field_url.id, "value": "https://example.com"},
@ -141,7 +143,6 @@ class TestCustomField(DirectoriesMixin, APITestCase):
) )
self.assertEqual(CustomFieldInstance.objects.count(), 0) self.assertEqual(CustomFieldInstance.objects.count(), 0)
self.assertEqual(CustomFieldShortText.objects.count(), 0)
resp = self.client.patch( resp = self.client.patch(
f"/api/documents/{doc.id}/", f"/api/documents/{doc.id}/",
@ -149,7 +150,7 @@ class TestCustomField(DirectoriesMixin, APITestCase):
"custom_fields": [ "custom_fields": [
{ {
"field": custom_field_string.id, "field": custom_field_string.id,
"value": "test value", "value_text": "test value",
}, },
], ],
}, },
@ -162,7 +163,6 @@ class TestCustomField(DirectoriesMixin, APITestCase):
self.assertEqual(doc.custom_fields.first().value, "test value") self.assertEqual(doc.custom_fields.first().value, "test value")
self.assertEqual(CustomFieldInstance.objects.count(), 1) self.assertEqual(CustomFieldInstance.objects.count(), 1)
self.assertEqual(CustomFieldShortText.objects.count(), 1)
resp = self.client.patch( resp = self.client.patch(
f"/api/documents/{doc.id}/", f"/api/documents/{doc.id}/",
@ -170,7 +170,7 @@ class TestCustomField(DirectoriesMixin, APITestCase):
"custom_fields": [ "custom_fields": [
{ {
"field": custom_field_string.id, "field": custom_field_string.id,
"value": "a new test value", "value_text": "a new test value",
}, },
], ],
}, },
@ -182,4 +182,91 @@ class TestCustomField(DirectoriesMixin, APITestCase):
self.assertEqual(doc.custom_fields.first().value, "a new test value") self.assertEqual(doc.custom_fields.first().value, "a new test value")
self.assertEqual(CustomFieldInstance.objects.count(), 1) self.assertEqual(CustomFieldInstance.objects.count(), 1)
self.assertEqual(CustomFieldShortText.objects.count(), 1)
def test_delete_custom_field_instance(self):
doc = Document.objects.create(
title="WOW",
content="the content",
checksum="123",
mime_type="application/pdf",
)
custom_field_string = CustomField.objects.create(
name="Test Custom Field String",
data_type=CustomField.FieldDataType.STRING,
)
custom_field_date = CustomField.objects.create(
name="Test Custom Field Date",
data_type=CustomField.FieldDataType.DATE,
)
date_value = date.today()
resp = self.client.patch(
f"/api/documents/{doc.id}/",
data={
"custom_fields": [
{
"field": custom_field_string.id,
"value_text": "a new test value",
},
{
"field": custom_field_date.id,
"value_date": date_value.isoformat(),
},
],
},
format="json",
)
self.assertEqual(resp.status_code, status.HTTP_200_OK)
self.assertEqual(CustomFieldInstance.objects.count(), 2)
self.assertEqual(len(doc.custom_fields.all()), 2)
resp = self.client.patch(
f"/api/documents/{doc.id}/",
data={
"custom_fields": [
{
"field": custom_field_date.id,
"value_date": date_value.isoformat(),
},
],
},
format="json",
)
self.assertEqual(resp.status_code, status.HTTP_200_OK)
self.assertEqual(CustomFieldInstance.objects.count(), 1)
self.assertEqual(Document.objects.count(), 1)
self.assertEqual(len(doc.custom_fields.all()), 1)
self.assertEqual(doc.custom_fields.first().value, date_value)
def test_custom_field_validation(self):
doc = Document.objects.create(
title="WOW",
content="the content",
checksum="123",
mime_type="application/pdf",
)
custom_field_string = CustomField.objects.create(
name="Test Custom Field String",
data_type=CustomField.FieldDataType.STRING,
)
resp = self.client.patch(
f"/api/documents/{doc.id}/",
data={
"custom_fields": [
{
"field": custom_field_string.id,
# Whoops, spelling
"value_test": "a new test value",
},
],
},
format="json",
)
from pprint import pprint
pprint(resp.json())
self.assertEqual(resp.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(CustomFieldInstance.objects.count(), 0)
self.assertEqual(len(doc.custom_fields.all()), 0)

View File

@ -153,7 +153,7 @@ class TestExportImport(DirectoriesMixin, FileSystemAssertsMixin, TestCase):
manifest = self._do_export(use_filename_format=use_filename_format) manifest = self._do_export(use_filename_format=use_filename_format)
self.assertEqual(len(manifest), 194) self.assertEqual(len(manifest), 169)
# dont include consumer or AnonymousUser users # dont include consumer or AnonymousUser users
self.assertEqual( self.assertEqual(
@ -247,7 +247,7 @@ class TestExportImport(DirectoriesMixin, FileSystemAssertsMixin, TestCase):
self.assertEqual(Document.objects.get(id=self.d4.id).title, "wow_dec") self.assertEqual(Document.objects.get(id=self.d4.id).title, "wow_dec")
self.assertEqual(GroupObjectPermission.objects.count(), 1) self.assertEqual(GroupObjectPermission.objects.count(), 1)
self.assertEqual(UserObjectPermission.objects.count(), 1) self.assertEqual(UserObjectPermission.objects.count(), 1)
self.assertEqual(Permission.objects.count(), 144) self.assertEqual(Permission.objects.count(), 124)
messages = check_sanity() messages = check_sanity()
# everything is alright after the test # everything is alright after the test
self.assertEqual(len(messages), 0) self.assertEqual(len(messages), 0)
@ -676,15 +676,15 @@ class TestExportImport(DirectoriesMixin, FileSystemAssertsMixin, TestCase):
os.path.join(self.dirs.media_dir, "documents"), os.path.join(self.dirs.media_dir, "documents"),
) )
self.assertEqual(ContentType.objects.count(), 36) self.assertEqual(ContentType.objects.count(), 31)
self.assertEqual(Permission.objects.count(), 144) self.assertEqual(Permission.objects.count(), 124)
manifest = self._do_export() manifest = self._do_export()
with paperless_environment(): with paperless_environment():
self.assertEqual( self.assertEqual(
len(list(filter(lambda e: e["model"] == "auth.permission", manifest))), len(list(filter(lambda e: e["model"] == "auth.permission", manifest))),
144, 124,
) )
# add 1 more to db to show objects are not re-created by import # add 1 more to db to show objects are not re-created by import
Permission.objects.create( Permission.objects.create(
@ -692,7 +692,7 @@ class TestExportImport(DirectoriesMixin, FileSystemAssertsMixin, TestCase):
codename="test_perm", codename="test_perm",
content_type_id=1, content_type_id=1,
) )
self.assertEqual(Permission.objects.count(), 145) self.assertEqual(Permission.objects.count(), 125)
# will cause an import error # will cause an import error
self.user.delete() self.user.delete()
@ -701,5 +701,5 @@ class TestExportImport(DirectoriesMixin, FileSystemAssertsMixin, TestCase):
with self.assertRaises(IntegrityError): with self.assertRaises(IntegrityError):
call_command("document_importer", "--no-progress-bar", self.target) call_command("document_importer", "--no-progress-bar", self.target)
self.assertEqual(ContentType.objects.count(), 36) self.assertEqual(ContentType.objects.count(), 31)
self.assertEqual(Permission.objects.count(), 145) self.assertEqual(Permission.objects.count(), 125)