mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-09-16 21:55:37 -05:00
Enhancement: support custom field values with post document endpoint
This commit is contained in:
@@ -1682,6 +1682,12 @@ class PostDocumentSerializer(serializers.Serializer):
|
|||||||
required=False,
|
required=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
custom_fields_w_values = serializers.JSONField(
|
||||||
|
label="Custom fields with values",
|
||||||
|
write_only=True,
|
||||||
|
required=False,
|
||||||
|
)
|
||||||
|
|
||||||
def validate_document(self, document):
|
def validate_document(self, document):
|
||||||
document_data = document.file.read()
|
document_data = document.file.read()
|
||||||
mime_type = magic.from_buffer(document_data, mime=True)
|
mime_type = magic.from_buffer(document_data, mime=True)
|
||||||
@@ -1732,6 +1738,27 @@ class PostDocumentSerializer(serializers.Serializer):
|
|||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def validate_custom_fields_w_values(self, custom_fields_w_values):
|
||||||
|
if custom_fields_w_values:
|
||||||
|
custom_field_serializer = CustomFieldInstanceSerializer()
|
||||||
|
for field_id, value in custom_fields_w_values.items():
|
||||||
|
try:
|
||||||
|
field = CustomField.objects.get(id=field_id)
|
||||||
|
except CustomField.DoesNotExist:
|
||||||
|
raise serializers.ValidationError(
|
||||||
|
_("Custom field with id %(id)s does not exist")
|
||||||
|
% {
|
||||||
|
"id": field_id,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
# validate the value using the CustomFieldInstanceSerializer
|
||||||
|
custom_field_serializer.validate(
|
||||||
|
{
|
||||||
|
"field": field,
|
||||||
|
"value": value,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
def validate_created(self, created):
|
def validate_created(self, created):
|
||||||
# support datetime format for created for backwards compatibility
|
# support datetime format for created for backwards compatibility
|
||||||
if isinstance(created, datetime):
|
if isinstance(created, datetime):
|
||||||
|
@@ -1537,6 +1537,50 @@ class TestDocumentApi(DirectoriesMixin, DocumentConsumeDelayMixin, APITestCase):
|
|||||||
overrides.update(new_overrides)
|
overrides.update(new_overrides)
|
||||||
self.assertEqual(overrides.custom_fields, {cf.id: None, cf2.id: 123})
|
self.assertEqual(overrides.custom_fields, {cf.id: None, cf2.id: 123})
|
||||||
|
|
||||||
|
def test_upload_with_custom_field_values(self):
|
||||||
|
"""
|
||||||
|
GIVEN: A document with a source file
|
||||||
|
WHEN: Upload the document with custom fields and values
|
||||||
|
THEN: Metadata is set correctly
|
||||||
|
"""
|
||||||
|
self.consume_file_mock.return_value = celery.result.AsyncResult(
|
||||||
|
id=str(uuid.uuid4()),
|
||||||
|
)
|
||||||
|
|
||||||
|
cf_string = CustomField.objects.create(
|
||||||
|
name="stringfield",
|
||||||
|
data_type=CustomField.FieldDataType.STRING,
|
||||||
|
)
|
||||||
|
cf_int = CustomField.objects.create(
|
||||||
|
name="intfield",
|
||||||
|
data_type=CustomField.FieldDataType.INT,
|
||||||
|
)
|
||||||
|
|
||||||
|
with (Path(__file__).parent / "samples" / "simple.pdf").open("rb") as f:
|
||||||
|
response = self.client.post(
|
||||||
|
"/api/documents/post_document/",
|
||||||
|
{
|
||||||
|
"document": f,
|
||||||
|
"custom_fields_w_values": {
|
||||||
|
str(cf_string.id): "a string",
|
||||||
|
str(cf_int.id): 123,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||||
|
|
||||||
|
self.consume_file_mock.assert_called_once()
|
||||||
|
|
||||||
|
input_doc, overrides = self.get_last_consume_delay_call_args()
|
||||||
|
|
||||||
|
self.assertEqual(input_doc.original_file.name, "simple.pdf")
|
||||||
|
self.assertEqual(overrides.filename, "simple.pdf")
|
||||||
|
self.assertEqual(
|
||||||
|
overrides.custom_fields,
|
||||||
|
{cf_string.id: "a string", cf_int.id: 123},
|
||||||
|
)
|
||||||
|
|
||||||
def test_upload_with_webui_source(self):
|
def test_upload_with_webui_source(self):
|
||||||
"""
|
"""
|
||||||
GIVEN: A document with a source file
|
GIVEN: A document with a source file
|
||||||
|
@@ -1498,6 +1498,9 @@ class PostDocumentView(GenericAPIView):
|
|||||||
created = serializer.validated_data.get("created")
|
created = serializer.validated_data.get("created")
|
||||||
archive_serial_number = serializer.validated_data.get("archive_serial_number")
|
archive_serial_number = serializer.validated_data.get("archive_serial_number")
|
||||||
custom_field_ids = serializer.validated_data.get("custom_fields")
|
custom_field_ids = serializer.validated_data.get("custom_fields")
|
||||||
|
custom_fields_w_values = serializer.validated_data.get(
|
||||||
|
"custom_fields_w_values",
|
||||||
|
)
|
||||||
from_webui = serializer.validated_data.get("from_webui")
|
from_webui = serializer.validated_data.get("from_webui")
|
||||||
|
|
||||||
t = int(mktime(datetime.now().timetuple()))
|
t = int(mktime(datetime.now().timetuple()))
|
||||||
@@ -1516,6 +1519,13 @@ class PostDocumentView(GenericAPIView):
|
|||||||
source=DocumentSource.WebUI if from_webui else DocumentSource.ApiUpload,
|
source=DocumentSource.WebUI if from_webui else DocumentSource.ApiUpload,
|
||||||
original_file=temp_file_path,
|
original_file=temp_file_path,
|
||||||
)
|
)
|
||||||
|
custom_fields = None
|
||||||
|
if custom_fields_w_values:
|
||||||
|
custom_fields = {
|
||||||
|
cf_id: value for cf_id, value in custom_fields_w_values.items()
|
||||||
|
}
|
||||||
|
elif custom_field_ids:
|
||||||
|
custom_fields = {cf_id: None for cf_id in custom_field_ids}
|
||||||
input_doc_overrides = DocumentMetadataOverrides(
|
input_doc_overrides = DocumentMetadataOverrides(
|
||||||
filename=doc_name,
|
filename=doc_name,
|
||||||
title=title,
|
title=title,
|
||||||
@@ -1526,10 +1536,7 @@ class PostDocumentView(GenericAPIView):
|
|||||||
created=created,
|
created=created,
|
||||||
asn=archive_serial_number,
|
asn=archive_serial_number,
|
||||||
owner_id=request.user.id,
|
owner_id=request.user.id,
|
||||||
# TODO: set values
|
custom_fields=custom_fields,
|
||||||
custom_fields={cf_id: None for cf_id in custom_field_ids}
|
|
||||||
if custom_field_ids
|
|
||||||
else None,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
async_task = consume_file.delay(
|
async_task = consume_file.delay(
|
||||||
|
Reference in New Issue
Block a user