Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(relations): integrate RelationFormHX into RelationForm #1260

Merged
merged 1 commit into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 19 additions & 31 deletions apis_core/relations/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ class RelationForm(GenericModelForm):
Relations have generic relations to subj and obj, but we
hide those ForeignKey form fields and instead show
autocomplete choices fields.
In addition, one can pass a hx_post_route argument to the
form to make the form set the `hx-post` attribute to the
given value.
We also pass a `reverse` boolean, wich gets passed on
to the htmx POST endpoint using url parameters (the endpoint
can then select the success_url based on the `reverse` state).
"""

class Meta:
Expand Down Expand Up @@ -80,6 +86,8 @@ def __init__(self, *args, **kwargs):
generic apis_entities autocomplete with the correct parameters.
"""

self.is_reverse = kwargs.pop("reverse", False)
hx_post_route = kwargs.pop("hx_post_route", False)
super().__init__(*args, **kwargs)
subj_content_type = kwargs["initial"].get("subj_content_type", None)
subj_object_id = kwargs["initial"].get("subj_object_id", None)
Expand Down Expand Up @@ -133,6 +141,16 @@ def __init__(self, *args, **kwargs):
self.helper.form_id = f"relation_{model_ct.model}_form"
self.helper.add_input(Submit("submit", "Submit"))

if hx_post_route:
urlparams = kwargs["initial"]
urlparams["reverse"] = self.is_reverse
urlparams = {k: v for k, v in urlparams.items() if v}
self.helper.attrs = {
"hx-post": hx_post_route + "?" + urlencode(urlparams),
"hx-swap": "outerHTML",
"hx-target": f"#{self.helper.form_id}",
}

def clean(self) -> dict:
"""
We check if there are `subj` or `obj` fields in the form data
Expand All @@ -156,39 +174,9 @@ def clean(self) -> dict:
del cleaned_data["obj"]
return cleaned_data


class RelationFormHX(RelationForm):
"""
A Relation form that sets a hx-post attribute to the
form to make the htmx POST request use another route.
We also pass a `reverse` boolean, wich gets passed on
to the POST endpoint using url parameters. The POST
endpoint then calculates the success_url based on the
`reverse` state.
"""

def __init__(self, *args, **kwargs):
self.is_reverse = kwargs.pop("reverse", False)
super().__init__(*args, **kwargs)
urlparams = kwargs["initial"]
urlparams["reverse"] = self.is_reverse
urlparams = {k: v for k, v in urlparams.items() if v}
relation_content_type = ContentType.objects.get_for_model(self.Meta.model)
hx_post = (
reverse(
"apis_core:relations:create_relation_form", args=[relation_content_type]
)
+ "?"
+ urlencode(urlparams)
)
self.helper.attrs = {
"hx-post": hx_post,
"hx-swap": "outerHTML",
"hx-target": f"#{self.helper.form_id}",
}

@property
def relation_name(self) -> str:
"""A helper method to access the correct name of the relation"""
if self.is_reverse:
return self._meta.model.reverse_name
return self._meta.model.name
9 changes: 4 additions & 5 deletions apis_core/relations/views.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
from django.contrib.contenttypes.models import ContentType
from django.forms import modelform_factory
from django.shortcuts import get_object_or_404
from django.urls import reverse
from django.views.generic.base import TemplateView

from apis_core.generic.views import Create
from apis_core.relations.forms import RelationFormHX
from apis_core.relations.templatetags.relations import (
possible_relation_types_from,
relations_from,
Expand Down Expand Up @@ -42,6 +40,10 @@ def get(self, *args, **kwargs):
def get_form_kwargs(self, *args, **kwargs) -> dict:
kwargs = super().get_form_kwargs(*args, **kwargs)
kwargs["reverse"] = self.reverse
content_type = ContentType.objects.get_for_model(self.model)
kwargs["hx_post_route"] = reverse(
"apis_core:relations:create_relation_form", args=[content_type]
)
return kwargs

def get_success_url(self) -> str:
Expand All @@ -58,9 +60,6 @@ def get_success_url(self) -> str:
]
return reverse("apis_core:relations:list_relations", args=args)

def get_form_class(self, *args, **kwargs):
return modelform_factory(self.model, RelationFormHX)


class ListRelations(TemplateView):
template_name = "relations/list_relations.html"
Expand Down
Loading