我是Python和Django的新手:)我需要一些帮助。
我想做什么:
我有一个模型 Page ,当有人试图更新一个对象时,我需要添加一个自定义字段“message”。
为什么呢?因为我正在建立一个修订系统。这个领域,它只是对变化的解释。所以这个字段没有链接到Page(但是链接到另一个模型PageRevision)
经过一些研究后,我设法将此字段添加到admin.py文件中的表单中,如下所示:
class PageAdminForm(forms.ModelForm):
# custom field not backed by database
message = forms.CharField(required=False)
class Meta:
model = Page
它正在工作,我的领域现在显示......但我不希望这个领域到处都是。就在有人试图更新Page对象时。 我找到了这个答案different-fields-for-add-and-change-pages-in-admin,但它不适合我,因为它是一个自定义字段(我认为)。
我在admin.py中的其余代码:
class PageAdmin(admin.ModelAdmin):
form = PageAdminForm
fields = ["title", "weight", "description", "message"]
list_display = ["title", "weight", "description"]
list_filter = ["updated_at"]
def get_form(self, request, obj=None, **kwargs):
if obj is None:
# not working ?
kwargs['exclude'] = ['message']
# else:
# kwargs['exclude'] = ['message']
return super(PageAdmin, self).get_form(request, obj, **kwargs)
def save_model(self, request, obj, form, change):
if not obj.id:
obj.author = request.user
obj.modified_by = request.user
wiki_page = obj.save()
# save page in revision table
revision = PageRevision(change=change, obj=wiki_page,
request=request)
# retrieve value in the custom field
revision.message = form.cleaned_data['message']
revision.save()
def get_form 不排除我的自定义消息字段,因为我认为它不知道是否存在。如果我把另一个像标题的字段,它的工作原理。 那么如何从添加视图中排除自定义字段?
谢谢:)
答案 0 :(得分:5)
你是对的,它不会以这种方式工作,因为'message'不是在Page模型上找到的字段,ModelAdmin类将忽略排除。你可以通过多种方式实现这一目标,但我认为最好的方法是:
class PageAdmin(admin.ModelAmin):
change_form = PageAdminForm
...
def get_form(self, request, obj=None, **kwargs):
if obj is not None:
kwargs['form'] = self.change_form
return super(UserAdmin, self).get_form(request, obj, **defaults)
Basicaly这里django在编辑页面时添加页面和自定义表单时会使用自动生成的ModelForm。 Django本身使用类似的技术在添加和更改用户时显示不同的表单:
https://github.com/django/django/blob/stable/1.6.x/django/contrib/auth/admin.py(有趣的部分在第68行)
答案 1 :(得分:-1)
我刚刚偶然发现了同样的问题,由于它出现在第一个搜索结果中,我想为不想使用自定义表单的人添加其他解决方案。
您可以覆盖管理类的 get_fields
方法以从“添加”页面中删除自定义字段。
def get_fields(self, request, obj=None):
fields = list(super().get_fields(request, obj=obj))
if obj is None:
fields.remove("message")
return fields