禁止 Django 自引用外键指向自身对象
Posted
技术标签:
【中文标题】禁止 Django 自引用外键指向自身对象【英文标题】:Disallow Django self-referential foreign key to point to self object 【发布时间】:2017-04-08 13:04:07 【问题描述】:我有一个常规的自引用外键:
idol = models.ForeignKey("self", on_delete=models.CASADE)
管理页面允许我选择相同的对象 ID。如何防止 django 管理表单显示它?
【问题讨论】:
【参考方案1】:您可以在 ModelAdmin
类的子类中覆盖 formfield_for_foreignkey
。
ModelAdmin 上的 formfield_for_foreignkey 方法允许您 覆盖外键字段的默认表单字段。
父对象id可以保存在change_view
方法中:
class IdolAdmin(admin.ModelAdmin):
def change_view(self, request, object_id, form_url='', extra_context=None):
self.object_id = object_id
return super(IdolAdmin, self).change_view(
request, object_id, form_url, extra_context=extra_context,
)
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == "idol":
kwargs['queryset'] = Idol.objects.exclude(pk=self.object_id)
return super(IdolAdmin, self).formfield_for_foreignkey(
db_field, request, **kwargs)
【讨论】:
【参考方案2】:您应该能够将模型管理员的表单设置为包含修改的自定义表单
class ModelAdmin...
form = MyModelForm
我想表单看起来像这样
class MyModelForm(ModelForm)
class Meta:
model = MyModel
def __init__(self, *args, **kwargs):
super(MyModelForm, self).__init__(*args, **kwargs)
if self.instance.pk:
query = self.fields['my_field'].queryset
self.fields['my_field'].queryset = query.exclude(id=self.instance.id)
【讨论】:
【参考方案3】:您可以扩展render_change_form
。
class IdolAdmin(admin.ModelAdmin):
def render_change_form(self, request, context, *args, **kwargs):
queryset = context['adminform'].form.fields['idol'].queryset
original_id = context.get('original', None)
if(original_id):
context['adminform'].form.fields['idol'].queryset = queryset.exclude(id=original_id.id)
return super(IdolAdmin, self).render_change_form(request, context, args, kwargs)
【讨论】:
以上是关于禁止 Django 自引用外键指向自身对象的主要内容,如果未能解决你的问题,请参考以下文章
Django:在 GenericStackedInline 上禁止 can_delete
Django - 使用 ExtJS 发布 ajax 请求禁止 403
graphene-django:没有“Meta.fields”或“Meta.exclude”的“Meta.model”自 0.15.0 以来已被弃用,现在已被禁止