我的博客文章模型有多对多标签字段:
tags = models.ManyToManyField(PostTag)
但是编辑它很不舒服,我把我的模型修改成这样:
^{pr2}$然后我修改了我的admin.py
:
class BlogAdminForm (forms.ModelForm):
tagging = forms.CharField(required=False, label="Tags", max_length=200,
widget=forms.TextInput(attrs={'class':'vTextField'}))
class Meta:
model = BlogPost
def __init__(self, *args, **kwargs):
super(BlogAdminForm, self).__init__(*args, **kwargs)
if kwargs.has_key('instance'):
instance = kwargs['instance']
self.initial['tagging'] = instance.tagging
def save(self, commit=True):
model = super(BlogAdminForm, self).save(commit=False)
model.tagging = self.cleaned_data["tagging"]
if commit:
model.save()
return model
这很好,但只适用于编辑对象。我试图创建新对象时出错。为什么?因为多对多关系可以与尚未在数据库中且没有主键的对象一起使用(“BlogPost”实例需要有主键值才能使用多对多关系)。我试图通过以下方式编辑save方法来解决这个问题:
def save(self, commit=True):
model = super(BlogAdminForm, self).save(commit=False)
try:
model.tagging = self.cleaned_data["tagging"]
except ValueError:
model.save()
model.tagging = self.cleaned_data["tagging"]
if commit:
model.save()
这解决了最初的问题。但是现在model.save()
没有调用管理模型的save_model
方法:
class BlogAdmin (admin.ModelAdmin):
# ...
form = BlogAdminForm
def save_model(self, request, obj, form, change):
obj.author = request.user
obj.save()
结果我得到了一个新的错误:null value in column "author_id" violates not-null constraint.
我做错了什么?我可以手动调用这个方法吗?在
在保存实例之后,必须保存标记,这意味着要在} method ,它会说:
save_model
函数中保存。这与您的标记操作代码无关:如果您查看documentation for the ^{有几种方法可以解决你的问题。您可以编写一个widget,在标记ID和逗号分隔的标记名列表之间来回转换,然后在
save_model
方法中调用form.save_m2m()
。但是这种方法的缺点是,在解码来自小部件的值时,您必须创建新的标记,即使表单没有保存(可能是因为表单中其他地方的验证错误)。在因此,我认为在这种情况下,更好的方法是将您自己的
save_tags
方法添加到表单中:请注意,我将标记操作代码移到了表单中:我认为它属于这里,而不是模型中,因为它都是关于用户输入的。我还做了一些风格上的改进:
'instance' in kwargs
比kwargs.has_key('instance')
简单。生成器表达式
(t.name for t in kwargs['instance'].tags.all())
比在for
循环中构建列表简单。^{} method 是一个方便的快捷方式,可以避免
try: ... except ObjectDoesNotExist: ...
您可以直接分配给
ManyToMany
字段,而不是先调用clear
,然后再调用add
(而且,当标记不变时,它更有效)。相关问题 更多 >
编程相关推荐