python - 在 Django admin 中提交表单后添加数据
问题描述
(我对 Django 很陌生,并且使用 Django 1.8 的代码库)
有一个模型(Survey)与另一个模型(Page)有多对多的关系,并引用起始页(Page)。在管理面板中创建这个对用户来说真的很麻烦,但如果他们做出一些是/否的决定,就可以解决。
因此,在管理添加页面中,我添加了一些不属于模型的选择字段(或多或少“包括 A 部分?”/“包括 B 部分?”/“包括 C 部分?”...等),并根据用户在此处选择的内容,我想在 Survey 和 starting_page 上的 page_links 中添加不同的键。
解决这些问题很好,但是当保存表单/模型时, page_links 和 start_page 不存在,大概是因为它们不是表单的一部分。
我尝试将它们添加到cleaned_data(保存或清理),但这不起作用。
这是模型:
class Survey(models.Model):
title = models.CharField(max_length=255)
start_page = models.ForeignKey('Page', related_name='surveys_started', null=True)
page_links = models.ManyToManyField('PageLink', related_name='surveys')
这是管理员:
class SurveyAdmin(admin.ModelAdmin):
fieldsets = (
(None, {
'fields': ('title', ),
}),
('User Decisions', {
'fields': ('do_a', 'do_b', 'do_c', )
}),
)
form = SurveyForm
和表格:
class SurveyForm(forms.ModelForm):
title = forms.CharField(required=True)
do_a = forms.ChoiceField(label='Do A',choices=[(True, 'Yes'), (False, 'No')], initial=True)
do_b = forms.ChoiceField(label='Do B',choices=[(True, 'Yes'), (False, 'No')], initial=True)
do_c = forms.ChoiceField(label='Do C',choices=[(True, 'Yes'), (False, 'No')], initial=True)
def save(self, commit=True):
title = self.cleaned_data.get('title', 'N/A')
do_a = self.cleaned_data.get('do_a', True)
do_b = self.cleaned_data.get('do_b', True)
do_c = self.cleaned_data.get('do_c', True)
# Assume these two work fine
page_links = work_out_links(do_a, do_b, do_c)
start_page = get_start_page(do_a, do_b, do_c)
self.cleaned_data['page_links'] = page_links
self.cleaned_data['start_page'] = start_page
return super(SurveyForm, self).save(commit=commit)
class Meta:
exclude = ['start_page']
基本上我只希望 save_model 中的 'page_links' 和 'start_page' 的内容在数据库的 Survey 实例中。
(注意:我知道我似乎应该创建一个中间“部分”并让用户选择那些,但假设如果可能的话我不这样做是有原因的 8))
非常感谢任何帮助。
解决方案
好的,结果证明一种有效的方法是正常返回表单数据,然后在 admin.ModelAdmin 的 save_model 方法中进行分配。
于是表格变成了:
class SurveyForm(forms.ModelForm):
title = forms.CharField(required=True)
do_a = forms.ChoiceField(label='Do A',choices=[(True, 'Yes'), (False, 'No')], initial=True)
do_b = forms.ChoiceField(label='Do B',choices=[(True, 'Yes'), (False, 'No')], initial=True)
do_c = forms.ChoiceField(label='Do C',choices=[(True, 'Yes'), (False, 'No')], initial=True)
def save(self, commit=True):
title = self.cleaned_data.get('title', 'N/A')
do_a = self.cleaned_data.get('do_a', True)
do_b = self.cleaned_data.get('do_b', True)
do_c = self.cleaned_data.get('do_c', True)
# Assume these two work fine
page_links = work_out_links(do_a, do_b, do_c)
start_page = get_start_page(do_a, do_b, do_c)
self.cleaned_data['page_links'] = page_links
self.cleaned_data['start_page'] = start_page
return super(SurveyForm, self).save(commit=commit)
class Meta:
exclude = ['start_page']
ModelAdmin 变成了:
class SurveyAdmin(admin.ModelAdmin):
fieldsets = (
(None, {
'fields': ('title', ),
}),
('User Decisions', {
'fields': ('do_a', 'do_b', 'do_c', )
}),
)
form = SurveyForm
def save_model(self, request, obj, form, change):
obj.start_page = form.cleaned_data['start_page']
obj.save()
# Need to save _before_ adding foreign keys
obj.page_links = form.cleaned_data['page_links']
这很好用,(编辑)虽然我几乎肯定应该将更多的逻辑从 form.save 移动到 modelAdmin.save_model。
推荐阅读
- javascript - 使用数据属性中的值检查链接单击上的复选框(可能在更改冲突时?)
- javascript - 如何根据 JavaScript 中变量的值更改 CSS 类?
- swift - 如何为 CollectionView Cell 指定行数、列数和间距
- swift - 是否有任何解决方法可以将存储的属性快速放入扩展中?
- assembly - 一个词在给定语句中使用了多少次。MIPS MARS 组件
- rest - REST API - 更多参数以方便使用
- r - 我如何摆脱 ¦ 登录我的数据
- c++ - int&referenceToA = a; 怎么样?可能的?
- python - 如何检查是否已经选择了某些内容?
- http - 托管在不同 Web 服务器上的 HTTP 请求对象的 TCP 连接