Django Admin not saving pre-populated inline fields which are left in their initial state

半城伤御伤魂 提交于 2020-01-11 09:35:12

问题


I have some custom admin code which initialises some inline child objects.

If the user edits one of the inline child object's default values, then that child element is created when the parent object is saved.

I assume that Django is checking whether values have changed from their initial values and only saving if the user has changed a value.

Is this the case?

How do I force Django Admin to create inline child objects with their unchanged default values, if the user chooses not to change the default values?

class PrepopIpInlineFormSet(forms.models.BaseInlineFormSet):
    model = Ip

    def __init__(self, *args, **kwargs):
        super(PrepopIpInlineFormSet, self).__init__(*args, **kwargs)
        initial = # calculate a set of default Ip model initial values
        self.initial = initial


class PrepopIpInline(admin.options.InlineModelAdmin):
    template = "admin/linked.html"
    model = Ip
    formset = PrepopIpInlineFormSet
    fk_name = 'sim'
    admin_model_path = None
    show_url = True

    def __init__(self, *args):
        super(PrepopIpInline, self).__init__(*args)
        if self.admin_model_path is None:
            self.admin_model_path = self.model.__name__.lower()

    def get_formset(self, request, obj=None, **kwargs):
        formset = super(PrepopIpInline, self).get_formset(request, obj, **kwargs)
        formset.request = request
        return formset

    def get_extra(self, request, obj=None, **kwargs):
        if obj:
            return 0
        else:
            return ApnGgsn.objects.all().count()

回答1:


Origin: How to force-save an "empty"/unchanged django admin inline?

from django.contrib import admin
from django.forms.models import BaseInlineFormSet, ModelForm

class AlwaysChangedModelForm(ModelForm):
    def has_changed(self):
        """ Should returns True if data differs from initial. 
        By always returning true even unchanged inlines will get validated and saved."""
        return True

class CheckerInline(admin.StackedInline):
    """ Base class for checker inlines """
    extra = 0
    form = AlwaysChangedModelForm



回答2:


In the ModelAdmin object itself, you could super the save_related method. Then, once that is completed, check for the existence of those models. If they don't exist, create them. It would look something like this:

class ParentObjectAdmin(admin.ModelAdmin):
  def save_related(self, request, form, formsets, change):
    super(ParentObjectAdmin, self).save_related(request, form, formsets, change)
    obj = form.instance
    if form.is_valid() and not ChildObject.objects.filter(parent = obj).exists():
      ChildObject.objects.create(name = ChildObject.default_name, parent = obj, ...)

Full disclosure: I can't remember if (in the case of a newly created ParentObject) whether or not the form.instance attribute will yet be populated. I do know that the underlying object will have been created at that point (because save_model is called before save_related).

If what I'm proposing with "obj = form.instance" doesn't work, you can also get that new object by querying based on unique values in your form data.

For example, instead of obj = form.instance, do:

obj = ParentObject.objects.get(username = form.cleaned_data.get("username"))


来源:https://stackoverflow.com/questions/34355406/django-admin-not-saving-pre-populated-inline-fields-which-are-left-in-their-init

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!