我曾问过一个与此有关的问题。但我认为直接问我的问题会更好。我有一个与其他两个表“域”和“组”有多对多关系的“用户”表。因此,在管理界面中,我将 Groups 和 Domains 视为 2 ModelMultipleChoiceFields。但我想以更加用户友好的方式在 UI 上呈现它们。我想在域和组中显示每个可用的选项,并根据用户属性选择/取消选择复选框。想知道我是否可以在管理员中执行此操作,或者我需要独立于管理员编写自己的视图。
5 回答
我认为内置小部件CheckboxSelectMultiple
可以满足您的需求。如果没有,您将不得不创建自己的小部件。小部件的文档是一个很好的起点。最简单的开始方法是从 Django 源中复制现有的小部件并对其进行修改。
准确地说,它是 Django 管理员在 ManyToManyField 的情况下选择显示的小部件。在这种情况下,您觉得它的 SelectMultiple 小部件对用户不太友好。
很简单的部分是,您始终可以在使用自己的 ModelForm 时选择小部件。但是如果你想在 Django Admin 中这样做,你需要一个往返。看一下这个。
from django.forms import widgets
from django.contrib import admin
class MyModelAdmin(admin.ModelAdmin):
def formfield_for_manytomany(self, db_field, request=None, **kwargs):
"""
Get a form Field for a ManyToManyField.
"""
# If it uses an intermediary model, don't show field in admin.
if db_field.rel.through is not None:
return None
if db_field.name in self.raw_id_fields:
kwargs['widget'] = admin.widgets.ManyToManyRawIdWidget(db_field.rel)
kwargs['help_text'] = ''
elif db_field.name in (list(self.filter_vertical) + list(self.filter_horizontal)):
kwargs['widget'] = admin.widgets.FilteredSelectMultiple(db_field.verbose_name, (db_field.name in self.filter_vertical))
else:
kwargs['widget'] = widgets.CheckboxSelectMultiple()
kwargs['help_text'] = ''
return db_field.formfield(**kwargs)
现在,在 admin.py 中定义您的例程管理员为
class SomeModelAdmin(MyModelAdmin):
search_fields = ['foo', 'bar']
list_display = ('foo',)
ordering = ('-bar',)
admin.site.register(SomeModel, SomeModelAdmin)
您现在将在 DJango Admin 中获得复选框。当然,您将需要一些 CSS 更改。
它实际上在管理员中默认使用模型表单。所以,你需要覆盖它。
from django import forms
from django.forms import widgets
class DomainForm(forms.ModelForm):
field2 = YourField(widget=widgets.CheckboxSelectMultiple)
class Meta:
model = Domain()
fields = ('field1', 'field2')
所以,在这种情况下,我已经覆盖了默认的 FIELD2 字段类型。
I'm not completely sure I understand what you are attempting to do, but perhaps something like filter_horizontal would do what you want.
您可以更改 django 管理界面字段小部件
from django.forms import widgets
class UserAdmin(admin.ModelAdmin):
model = User
def formfield_for_manytomany(self, db_field, request=None, **kwargs):
if db_field.name == 'domain' or db_field.name == 'groups':
kwargs['widget'] = widgets.CheckboxSelectMultiple()
# or just make all the manytomany fields as checkbox
kwargs['widget'] = widgets.CheckboxSelectMultiple()
return db_field.formfield(**kwargs)
# for other field
def formfield_for_dbfield(self, db_field, **kwargs):
.....
return super(UserAdmin, self).formfield_for_dbfield(db_field, **kwargs)
admin.site.register(User, UserAdmin)