|
4 | 4 | from urllib.parse import parse_qsl, urlparse, urlunparse
|
5 | 5 |
|
6 | 6 | from django.urls import path, re_path, include
|
| 7 | +from django.core.exceptions import ValidationError |
7 | 8 | from django.contrib.admin.options import IS_POPUP_VAR, TO_FIELD_VAR
|
8 | 9 | from django.contrib.admin.utils import unquote, quote
|
9 | 10 | from django.contrib import admin
|
|
14 | 15 | from django.forms.models import _get_foreign_key
|
15 | 16 | from django.http import HttpResponseRedirect
|
16 | 17 | from django.shortcuts import get_object_or_404
|
17 |
| -from django.template.response import SimpleTemplateResponse, TemplateResponse |
| 18 | +from django.template.response import TemplateResponse |
18 | 19 | from django.utils.decorators import method_decorator
|
19 | 20 | from django.utils.functional import cached_property
|
20 | 21 | from django.utils.html import format_html
|
21 | 22 | from django.utils.http import urlencode, urlquote
|
22 | 23 | from django.utils.translation import ugettext as _
|
23 | 24 | from django.views.decorators.csrf import csrf_protect
|
24 | 25 | from django.urls import Resolver404, get_script_prefix, resolve, reverse
|
25 |
| -from .forms import get_form |
26 | 26 |
|
27 | 27 | csrf_protect_m = method_decorator(csrf_protect)
|
28 | 28 |
|
29 |
| -__all__ = ('SubAdmin', 'RootSubAdmin', 'SubAdminMixin', 'RootSubAdminMixin', 'SubAdminChangeList', 'SubAdminHelper') |
| 29 | +__all__ = ('SubAdmin', 'RootSubAdmin', 'SubAdminMixin', 'RootSubAdminMixin', 'SubAdminChangeList', 'SubAdminHelper', 'SubAdminFormMixin') |
30 | 30 |
|
31 | 31 |
|
32 | 32 | class SubAdminHelper(object):
|
@@ -87,6 +87,38 @@ def url_for_result(self, result):
|
87 | 87 | return self.model_admin.reverse_url('change', *self.model_admin.get_base_url_args(self.request) + [pk])
|
88 | 88 |
|
89 | 89 |
|
| 90 | +class SubAdminFormMixin(object): |
| 91 | + def _post_clean(self): |
| 92 | + validate_unique = self._validate_unique |
| 93 | + self._validate_unique = False |
| 94 | + super()._post_clean() |
| 95 | + |
| 96 | + for fk_field, fk_instance in self._related_instances_fields.items(): |
| 97 | + setattr(self.instance, fk_field, fk_instance) |
| 98 | + |
| 99 | + self._validate_unique = validate_unique |
| 100 | + if self._validate_unique: |
| 101 | + self.validate_unique() |
| 102 | + |
| 103 | + |
| 104 | + def validate_unique(self): |
| 105 | + exclude = self._get_subadmin_validation_exclusions() |
| 106 | + |
| 107 | + try: |
| 108 | + self.instance.validate_unique(exclude=exclude) |
| 109 | + except ValidationError as e: |
| 110 | + self._update_errors(e) |
| 111 | + |
| 112 | + def _get_subadmin_validation_exclusions(self): |
| 113 | + return [f for f in self._get_validation_exclusions() if f not in self._related_instances_fields.keys()] |
| 114 | + |
| 115 | + @cached_property |
| 116 | + def _related_instances_fields(self): |
| 117 | + return { |
| 118 | + key: self._related_instances[key] for key in self._related_instances.keys() if key in self._meta.model._meta._forward_fields_map.keys() |
| 119 | + } |
| 120 | + |
| 121 | + |
90 | 122 | class SubAdminBase(object):
|
91 | 123 | subadmins = None
|
92 | 124 |
|
@@ -198,13 +230,17 @@ def get_exclude(self, request, obj=None):
|
198 | 230 | exclude.extend(request.subadmin.related_instances.keys())
|
199 | 231 | return list(set(exclude))
|
200 | 232 |
|
| 233 | + def prep_subadmin_form(self, request, form): |
| 234 | + attrs = {'_related_instances': request.subadmin.related_instances} |
| 235 | + return type(form)(form.__name__, (SubAdminFormMixin, form), attrs) |
| 236 | + |
| 237 | + def get_form(self, request, obj=None, **kwargs): |
| 238 | + form = super().get_form(request, obj, **kwargs) |
| 239 | + return self.prep_subadmin_form(request, form) |
| 240 | + |
201 | 241 | def get_changelist_form(self, request, **kwargs):
|
202 | 242 | form = super().get_changelist_form(request, **kwargs)
|
203 |
| - return get_form(form, self.model, request.subadmin.related_instances) |
204 |
| - |
205 |
| - def get_form(self, request, obj=None, change=False, **kwargs): |
206 |
| - form = super().get_form(request, obj, change, **kwargs) |
207 |
| - return get_form(form, self.model, request.subadmin.related_instances) |
| 243 | + return self.prep_subadmin_form(request, form) |
208 | 244 |
|
209 | 245 | def get_base_viewname(self):
|
210 | 246 | if hasattr(self.parent_admin, 'get_base_viewname'):
|
@@ -408,7 +444,11 @@ def response_change(self, request, obj):
|
408 | 444 | 'obj': str(obj),
|
409 | 445 | 'new_value': str(new_value),
|
410 | 446 | })
|
411 |
| - return SimpleTemplateResponse('admin/popup_response.html', { |
| 447 | + return TemplateResponse(request, self.popup_response_template or [ |
| 448 | + 'admin/%s/%s/popup_response.html' % (opts.app_label, opts.model_name), |
| 449 | + 'admin/%s/popup_response.html' % opts.app_label, |
| 450 | + 'admin/popup_response.html', |
| 451 | + ], { |
412 | 452 | 'popup_response_data': popup_response_data,
|
413 | 453 | })
|
414 | 454 |
|
@@ -487,7 +527,11 @@ def response_delete(self, request, obj_display, obj_id):
|
487 | 527 | 'action': 'delete',
|
488 | 528 | 'value': str(obj_id),
|
489 | 529 | })
|
490 |
| - return SimpleTemplateResponse('admin/popup_response.html', { |
| 530 | + return TemplateResponse(request, self.popup_response_template or [ |
| 531 | + 'admin/%s/%s/popup_response.html' % (opts.app_label, opts.model_name), |
| 532 | + 'admin/%s/popup_response.html' % opts.app_label, |
| 533 | + 'admin/popup_response.html', |
| 534 | + ], { |
491 | 535 | 'popup_response_data': popup_response_data,
|
492 | 536 | })
|
493 | 537 |
|
|
0 commit comments