如何解决django Admin-根据编辑形式中的其他选择过滤外键选择无jQuery
我正在研究一个由超级管理员管理的项目,该超级管理员为不同公司输入数据。
可以说,我有以下模型:
class Company(models.Model):
name = models.CharField(max_length=100)
class ContactPerson(models.Model):
name = models.CharField(max_length=100)
company = models.ForeignKey(Company)
class Item(models.Model):
company = models.ForeignKey(Company)
contact_person = models.ForeignKey(ContactPerson)
我需要确保我(在django admin中)处于编辑模式,我只会看到属于所选公司的联系人。
要不在2005年,我要避免编写大量丑陋的jQuery代码。
我想我可以覆盖Item
的管理表单。但是我仍然必须将contact_person
设置为可选,因此当我创建新的Item
时,联系人列表必须为空。然后,我选择一家公司,保存并返回编辑。现在contact_person
列表将被填充,我可以添加一个人。但是,如果现在更改逗号,则必须删除所有选定的联系人。当然,我可以用表格的方式来实现这一点……但是它看起来很hacky,而不像一个不错的Django解决方案。
有人有什么好主意吗?
谢谢!
罗尼
解决方法
实际上,django为我提供了一个简洁的解决方案。
当您查看Django代码中的UserAdmin
类时,您会发现一种内置的方法来处理两步创建过程。
@admin.register(User)
class UserAdmin(admin.ModelAdmin):
...
add_form = UserCreationForm
...
def get_form(self,request,obj=None,**kwargs):
"""
Use special form during user creation
"""
defaults = {}
if obj is None:
defaults['form'] = self.add_form
defaults.update(kwargs)
return super().get_form(request,obj,**defaults)
设置属性add_form
且对象尚无ID(=我们正在创建它)时,它的形式与通常不同。
我将这个想法包装在管理员混合中,如下所示:
class AdminCreateFormMixin:
"""
Mixin to easily use a different form for the create case (in comparison to "edit") in the django admin
Logic copied from `django.contrib.auth.admin.UserAdmin`
"""
add_form = None
def get_form(self,**kwargs):
defaults = {}
if obj is None:
defaults['form'] = self.add_form
defaults.update(kwargs)
return super().get_form(request,**defaults)
现在,当我有相关字段时,我将创建一个小型表单,其中包含与company
独立的所有值以及包含所有内容的常规表单。
@admin.register(Item)
class ItemAdmin(AdminCreateFormMixin,admin.ModelAdmin):
form = ItemEditForm
add_form = ItemAddForm
...
现在,我可以在编辑表单中自定义相关字段的查询集:
class ItemEditForm(AdminDisabledCompanyFieldMixin,forms.ModelForm):
class Meta:
model = Item
exclude = ()
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
self.fields['contact_person'].queryset = ContactPerson.objects.filter(company=self.instance.company)
唯一的缺点是,数据库的所有相关字段都必须可空。否则,您将无法在创建过程中将其保存。
幸运的是,您可以使用模型声明中的blank=False,null=True
告诉django,该字段是表单中的必填字段,而不是数据库级的字段。
希望这对其他人也有帮助!
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。