首页 文章

Django管理表单和内联模型的默认值

提问于
浏览
1

我正在将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 .

2 回答

  • 3

    其中一个旧线程中有一个解决方案: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
    
  • 1

    一个简短的调查引导我找到 class BaseModelFormSetsave_new_objects ,位于 django/forms/models.py . 它有以下检查: if not form.has_changed()

    看起来很有希望,对吧?现在,我们要"enhance"这个方法 . 从哪儿开始?嗯...内联继承自 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 ,而是在示例中为表单字段设置默认值 .

相关问题