python - django - How to cross check ModelAdmin and its inlines? -
i have 2 models (modelparent , modelchild) same m2m fields on subject model. modelchild has foreign key on modelparent , modelchild defined inline modelparent on admin page.
### 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)
i have 1 important restriction though, modelchild's subjects_child field must not reference subject subject_parent subjects_parent.
so, if select same subject (in subject_parent , subject_child) on admin page both models, how can validate this? if 1 field changes validate against db, if both change (subject_parent , subject_child)? how can validate both forms before saving?
i have inherited new class named modeladminwithinline admin.modeladmin , modified methods add_view(...) , change_view(...) call function is_cross_valid(self, form, formsets), can validate forms together. both functions had:
#... if all_valid(formsets) , form_validated: #...
changed to:
#... formsets_validated = all_valid(formsets) cross_validated = self.is_cross_valid(form, formsets) if formsets_validated , form_validated , cross_validated: #...
the new function is_cross_valid(...) defined this:
def is_cross_valid(self, form, formsets): return true
so new class should work same modeladmin if don't change is_cross_valid(...) function.
now admin.py looks this:
###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 cross validation on forms #for example, here particular validation: valid = true if hasattr(form, 'cleaned_data'): subjects_parent = form.cleaned_data.get("subjects_parent") #you can access forms formsets this: formset in formsets: 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 , (delete_form == false): subject in subjects_child: if subject in subjects_parent: valid = false #from here can still report errors in regular forms: if "subjects_child" in formset_form.cleaned_data.keys(): formset_form._errors["subjects_child"] = errorlist([u"subject %s selected in parent modelparent" % subject]) del formset_form.cleaned_data["subjects_child"] else: formset_form._errors["subjects_child"] += errorlist(u"subject %s selected in parent modelparent" % subject]) #return true on success or false otherwise. return valid admin.site.register(modelparent, modelparentadmin)
the solution little bit hackish works :). errors show same regular modelform , modeladmin classes. django 1.2 (which should released shortly) should have model validation, hope problem solved more nicely.
Comments
Post a Comment