# External ID support for serializer
* adds support for sending "external_identifier" in POST and PUT requests * if an external identifier already exists on the database, the client will be informed that the entry should not be POSTed again but rather an update via PUT should be performed
This commit is contained in:
@@ -113,7 +113,9 @@ class CompensationAPISerializerV1(AbstractModelAPISerializerV1, AbstractCompensa
|
|||||||
obj = self._initialize_objects(json_model, user)
|
obj = self._initialize_objects(json_model, user)
|
||||||
|
|
||||||
# Fill in data to objects
|
# Fill in data to objects
|
||||||
properties = json_model["properties"]
|
properties = json_model.get("properties", None)
|
||||||
|
if not properties:
|
||||||
|
raise AssertionError("No 'properties' found in payload!")
|
||||||
obj.identifier = obj.generate_new_identifier()
|
obj.identifier = obj.generate_new_identifier()
|
||||||
obj.title = properties["title"]
|
obj.title = properties["title"]
|
||||||
obj.is_cef = properties["is_cef"]
|
obj.is_cef = properties["is_cef"]
|
||||||
@@ -129,6 +131,7 @@ class CompensationAPISerializerV1(AbstractModelAPISerializerV1, AbstractCompensa
|
|||||||
obj = self._set_compensation_states(obj, properties["after_states"], obj.after_states)
|
obj = self._set_compensation_states(obj, properties["after_states"], obj.after_states)
|
||||||
obj = self._set_deadlines(obj, properties["deadlines"])
|
obj = self._set_deadlines(obj, properties["deadlines"])
|
||||||
|
|
||||||
|
self._set_external_identifier(obj, properties.get("external_identifier", None))
|
||||||
obj.log.add(obj.created)
|
obj.log.add(obj.created)
|
||||||
|
|
||||||
celery_update_parcels.delay(obj.geometry.id)
|
celery_update_parcels.delay(obj.geometry.id)
|
||||||
@@ -153,6 +156,10 @@ class CompensationAPISerializerV1(AbstractModelAPISerializerV1, AbstractCompensa
|
|||||||
|
|
||||||
# Fill in data to objects
|
# Fill in data to objects
|
||||||
properties = json_model["properties"]
|
properties = json_model["properties"]
|
||||||
|
|
||||||
|
external_identifier = properties.get("external_identifier", None)
|
||||||
|
self._check_external_identifier_on_entry_creation(external_identifier)
|
||||||
|
|
||||||
obj.title = properties["title"]
|
obj.title = properties["title"]
|
||||||
obj.is_cef = properties["is_cef"]
|
obj.is_cef = properties["is_cef"]
|
||||||
obj.is_coherence_keeping = properties["is_coherence_keeping"]
|
obj.is_coherence_keeping = properties["is_coherence_keeping"]
|
||||||
@@ -170,6 +177,7 @@ class CompensationAPISerializerV1(AbstractModelAPISerializerV1, AbstractCompensa
|
|||||||
obj = self._set_compensation_states(obj, properties["after_states"], obj.after_states)
|
obj = self._set_compensation_states(obj, properties["after_states"], obj.after_states)
|
||||||
obj = self._set_deadlines(obj, properties["deadlines"])
|
obj = self._set_deadlines(obj, properties["deadlines"])
|
||||||
|
|
||||||
|
self._set_external_identifier(obj, properties.get("external_identifier", None))
|
||||||
obj.log.add(update_action)
|
obj.log.add(update_action)
|
||||||
|
|
||||||
celery_update_parcels.delay(obj.geometry.id)
|
celery_update_parcels.delay(obj.geometry.id)
|
||||||
|
|||||||
@@ -121,7 +121,9 @@ class EcoAccountAPISerializerV1(AbstractModelAPISerializerV1,
|
|||||||
obj = self._initialize_objects(json_model, user)
|
obj = self._initialize_objects(json_model, user)
|
||||||
|
|
||||||
# Fill in data to objects
|
# Fill in data to objects
|
||||||
properties = json_model["properties"]
|
properties = json_model.get("properties", None)
|
||||||
|
if not properties:
|
||||||
|
raise AssertionError("No 'properties' found in payload!")
|
||||||
obj.identifier = obj.generate_new_identifier()
|
obj.identifier = obj.generate_new_identifier()
|
||||||
obj.title = properties["title"]
|
obj.title = properties["title"]
|
||||||
obj.is_pik = properties.get("is_pik", False)
|
obj.is_pik = properties.get("is_pik", False)
|
||||||
@@ -147,6 +149,7 @@ class EcoAccountAPISerializerV1(AbstractModelAPISerializerV1,
|
|||||||
obj = self._set_compensation_states(obj, properties["after_states"], obj.after_states)
|
obj = self._set_compensation_states(obj, properties["after_states"], obj.after_states)
|
||||||
obj = self._set_deadlines(obj, properties["deadlines"])
|
obj = self._set_deadlines(obj, properties["deadlines"])
|
||||||
|
|
||||||
|
self._set_external_identifier(obj, properties.get("external_identifier", None))
|
||||||
obj.log.add(obj.created)
|
obj.log.add(obj.created)
|
||||||
obj.users.add(user)
|
obj.users.add(user)
|
||||||
|
|
||||||
@@ -172,6 +175,10 @@ class EcoAccountAPISerializerV1(AbstractModelAPISerializerV1,
|
|||||||
|
|
||||||
# Fill in data to objects
|
# Fill in data to objects
|
||||||
properties = json_model["properties"]
|
properties = json_model["properties"]
|
||||||
|
|
||||||
|
external_identifier = properties.get("external_identifier", None)
|
||||||
|
self._check_external_identifier_on_entry_creation(external_identifier)
|
||||||
|
|
||||||
obj.title = properties["title"]
|
obj.title = properties["title"]
|
||||||
obj.is_pik = properties.get("is_pik", False)
|
obj.is_pik = properties.get("is_pik", False)
|
||||||
obj.deductable_surface = float(properties["deductable_surface"])
|
obj.deductable_surface = float(properties["deductable_surface"])
|
||||||
@@ -192,6 +199,7 @@ class EcoAccountAPISerializerV1(AbstractModelAPISerializerV1,
|
|||||||
obj = self._set_compensation_states(obj, properties["after_states"], obj.after_states)
|
obj = self._set_compensation_states(obj, properties["after_states"], obj.after_states)
|
||||||
obj = self._set_deadlines(obj, properties["deadlines"])
|
obj = self._set_deadlines(obj, properties["deadlines"])
|
||||||
|
|
||||||
|
self._set_external_identifier(obj, external_identifier)
|
||||||
obj.log.add(update_action)
|
obj.log.add(update_action)
|
||||||
|
|
||||||
celery_update_parcels.delay(obj.geometry.id)
|
celery_update_parcels.delay(obj.geometry.id)
|
||||||
|
|||||||
@@ -104,6 +104,10 @@ class EmaAPISerializerV1(AbstractModelAPISerializerV1, AbstractCompensationAPISe
|
|||||||
|
|
||||||
# Fill in data to objects
|
# Fill in data to objects
|
||||||
properties = json_model["properties"]
|
properties = json_model["properties"]
|
||||||
|
|
||||||
|
external_identifier = properties.get("external_identifier", None)
|
||||||
|
self._check_external_identifier_on_entry_creation(external_identifier)
|
||||||
|
|
||||||
obj.identifier = obj.generate_new_identifier()
|
obj.identifier = obj.generate_new_identifier()
|
||||||
obj.title = properties["title"]
|
obj.title = properties["title"]
|
||||||
obj.is_pik = properties.get("is_pik", False)
|
obj.is_pik = properties.get("is_pik", False)
|
||||||
@@ -119,6 +123,7 @@ class EmaAPISerializerV1(AbstractModelAPISerializerV1, AbstractCompensationAPISe
|
|||||||
obj = self._set_compensation_states(obj, properties["after_states"], obj.after_states)
|
obj = self._set_compensation_states(obj, properties["after_states"], obj.after_states)
|
||||||
obj = self._set_deadlines(obj, properties["deadlines"])
|
obj = self._set_deadlines(obj, properties["deadlines"])
|
||||||
|
|
||||||
|
self._set_external_identifier(obj, external_identifier)
|
||||||
obj.log.add(obj.created)
|
obj.log.add(obj.created)
|
||||||
obj.users.add(user)
|
obj.users.add(user)
|
||||||
|
|
||||||
@@ -161,6 +166,7 @@ class EmaAPISerializerV1(AbstractModelAPISerializerV1, AbstractCompensationAPISe
|
|||||||
obj = self._set_compensation_states(obj, properties["after_states"], obj.after_states)
|
obj = self._set_compensation_states(obj, properties["after_states"], obj.after_states)
|
||||||
obj = self._set_deadlines(obj, properties["deadlines"])
|
obj = self._set_deadlines(obj, properties["deadlines"])
|
||||||
|
|
||||||
|
self._set_external_identifier(obj, properties.get("external_identifier", None))
|
||||||
obj.log.add(update_action)
|
obj.log.add(update_action)
|
||||||
|
|
||||||
celery_update_parcels.delay(obj.geometry.id)
|
celery_update_parcels.delay(obj.geometry.id)
|
||||||
|
|||||||
@@ -150,10 +150,14 @@ class InterventionAPISerializerV1(AbstractModelAPISerializerV1,
|
|||||||
|
|
||||||
# Fill in data to objects
|
# Fill in data to objects
|
||||||
properties = json_model["properties"]
|
properties = json_model["properties"]
|
||||||
|
|
||||||
|
external_identifier = properties.get("external_identifier", None)
|
||||||
|
self._check_external_identifier_on_entry_creation(external_identifier)
|
||||||
|
|
||||||
obj.identifier = obj.generate_new_identifier()
|
obj.identifier = obj.generate_new_identifier()
|
||||||
obj.title = properties["title"]
|
obj.title = properties.get("title", None)
|
||||||
self._set_responsibility(obj, properties["responsible"])
|
self._set_responsibility(obj, properties.get("responsible", None))
|
||||||
self._set_legal(obj, properties["legal"])
|
self._set_legal(obj, properties.get("legal", None))
|
||||||
|
|
||||||
obj.responsible.handler.save()
|
obj.responsible.handler.save()
|
||||||
obj.responsible.save()
|
obj.responsible.save()
|
||||||
@@ -161,6 +165,7 @@ class InterventionAPISerializerV1(AbstractModelAPISerializerV1,
|
|||||||
obj.legal.save()
|
obj.legal.save()
|
||||||
obj.save()
|
obj.save()
|
||||||
|
|
||||||
|
self._set_external_identifier(obj, external_identifier)
|
||||||
obj.users.add(user)
|
obj.users.add(user)
|
||||||
obj.log.add(obj.created)
|
obj.log.add(obj.created)
|
||||||
|
|
||||||
@@ -186,7 +191,7 @@ class InterventionAPISerializerV1(AbstractModelAPISerializerV1,
|
|||||||
|
|
||||||
# Fill in data to objects
|
# Fill in data to objects
|
||||||
properties = json_model["properties"]
|
properties = json_model["properties"]
|
||||||
obj.title = properties["title"]
|
obj.title = properties.get("title")
|
||||||
self._set_responsibility(obj, properties.get("responsible", None))
|
self._set_responsibility(obj, properties.get("responsible", None))
|
||||||
self._set_legal(obj, properties.get("legal", None))
|
self._set_legal(obj, properties.get("legal", None))
|
||||||
self._set_payments(obj, properties.get("payments", None))
|
self._set_payments(obj, properties.get("payments", None))
|
||||||
@@ -199,6 +204,7 @@ class InterventionAPISerializerV1(AbstractModelAPISerializerV1,
|
|||||||
obj.legal.save()
|
obj.legal.save()
|
||||||
obj.save()
|
obj.save()
|
||||||
|
|
||||||
|
self._set_external_identifier(obj, properties.get("external_identifier", None))
|
||||||
obj.mark_as_edited(user, edit_comment="API update")
|
obj.mark_as_edited(user, edit_comment="API update")
|
||||||
obj.send_data_to_egon()
|
obj.send_data_to_egon()
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ from django.contrib.gis.geos import MultiPolygon
|
|||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
from django.db.models import QuerySet
|
from django.db.models import QuerySet
|
||||||
|
|
||||||
|
from api.models import ExternalIdentifier
|
||||||
from api.utils.serializer.serializer import AbstractModelAPISerializer
|
from api.utils.serializer.serializer import AbstractModelAPISerializer
|
||||||
from codelist.models import KonovaCode
|
from codelist.models import KonovaCode
|
||||||
from codelist.settings import CODELIST_COMPENSATION_ACTION_ID, CODELIST_BIOTOPES_ID, CODELIST_PROCESS_TYPE_ID, \
|
from codelist.settings import CODELIST_COMPENSATION_ACTION_ID, CODELIST_BIOTOPES_ID, CODELIST_PROCESS_TYPE_ID, \
|
||||||
@@ -137,6 +138,63 @@ class AbstractModelAPISerializerV1(AbstractModelAPISerializer):
|
|||||||
success = entry.deleted is not None
|
success = entry.deleted is not None
|
||||||
return success
|
return success
|
||||||
|
|
||||||
|
def _set_external_identifier(self, obj, external_identifier):
|
||||||
|
""" If an external identifier was provided in the payload, we set it
|
||||||
|
in the database
|
||||||
|
|
||||||
|
Args:
|
||||||
|
obj (BaseObject): The already processed konova object (EIV, KOM, ...)
|
||||||
|
external_identifier (any): The external identifier taken from the payload
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
"""
|
||||||
|
if external_identifier is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
ext_id_obj = ExternalIdentifier.objects.get_or_create(
|
||||||
|
internal_id=obj.id,
|
||||||
|
external_id=external_identifier
|
||||||
|
)[0]
|
||||||
|
if not ext_id_obj.created:
|
||||||
|
ext_id_obj.created = obj.created
|
||||||
|
ext_id_obj.save()
|
||||||
|
|
||||||
|
return ext_id_obj
|
||||||
|
|
||||||
|
def _get_external_identifier(self, external_identifier):
|
||||||
|
""" Checks whether a linkage based on an external identifier already exists and returns it if so.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
external_identifier (any): The external identifier according to payload
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
ExternalIdentifier | None
|
||||||
|
"""
|
||||||
|
if external_identifier:
|
||||||
|
try:
|
||||||
|
obj = ExternalIdentifier.objects.get(external_id=external_identifier)
|
||||||
|
return obj
|
||||||
|
except ObjectDoesNotExist:
|
||||||
|
pass
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _check_external_identifier_on_entry_creation(self, external_identifier):
|
||||||
|
""" Special check for POST processing:
|
||||||
|
Checks whether an external identifier already exists on the database. This hints that
|
||||||
|
the entry already has been created in the past. Instead of POST, the PUT method shall be used
|
||||||
|
to avoid creating duplicates.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
external_identifier (any): The external identifier according to payload
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
"""
|
||||||
|
persisted_external_identifier = self._get_external_identifier(external_identifier)
|
||||||
|
if persisted_external_identifier:
|
||||||
|
raise AssertionError(f"{external_identifier} has already been initially created! Use PUT for updates!")
|
||||||
|
|
||||||
|
|
||||||
class DeductableAPISerializerV1Mixin:
|
class DeductableAPISerializerV1Mixin:
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|||||||
Reference in New Issue
Block a user