我想在 manytomany 字段中添加一个默认的项目列表,以防在 admin 中更新时将其留空。
我的问题是,通过覆盖 save、save_model 或 post_save 信号来更改多对多字段不起作用,因为 django 还没有完成保存子关系,只有父级(例如。Django:多对多关系的自定义保存方法)。 我尝试了信号m2m_changed,这是其他帖子中建议的解决方案,不会被触发,因为如果列表留空,它就不会改变!
谁能想到另一种方法,因为我似乎已经到达了方法覆盖和信号的死胡同? 我不介意在管理员中显示表单之前还是之后添加默认列表。
更新
什么不起作用:
(夹具是我的m2m字段的名称)。
我尝试了下面的建议,覆盖了各种方法。从此跟踪中,您可以看到夹具已添加,并且可以通过许多管理员和模型方法查看,但是在调用这些方法后的某个时间,它们将被删除并替换。 似乎没有可以覆盖的after_everything_else方法。
[Wed Sep 18 15:24:06 2013] [error] in save of model fixture count = 0
[Wed Sep 18 15:24:06 2013] [error] in save of overriden admin model form fixture count = 15
[Wed Sep 18 15:24:06 2013] [error] in save_model of admin fixture count = 15
[Wed Sep 18 15:24:06 2013] [error] in save of model fixture count = 15
什么有效
覆盖管理表单并将clean_fixtures方法放入其中。 clean_fixtures不会被调用,它只是放在管理资源中,它必须采用这样的覆盖形式:
class RankingUpdateForm(forms.ModelForm):
def clean_fixtures(self):
data = self.cleaned_data['fixtures']
# add default set of fixtures if none already there
if len(data) == 0:
return get_default_fixtures()
else:
return data
class RankingUpdateAdmin(admin.ModelAdmin):
list_display = ('rank_type','date', 'comment', 'issued')
form = RankingUpdateForm
def clean_fixtures(self):
assert False, "I'm never called!"
def save_formset(self):
assert False, "I'm never called either!"
您可以覆盖管理表单,并在 ManyToMany 字段的表单清理方法中实现逻辑。例如。
def clean_recipients(self):
data = self.cleaned_data['recipients']
if not data:
# return default recipients if the selected list is empty.
data = [r.pk for r in Recipient.objets.all()] #just an example, you can alter this query to select your defaults
return data
更新
重写保存方法以保存
收件人def save(self, commit=True):
instance = forms.ModelForm.save(self, False)
old_save_m2m = self.save_m2m
def save_m2m():
old_save_m2m()
instance.recepient_set.clear()
for recepient in self.cleaned_data['recepients']:
instance.recepient_set.add(recepient)
self.save_m2m = save_m2m
if commit:
instance.save()
self.save_m2m()
return instance
这是我用来在管理员表单集中自动填充作者(如果未设置)的代码片段
class AutoAuthoredModelAdmin(admin.ModelAdmin):
def save_model(self, request, obj, form, change):
if obj.author is None:
obj.author = request.user
super(AutoAuthoredModelAdmin, self).save_model(request, obj, form, change)
def save_formset(self, request, form, formset, change):
if hasattr(formset.model, 'author'):
instances = formset.save(commit=False)
for instance in instances:
if instance.author is None:
instance.author = request.user
super(AutoAuthoredModelAdmin, self).save_formset(request, form, formset, change)