ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

python – django – 如何交叉检查ModelAdmin及其内联?

2019-05-15 23:43:16  阅读:188  来源: 互联网

标签:python django django-forms django-admin


我有两个模型(ModelParent和ModelChild)在Subject模型上具有相同的m2m字段.
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)

我有一个重要的限制,ModelChild的subjects_child字段不得引用subject_parent与subject_parent一起使用的任何主题.

因此,如果我在两个模型的管理页面上选择相同的主题(在subject_parent和subject_child中),我该如何验证?
如果只有一个字段发生更改,则会根据数据库对其进行验证,但如果两者都发生更改(subject_parent和subject_child)会怎样?
如何在保存前同时验证两种表格?

最佳答案:

我从admin.ModelAdmin继承了一个名为ModelAdminWithInline的新类,并修改了方法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

因此,如果不更改is_cross_valid(…)函数,则新类应与ModelAdmin完全相同.

现在我的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)

解决方案有点hackish但它的工作原理:).错误显示与常规ModelForm和ModelAdmin类相同. Django 1.2(应该很快发布)应该有模型验证,所以我希望这个问题可以更好地解决.

标签:python,django,django-forms,django-admin
来源: https://codeday.me/bug/20190515/1111127.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有