Saving some more work on this, even though it will fail linting
This commit is contained in:
parent
3787f4f8fe
commit
63d6213272
1
Pipfile
1
Pipfile
@ -16,6 +16,7 @@ django-extensions = "*"
|
|||||||
django-filter = "~=23.3"
|
django-filter = "~=23.3"
|
||||||
djangorestframework = "~=3.14"
|
djangorestframework = "~=3.14"
|
||||||
djangorestframework-guardian = "*"
|
djangorestframework-guardian = "*"
|
||||||
|
drf-writable-nested = "*"
|
||||||
filelock = "*"
|
filelock = "*"
|
||||||
gunicorn = "*"
|
gunicorn = "*"
|
||||||
imap-tools = "*"
|
imap-tools = "*"
|
||||||
|
10
Pipfile.lock
generated
10
Pipfile.lock
generated
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"_meta": {
|
"_meta": {
|
||||||
"hash": {
|
"hash": {
|
||||||
"sha256": "7b4272de2042a346f3252ae20e7bbeee60c375381f59526caa35511a706d4977"
|
"sha256": "3c380d590439f008ec85f1d5821ed96b4ebd56fcee3f287e6e0a6f5923262229"
|
||||||
},
|
},
|
||||||
"pipfile-spec": 6,
|
"pipfile-spec": 6,
|
||||||
"requires": {},
|
"requires": {},
|
||||||
@ -522,6 +522,14 @@
|
|||||||
"index": "pypi",
|
"index": "pypi",
|
||||||
"version": "==0.3.0"
|
"version": "==0.3.0"
|
||||||
},
|
},
|
||||||
|
"drf-writable-nested": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:154c0381e8a3a477e0fd539d5e1caf8ff4c1097a9c0c0fe741d4858b11b0455b"
|
||||||
|
],
|
||||||
|
"index": "pypi",
|
||||||
|
"markers": "python_version >= '3.7'",
|
||||||
|
"version": "==0.7.0"
|
||||||
|
},
|
||||||
"exceptiongroup": {
|
"exceptiongroup": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9",
|
"sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9",
|
||||||
|
@ -1008,15 +1008,6 @@ class CustomFieldInstance(models.Model):
|
|||||||
return CustomFieldInteger
|
return CustomFieldInteger
|
||||||
raise NotImplementedError(self.field.data_type)
|
raise NotImplementedError(self.field.data_type)
|
||||||
|
|
||||||
def to_json(self) -> dict[str, str]:
|
|
||||||
return {
|
|
||||||
"id": self.id,
|
|
||||||
"created": self.created,
|
|
||||||
"type": self.field.data_type,
|
|
||||||
"name": self.field.name,
|
|
||||||
"data": self.value,
|
|
||||||
}
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_json(
|
def from_json(
|
||||||
document: Document,
|
document: Document,
|
||||||
|
@ -396,6 +396,9 @@ 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,
|
||||||
@ -411,21 +414,54 @@ class CustomFieldSerializer(serializers.ModelSerializer):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class CustomFieldInstanceSerializer(serializers.Serializer):
|
class CustomFieldOnUpdateSerializer(serializers.ModelSerializer):
|
||||||
field = CustomFieldSerializer(required=True)
|
id = serializers.PrimaryKeyRelatedField(queryset=CustomField.objects.all())
|
||||||
value = SerializerMethodField()
|
|
||||||
|
class Meta:
|
||||||
|
model = CustomField
|
||||||
|
fields = [
|
||||||
|
"id",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class CustomFieldInstanceSerializer(serializers.ModelSerializer):
|
||||||
|
field = serializers.PrimaryKeyRelatedField(queryset=CustomField.objects.all())
|
||||||
|
value = serializers.JSONField()
|
||||||
|
|
||||||
|
def create(self, validated_data):
|
||||||
|
print("hello from create")
|
||||||
|
from pprint import pprint
|
||||||
|
|
||||||
|
pprint(dict(validated_data))
|
||||||
|
document: Document = validated_data["document"]
|
||||||
|
custom_field: CustomField = validated_data["field"]
|
||||||
|
instance, _ = CustomFieldInstance.objects.get_or_create(
|
||||||
|
document=document, field=custom_field
|
||||||
|
)
|
||||||
|
instance_data_class = instance.field_type
|
||||||
|
_, _ = instance_data_class.objects.update_or_create(
|
||||||
|
parent=instance, defaults={"value": validated_data["value"]}
|
||||||
|
)
|
||||||
|
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:
|
||||||
fields = [
|
model = CustomFieldInstance
|
||||||
"field",
|
fields = ["value", "field"]
|
||||||
"value",
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class DocumentSerializer(OwnedObjectSerializer, DynamicFieldsModelSerializer):
|
class DocumentSerializer(
|
||||||
|
OwnedObjectSerializer, NestedUpdateMixin, DynamicFieldsModelSerializer
|
||||||
|
):
|
||||||
correspondent = CorrespondentField(allow_null=True)
|
correspondent = CorrespondentField(allow_null=True)
|
||||||
tags = TagsField(many=True)
|
tags = TagsField(many=True)
|
||||||
document_type = DocumentTypeField(allow_null=True)
|
document_type = DocumentTypeField(allow_null=True)
|
||||||
@ -459,29 +495,6 @@ class DocumentSerializer(OwnedObjectSerializer, DynamicFieldsModelSerializer):
|
|||||||
return doc
|
return doc
|
||||||
|
|
||||||
def update(self, instance: Document, validated_data):
|
def update(self, instance: Document, validated_data):
|
||||||
if "custom_fields" in validated_data:
|
|
||||||
custom_fields = validated_data.pop("custom_fields")
|
|
||||||
for index, field_data in enumerate(custom_fields):
|
|
||||||
# get field value from initial_data since its not on the model
|
|
||||||
initial_field_data = self.initial_data["custom_fields"][index]
|
|
||||||
CustomFieldInstance.from_json(
|
|
||||||
document=instance,
|
|
||||||
field=initial_field_data["field"],
|
|
||||||
value=initial_field_data["value"],
|
|
||||||
)
|
|
||||||
existing_fields = CustomFieldInstance.objects.filter(document=instance)
|
|
||||||
for existing_field in existing_fields:
|
|
||||||
if (
|
|
||||||
not len(
|
|
||||||
[
|
|
||||||
f
|
|
||||||
for f in self.initial_data["custom_fields"]
|
|
||||||
if f["field"]["id"] == existing_field.field.id
|
|
||||||
],
|
|
||||||
)
|
|
||||||
> 0
|
|
||||||
):
|
|
||||||
existing_field.delete()
|
|
||||||
if "created_date" in validated_data and "created" not in validated_data:
|
if "created_date" in validated_data and "created" not in validated_data:
|
||||||
new_datetime = datetime.datetime.combine(
|
new_datetime = datetime.datetime.combine(
|
||||||
validated_data.get("created_date"),
|
validated_data.get("created_date"),
|
||||||
|
@ -2,9 +2,10 @@ 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
|
from documents.models import CustomField, CustomFieldInstance, CustomFieldShortText
|
||||||
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):
|
||||||
@ -80,41 +81,105 @@ class TestCustomField(DirectoriesMixin, APITestCase):
|
|||||||
data={
|
data={
|
||||||
"custom_fields": [
|
"custom_fields": [
|
||||||
{
|
{
|
||||||
"field": {
|
"field": custom_field_string.id,
|
||||||
"id": custom_field_string.id,
|
|
||||||
},
|
|
||||||
"value": "test value",
|
"value": "test value",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"field": {
|
"field": custom_field_date.id,
|
||||||
"id": custom_field_date.id,
|
|
||||||
},
|
|
||||||
"value": "2023-10-31",
|
"value": "2023-10-31",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"field": {
|
"field": custom_field_int.id,
|
||||||
"id": custom_field_int.id,
|
"value": "3",
|
||||||
},
|
|
||||||
"value": 3,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"field": {
|
"field": custom_field_boolean.id,
|
||||||
"id": custom_field_boolean.id,
|
"value": "True",
|
||||||
},
|
|
||||||
"value": True,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"field": {
|
"field": custom_field_url.id,
|
||||||
"id": custom_field_url.id,
|
|
||||||
},
|
|
||||||
"value": "https://example.com",
|
"value": "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)
|
||||||
|
|
||||||
|
resp_data = resp.json()["custom_fields"]
|
||||||
|
|
||||||
|
self.assertCountEqual(
|
||||||
|
resp_data,
|
||||||
|
[
|
||||||
|
{"field": custom_field_string.id, "value": "test value"},
|
||||||
|
{"field": custom_field_date.id, "value": "2023-10-31"},
|
||||||
|
{"field": custom_field_int.id, "value": 3},
|
||||||
|
{"field": custom_field_boolean.id, "value": True},
|
||||||
|
{"field": custom_field_url.id, "value": "https://example.com"},
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
doc.refresh_from_db()
|
||||||
|
self.assertEqual(len(doc.custom_fields.all()), 5)
|
||||||
|
for custom_field in doc.custom_fields.all():
|
||||||
|
print(custom_field.value, type(custom_field.value))
|
||||||
|
|
||||||
|
def test_change_custom_field_instance_value(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,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(CustomFieldInstance.objects.count(), 0)
|
||||||
|
self.assertEqual(CustomFieldShortText.objects.count(), 0)
|
||||||
|
|
||||||
|
resp = self.client.patch(
|
||||||
|
f"/api/documents/{doc.id}/",
|
||||||
|
data={
|
||||||
|
"custom_fields": [
|
||||||
|
{
|
||||||
|
"field": custom_field_string.id,
|
||||||
|
"value": "test value",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
format="json",
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(resp.status_code, status.HTTP_200_OK)
|
||||||
|
|
||||||
|
pprint(resp.json())
|
||||||
|
|
||||||
|
self.assertEqual(doc.custom_fields.first().value, "test value")
|
||||||
|
self.assertEqual(CustomFieldInstance.objects.count(), 1)
|
||||||
|
self.assertEqual(CustomFieldShortText.objects.count(), 1)
|
||||||
|
|
||||||
|
resp = self.client.patch(
|
||||||
|
f"/api/documents/{doc.id}/",
|
||||||
|
data={
|
||||||
|
"custom_fields": [
|
||||||
|
{
|
||||||
|
"field": custom_field_string.id,
|
||||||
|
"value": "a new test value",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
format="json",
|
||||||
|
)
|
||||||
self.assertEqual(resp.status_code, status.HTTP_200_OK)
|
self.assertEqual(resp.status_code, status.HTTP_200_OK)
|
||||||
|
|
||||||
doc.refresh_from_db()
|
pprint(resp.json())
|
||||||
self.assertEqual(len(doc.custom_fields.all()), 5)
|
|
||||||
self.assertEqual(doc.custom_fields.first().value, "test value")
|
self.assertEqual(doc.custom_fields.first().value, "a new test value")
|
||||||
|
self.assertEqual(CustomFieldInstance.objects.count(), 1)
|
||||||
|
self.assertEqual(CustomFieldShortText.objects.count(), 1)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user