Django如何交叉检查ModelAdmin及其内联?

2024-09-27 19:26:49 发布

您现在位置:Python中文网/ 问答频道 /正文

我有两个模型(ModelParent和ModelChild)在主题模型上具有相同的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\u child字段不能引用subject\u parent对其subjects\u parent所做的任何主题。在

所以,如果我在管理页面上为两个模型选择相同的主题(在Subject_parent和Subject_child中),我如何验证这一点? 如果只有一个字段发生更改,您将根据数据库对其进行验证,但是如果两个字段都发生了更改(subject\u parent和subject_child)? 如何在保存前同时验证这两个表单?在


Tags: py模型child主题modeladminmodelsclass
2条回答

我从继承了一个名为modeldAdminWithInline的新类管理模型管理员而修改后的方法add_view(…)和change_view(…)调用函数is_cross_valid(self,form,formsets),可以一起验证所有表单。 两种功能都有:

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

更改为:

^{pr2}$

新函数is_cross_valid(…)的定义如下:

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

因此,如果不更改is_cross_valid(…)函数,新类的工作方式应该与ModelAdmin完全相同。在

现在我的管理员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类的错误相同。django1.2(应该很快发布)应该有模型验证,所以我希望这个问题可以得到更好的解决。在

clean()方法没有admin()类。它们的形态确实如此。每个管理类都有一个名为form的参数。只需扩展form admin()和form admin()方法即可。 示例:

class SomeForm(ModelForm):
  #some code
  def clean(self):
   #some code
class SomeAdminClass(ModelAdmin):
 #some code
 form = SomeForm
 #more code

相关问题 更多 >

    热门问题