# NewIntervention view

* introduces BaseFormView and BaseNewSpatialLocatedObjectFormView
* refactors new intervention view from function to class
This commit is contained in:
mpeltriaux 2025-10-19 12:37:13 +02:00
parent a9b402862b
commit d03b714fb5
4 changed files with 132 additions and 66 deletions

View File

@ -14,8 +14,8 @@ from intervention.views.deduction import NewInterventionDeductionView, EditInter
RemoveInterventionDeductionView
from intervention.views.document import NewInterventionDocumentView, GetInterventionDocumentView, \
RemoveInterventionDocumentView, EditInterventionDocumentView
from intervention.views.intervention import new_view, edit_view, remove_view, \
InterventionIndexView, InterventionIdentifierGeneratorView, InterventionDetailView
from intervention.views.intervention import edit_view, remove_view, \
InterventionIndexView, InterventionIdentifierGeneratorView, InterventionDetailView, NewInterventionFormView
from intervention.views.log import InterventionLogView
from intervention.views.record import InterventionRecordView
from intervention.views.report import InterventionReportView
@ -27,7 +27,7 @@ from intervention.views.share import InterventionShareFormView, InterventionShar
app_name = "intervention"
urlpatterns = [
path("", InterventionIndexView.as_view(), name="index"),
path('new/', new_view, name='new'),
path('new/', NewInterventionFormView.as_view(), name='new'),
path('new/id', InterventionIdentifierGeneratorView.as_view(), name='new-id'),
path('<id>', InterventionDetailView.as_view(), name='detail'),
path('<id>/log', InterventionLogView.as_view(), name='log'),

View File

@ -8,7 +8,7 @@ Created on: 19.08.22
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import JsonResponse, HttpRequest
from django.http import HttpRequest
from django.shortcuts import get_object_or_404, render, redirect
from django.urls import reverse
from django.utils.translation import gettext_lazy as _
@ -17,16 +17,13 @@ from intervention.forms.intervention import EditInterventionForm, NewInterventio
from intervention.models import Intervention
from intervention.tables import InterventionTable
from konova.contexts import BaseContext
from konova.decorators import default_group_required, shared_access_required, any_group_check, login_required_modal, \
uuid_required
from konova.decorators import default_group_required, shared_access_required, login_required_modal
from konova.forms import SimpleGeomForm
from konova.forms.modals import RemoveModalForm
from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
from konova.utils.message_templates import DATA_CHECKED_PREVIOUSLY_TEMPLATE, RECORDED_BLOCKS_EDIT, \
CHECK_STATE_RESET, FORM_INVALID, IDENTIFIER_REPLACED, DO_NOT_FORGET_TO_SHARE, GEOMETRY_SIMPLIFIED, \
GEOMETRIES_IGNORED_TEMPLATE
from konova.views.base import BaseIndexView, BaseIdentifierGeneratorView
CHECK_STATE_RESET, FORM_INVALID, GEOMETRY_SIMPLIFIED, GEOMETRIES_IGNORED_TEMPLATE
from konova.views.base import BaseIndexView, BaseIdentifierGeneratorView, BaseNewSpatialLocatedObjectFormView
from konova.views.detail import BaseDetailView
@ -45,60 +42,12 @@ class InterventionIndexView(LoginRequiredMixin, BaseIndexView):
return qs
@login_required
@default_group_required
def new_view(request: HttpRequest):
"""
Renders a view for a new intervention creation
Args:
request (HttpRequest): The incoming request
Returns:
"""
template = "intervention/form/view.html"
data_form = NewInterventionForm(request.POST or None)
geom_form = SimpleGeomForm(request.POST or None, read_only=False)
if request.method == "POST":
if data_form.is_valid() and geom_form.is_valid():
generated_identifier = data_form.cleaned_data.get("identifier", None)
intervention = data_form.save(request.user, geom_form)
if generated_identifier != intervention.identifier:
messages.info(
request,
IDENTIFIER_REPLACED.format(
generated_identifier,
intervention.identifier
)
)
messages.success(request, _("Intervention {} added").format(intervention.identifier))
if geom_form.has_geometry_simplified():
messages.info(
request,
GEOMETRY_SIMPLIFIED
)
num_ignored_geometries = geom_form.get_num_geometries_ignored()
if num_ignored_geometries > 0:
messages.info(
request,
GEOMETRIES_IGNORED_TEMPLATE.format(num_ignored_geometries)
)
return redirect("intervention:detail", id=intervention.id)
else:
messages.error(request, FORM_INVALID, extra_tags="danger",)
else:
# For clarification: nothing in this case
pass
context = {
"form": data_form,
"geom_form": geom_form,
TAB_TITLE_IDENTIFIER: _("New intervention"),
}
context = BaseContext(request, context).context
return render(request, template, context)
class NewInterventionFormView(BaseNewSpatialLocatedObjectFormView):
_MODEL_CLS = Intervention
_FORM_CLS = NewInterventionForm
_TEMPLATE = "intervention/form/view.html"
_REDIRECT_URL = "intervention:detail"
_TAB_TITLE = _("New intervention")
class InterventionIdentifierGeneratorView(LoginRequiredMixin, BaseIdentifierGeneratorView):

View File

@ -25,6 +25,7 @@ class BaseForm(forms.Form):
cancel_redirect = None
form_caption = None
instance = None # The data holding model object
user = None # The performing user
request = None
form_attrs = {} # Holds additional attributes, that can be used in the template
has_required_fields = False # Automatically set. Triggers hint rendering in templates
@ -33,6 +34,7 @@ class BaseForm(forms.Form):
def __init__(self, *args, **kwargs):
self.instance = kwargs.pop("instance", None)
self.user = kwargs.pop("user", None)
super().__init__(*args, **kwargs)
if self.request is not None:
self.user = self.request.user

View File

@ -6,15 +6,19 @@ Created on: 15.10.25
from abc import abstractmethod
from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpRequest, JsonResponse
from django.shortcuts import render, redirect
from django.shortcuts import render, redirect, get_object_or_404
from django.urls import reverse
from django.views import View
from django.utils.translation import gettext_lazy as _
from konova.contexts import BaseContext
from konova.forms import BaseForm, SimpleGeomForm
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
from konova.utils.general import check_user_is_in_any_group
from konova.utils.message_templates import MISSING_GROUP_PERMISSION, DATA_UNSHARED
from konova.utils.message_templates import MISSING_GROUP_PERMISSION, DATA_UNSHARED, IDENTIFIER_REPLACED, \
GEOMETRY_SIMPLIFIED, GEOMETRIES_IGNORED_TEMPLATE
class BaseView(View):
@ -139,3 +143,114 @@ class BaseIdentifierGeneratorView(BaseView):
def _user_has_shared_access(self, user, **kwargs):
# No specific constraints for shared access
return True
class BaseFormView(BaseView):
_MODEL_CLS = None
_FORM_CLS = None
class Meta:
abstract = True
def _get_specific_context_data(self, **kwargs):
return {}
class BaseNewSpatialLocatedObjectFormView(LoginRequiredMixin, BaseFormView):
_GEOMETRY_FORM_CLS = SimpleGeomForm
def _user_has_permission(self, user):
# User has to have default privilege to call this endpoint
return user.is_default_user()
def _user_has_shared_access(self, user, **kwargs):
# There is no shared access control since nothing exists yet
return True
def get(self, request: HttpRequest):
form: BaseForm = self._FORM_CLS(None, user=request.user)
geom_form: SimpleGeomForm = self._GEOMETRY_FORM_CLS(None, user=request.user, read_only=False)
context = self._get_specific_context_data()
context = BaseContext(request, additional_context=context).context
context.update(
{
"form": form,
"geom_form": geom_form,
TAB_TITLE_IDENTIFIER: self._TAB_TITLE,
}
)
return render(request, self._TEMPLATE, context)
def post(self, request: HttpRequest):
form: BaseForm = self._FORM_CLS(request.POST or None, user=request.user)
geom_form: SimpleGeomForm = self._GEOMETRY_FORM_CLS(request.POST or None, user=request.user, read_only=False)
if form.is_valid() and geom_form.is_valid():
obj = form.save(request.user, geom_form)
self._REDIRECT_URL = reverse(self._REDIRECT_URL, args=(obj.id,))
generated_identifier = form.cleaned_data.get("identifier", None)
if generated_identifier != obj.identifier:
messages.info(
request,
IDENTIFIER_REPLACED.format(
generated_identifier,
obj.identifier
)
)
messages.success(request, _("{} added").format(obj.identifier))
if geom_form.has_geometry_simplified():
messages.info(
request,
GEOMETRY_SIMPLIFIED
)
num_ignored_geometries = geom_form.get_num_geometries_ignored()
if num_ignored_geometries > 0:
messages.info(
request,
GEOMETRIES_IGNORED_TEMPLATE.format(num_ignored_geometries)
)
return redirect(self._REDIRECT_URL)
else:
context = self._get_specific_context_data()
context = BaseContext(request, additional_context=context).context
return render(request, self._TEMPLATE, context)
class BaseEditSpatialLocatedObjectFormView(LoginRequiredMixin, BaseFormView):
def get(self, request: HttpRequest, id: str):
obj = get_object_or_404(
self._MODEL_CLS,
id=id
)
form: BaseForm = self._FORM_CLS(None, instance=obj, user=request.user)
context = self._get_specific_context_data()
context = BaseContext(request, additional_context=context).context
context.update(
{
"form": form,
TAB_TITLE_IDENTIFIER: self._TAB_TITLE,
}
)
return render(request, self._TEMPLATE, context)
def post(self, request: HttpRequest, id: str):
obj = get_object_or_404(
self._MODEL_CLS,
id=id
)
form: BaseForm = self._FORM_CLS(request.POST or None, instance=obj, user=request.user)
if form.is_valid():
obj = form.save()
context = self._get_specific_context_data(obj=obj)
else:
context = self._get_specific_context_data()
context = BaseContext(request, additional_context=context).context
return render(request, self._TEMPLATE, context)