【问题标题】:Django admin form and inlined model with default valueDjango 管理表单和具有默认值的内联模型
【发布时间】:2015-10-20 17:17:07
【问题描述】:

我正在将一个 django 应用程序从 1.4 更新到 1.8,并且遇到了 django admin 的一个小问题。

我的模型是这样的

def new_key():
   return binascii.b2a_hex(os.urandom(20))

class ApiKey(models.Model):
  customer = models.ForeignKey(UserProfile)
  key = models.CharField(max_length=40, default=new_key)

而 admin.py 是

class ApiKeyInline(admin.StackedInline):
  model = ApiKey
  extra = 0

class UserProfileAdmin(admin.ModelAdmin):
  inlines = [ApiKeyInline]

admin.site.register(UserProfile, UserProfileAdmin)

当使用管理页面 api 键时,会正确填充随机值。但是,当保存 UserProfile 时,它​​不会被保存,就好像什么都没有添加一样。如果我在自动生成的密钥保存中手动更改一个字母,则可以正常工作。在我看来,这是 django 检测到更改或类似情况的问题。

有什么建议吗?代码在 1.4 中工作。

【问题讨论】:

    标签: django django-admin


    【解决方案1】:

    在其中一个旧线程中有一个解决方案:How to force-save an "empty"/unchanged django admin inline?

    您应该将内联表单标记为始终更改。

    from django.forms import ModelForm
    from .models import UserProfile
    
    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
    
    #An inline model
    class ApiKey(admin.StackedInline):
        model = ApiKey
        extra = 0
        form = AlwaysChangedModelForm
    

    【讨论】:

      【解决方案2】:

      一个简短的调查将我带到位于django/forms/models.pyclass BaseModelFormSetsave_new_objects。 它有以下检查:if not form.has_changed()

      看起来很有希望,对吧?现在,我们要“增强”这种方法。从哪儿开始?嗯...内联继承自InlineModelAdmin,它有一个get_formset 方法。所以...

      class ApiKeyInline(admin.StackedInline):
          model = ApiKey
          extra = 0
      
          def get_formset(self, *args, **kwargs):
              formset = super(EmailInlineAdmin, self).get_formset(*args, **kwargs)
              # at this point, formset is a generated class called like "ApiKeyFormSet"
              # as it is a regular python objects, no one stops us from playing with it
              formset.save_new_objects = ApiKeyInline.my_own_save_new_objects_method
              return formset
      
          def my_own_save_new_objects_method(self, commit=True):
              # here should be something like 
              # django/forms/models.py    BaseModelFormSet.save_new_objects
              return self.new_objects
      

      my_own_save_new_objects_method的内容要自己编辑。再一次,原来的方法是在 dist-packages/django/forms/models.py 中,要么通过 super 调用它,要么写一些完全属于你的东西,反正跳过检查。

      另外,也许这是一个糟糕且过于复杂的解决方案。我有一种感觉,应该有一个更好的。例如,不在模型中设置default=new_key,而是为表单字段设置默认值,例如。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-02-06
        • 1970-01-01
        相关资源
        最近更新 更多