Skip to content

Commit

Permalink
✨ [open-zaak/open-notificaties#156] Support nested fields on kanaal k…
Browse files Browse the repository at this point in the history
…enmerken

and support kenmerken for django-loose-fk fields
  • Loading branch information
stevenbal committed Sep 19, 2024
1 parent 7abd32e commit d6e0bfc
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 12 deletions.
56 changes: 45 additions & 11 deletions notifications_api_common/kanalen.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,41 @@
Provide notifications kanaal/exchange classes.
"""
from collections import defaultdict
from typing import Dict, Tuple
from typing import Dict, cast

from django.core.exceptions import FieldDoesNotExist, ImproperlyConfigured
from django.db.models import Model
from django.db.models.base import ModelBase
from django.db.models import Field, Model

from glom import glom
from rest_framework.request import Request
from vng_api_common.tests import reverse

KANAAL_REGISTRY = set()


def get_field(model: Model, field: str) -> Field:
"""
Function to retrieve a field from a Model, can also be passed a path to a field
(e.g. `zaaktype.catalogus`)
"""
if "." in field:
model_field = None
bits = field.split(".")
for i, part in enumerate(bits):
model_field = model._meta.get_field(part)
if fk_field := getattr(model_field, "fk_field", None):
model_field = model._meta.get_field(fk_field)
if i != len(bits):
model = cast(Model, model_field.related_model)
assert model_field, "Could not find field on model"
return model_field
return model._meta.get_field(field)


class Kanaal:
def __init__(self, label: str, main_resource: ModelBase, kenmerken: Tuple = None):
def __init__(
self, label: str, main_resource: Model, kenmerken: tuple | None = None
):
self.label = label
self.main_resource = main_resource

Expand All @@ -22,7 +46,7 @@ def __init__(self, label: str, main_resource: ModelBase, kenmerken: Tuple = None
self.kenmerken = kenmerken or ()
for kenmerk in self.kenmerken:
try:
self.main_resource._meta.get_field(kenmerk)
get_field(self.main_resource, kenmerk)
except FieldDoesNotExist as exc:
raise ImproperlyConfigured(
f"Kenmerk '{kenmerk}' does not exist on the model {main_resource}"
Expand All @@ -38,12 +62,22 @@ def __repr__(self):
self.main_resource,
)

def get_kenmerken(self, obj: Model, data: Dict = None) -> Dict:
def get_kenmerken(
self, obj: Model, data: dict | None = None, request: Request | None = None
) -> Dict:
data = data or {}
return {
kenmerk: data.get(kenmerk, getattr(obj, kenmerk))
for kenmerk in self.kenmerken
}
kenmerken = {}
for kenmerk in self.kenmerken:
value = data.get(kenmerk, glom(obj, kenmerk, default=""))
if isinstance(value, Model):
if _loose_fk_data := getattr(value, "_loose_fk_data", None):
value = _loose_fk_data["url"]
else:
value = reverse(value)
if request:
value = request.build_absolute_uri(value)
kenmerken[kenmerk] = value
return kenmerken

def get_usage(self):
return self.usage.items()
Expand All @@ -54,7 +88,7 @@ def description(self):
kenmerken = [
kenmerk_template.format(
kenmerk=kenmerk,
help_text=self.main_resource._meta.get_field(kenmerk).help_text,
help_text=get_field(self.main_resource, kenmerk).help_text,
)
for kenmerk in self.kenmerken
]
Expand Down
4 changes: 3 additions & 1 deletion notifications_api_common/viewsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,9 @@ def construct_message(self, data: dict, instance: models.Model = None) -> dict:
"actie": self.action,
"aanmaakdatum": timezone.now(),
# each channel knows which kenmerken it has, so delegate this
"kenmerken": kanaal.get_kenmerken(main_object, main_object_data),
"kenmerken": kanaal.get_kenmerken(
main_object, main_object_data, request=self.request
),
}

# let the serializer & render machinery shape the data the way it
Expand Down
1 change: 1 addition & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ install_requires =
djangorestframework>=3.12.0
celery
djangorestframework_camel_case>=1.2.0
glom
gemma-zds-client>=0.15.0
zgw-consumers
tests_require =
Expand Down

0 comments on commit d6e0bfc

Please sign in to comment.