django – Как перекрестно проверить ModelAdmin и его встроенные строки?

У меня две модели (ModelParent и ModelChild) с одинаковыми полями m2m на модели Subject. ModelChild имеет внешний ключ на ModelParent, а ModelChild определен как встроенный для ModelParent на странице администратора.

### models.py ### class Subject(Models.Model): pass class ModelParent(models.Model): subjects_parent = ManyToManyField(Subject) class ModelChild(models.Model): parent = ForeignKey(ModelParent) subjects_child = ManyToManyField(Subject) ### admin.py ### class ModelChildInline(admin.TabularInline): model = ModelChild class ModelParentAdmin(admin.ModelAdmin): inlines = [ModelChildInline] admin.site.register(ModelParent, ModelParentAdmin) 

У меня есть одно важное ограничение, хотя в поле subject_child ModelChild не должно ссылаться ни на какой предмет, который subject_parent делает с его subject_parent.

Итак, если я выбираю один и тот же Subject (в subject_parent и subject_child) на странице администратора для обеих моделей, как я могу проверить это? Если изменяется только одно поле, вы проверяете его против db, но что, если оба изменения (subject_parent и subject_child)? Как я могу проверить обе формы вместе до сохранения?

2 Solutions collect form web for “django – Как перекрестно проверить ModelAdmin и его встроенные строки?”

Я унаследовал новый класс с именем ModelAdminWithInline от admin.ModelAdmin и модифицировал методы add_view (…) и change_view (…) для вызова функции is_cross_valid (self, form, formsets), где вы можете проверить все формы вместе. Обе функции имели:

 #... if all_valid(formsets) and form_validated: #... 

изменился на:

 #... formsets_validated = all_valid(formsets) cross_validated = self.is_cross_valid(form, formsets) if formsets_validated and form_validated and cross_validated: #... 

Новая функция is_cross_valid (…) определяется следующим образом:

 def is_cross_valid(self, form, formsets): return True 

поэтому новый класс должен работать точно так же, как ModelAdmin, если вы не измените функцию is_cross_valid (…).

Теперь мой admin.py выглядит так:

 ###admin.py### class ModelAdminWithInline(admin.ModelAdmin): def is_cross_valid(self, form, formsets): return True def add_view(self, request, form_url='', extra_context=None): #modified code def change_view(self, request, object_id, extra_context=None): #modified code class ModelChildInline(admin.TabularInline): model = ModelChild class ModelParentAdmin(ModelAdminWithInline): inlines = [ModelChildInline] def is_cross_valid(self, form, formsets): #Do some cross validation on forms #For example, here is my particular validation: valid = True if hasattr(form, 'cleaned_data'): subjects_parent = form.cleaned_data.get("subjects_parent") #You can access forms from formsets like this: for formset in formsets: for formset_form in formset.forms: if hasattr(formset_form, 'cleaned_data'): subjects_child = formset_form.cleaned_data.get("subjects_child") delete_form = formset_form.cleaned_data.get("DELETE") if subjects_child and (delete_form == False): for subject in subjects_child: if subject in subjects_parent: valid = False #From here you can still report errors like in regular forms: if "subjects_child" in formset_form.cleaned_data.keys(): formset_form._errors["subjects_child"] = ErrorList([u"Subject %s is already selected in parent ModelParent" % subject]) del formset_form.cleaned_data["subjects_child"] else: formset_form._errors["subjects_child"] += ErrorList(u"Subject %s is already selected in parent ModelParent" % subject]) #return True on success or False otherwise. return valid admin.site.register(ModelParent, ModelParentAdmin) 

Решение немного хакерское, но оно работает :). Ошибки отображаются так же, как и с обычными классами ModelForm и ModelAdmin. Django 1.2 (который должен быть выпущен в ближайшее время) должен иметь проверку модели, поэтому я надеюсь, что тогда эта проблема может быть решена более красиво.

Классы admin не имеют метода clean (). Их формы. Каждый класс администратора имеет параметр, называемый формой. Вы просто расширяете форму по умолчанию (это обычная форма ModelAdmin), реализуете метод clean () и добавляете форму в класс администратора. Пример:

 class SomeForm(ModelForm): #some code def clean(self): #some code class SomeAdminClass(ModelAdmin): #some code form = SomeForm #more code 
  • Получение NameError с Django 1.5 и IPython
  • удалить выбранный по умолчанию вариант в поле ForeignKey для django admin
  • python django shell (ipython) неожиданное поведение или ошибка?
  • Что эквивалентно «none» в шаблонах django?
  • Форма входа в Django в загрузочном всплывающем окне
  • Django form.as_p DateField не показывает тип ввода как дату
  • django: как получить значение от CharField и ModelChoiceField
  • Django FormWizard, как изменить динамический формат
  • Python - лучший язык программирования в мире.