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

时间:2015-10-20 17:17:08

标签: django django-admin

我正在将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 个答案:

答案 0 :(得分: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 :(得分:1)

简短的调查将我引导至位于public partial class Form1 : Form { TextBox[] descrip2Arr; public Form1() { InitializeComponent(); TextBox[] descripArr = { decrip1_Box, decrip2_Box, decrip3_Box, decrip4_Box, decrip5_Box, decrip6_Box, decrip7_Box, decrip8_Box, decrip9_Box, decrip10_Box,decrip11_Box,decrip12_Box, decrip13_Box,decrip14_Box,decrip15_Box,decrip16_Box}; for (int i = 0; i < descrip2Arr.Length; i++) descrip2Arr[i].Text = "Descrip 2 cod " + (i + 1).ToString(); } } 的{​​{1}} save_new_objects。 它有以下检查:class BaseModelFormSet

看起来很有希望,对吧?现在,我们想要“增强”这种方法。从哪儿开始?好吧......内联继承自django/forms/models.py,它有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,而是在表单字段中设置默认值。