2015-10-20 132 views
1

我正在将一个django应用程序从1.4更新到1.8,并且遇到了django管理员的一个小问题。Django管理员表单和默认值的内联模型

我的模型看起来像这样

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时,它不会被保存,就好像没有添加任何内容。如果我手动更改自动生成的密钥保存中的单个leter,则可以正常工作。在我看来,这是django检测到更改或类似问题的问题。

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

回答

1

一个简短的调查导致我save_new_objectsclass 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的内容,你必须自己编辑。原来的方法再次出现在dist-packages/django/forms/models.py中,可以通过超级方式调用它,也可以完全写入你自己的东西,无论如何跳过检查。

此外,也许这是一个可怕的和过度复杂的解决方案。我有一种感觉,应该有一个更好的。例如,在示例中,未在模型中设置default=new_key,而是为表单字段设置默认值。

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