我正在尝试创建一个 CheckboxSelectMultiple 小部件,其中列出了我项目的所有内容类型。在 ModelForm 中定义 MultipleChoiceField 字段时,我首先使用基本小部件,它工作正常。我现在想让它成为一个自定义小部件,我可以通过应用程序将其导入任何项目。
这是我正在使用的代码:
# myapp/models.py
from django.db import models
class Tiger(models.Model):
color = models.CharField(max_length=100)
# myapp/admin.py
from django import forms
from django.contrib import admin
from django.contrib.contenttypes.models import ContentType
from myapp.models import Tiger
class TigerForm(forms.ModelForm):
"""
Default ModelForm that will be overriden.
"""
class Meta:
model = Tiger
这是我定义我的自定义小部件的地方。我猜我没有正确传递值列表(请参阅代码中的注释)。
class TigerWidget(forms.CheckboxSelectMultiple):
"""
Custom widget that displays a list of checkboxes for each content type.
The goal is to make it generic enough to put it in an external app
that can be imported into any project.
"""
def __init__(self, attrs=None, choices=()):
# List all content types
content_types = ContentType.objects.all()
classes = tuple([(c.model, c.name) for c in content_types])
# Define widget choices as the list of these content types
self.choices = classes # I am guessing it should be done differently?
# Select all of them by default
self.initial = [c[0] for c in classes]
# Same behavior as parent
super(TigerWidget, self).__init__(attrs)
以下是使用它的其余类。
class TigerCustomForm(TigerForm):
"""
Custom form that adds a field using the custom widget to the form.
"""
# content_types = ContentType.objects.all()
# classes = tuple([(c.model, c.name) for c in content_types])
# This works fine.
# nickname = forms.MultipleChoiceField(
# widget=forms.CheckboxSelectMultiple,
# choices=classes,
# # Select all by default
# initial=[c[0] for c in classes]
# )
# This does not. An empty list (<ul></ul>) is rendered in the place of the widget.
nickname = forms.MultipleChoiceField(
widget=TigerWidget,
)
class TigerAdmin(admin.ModelAdmin):
form = TigerCustomForm
admin.site.register(Tiger, TigerAdmin)
admin.site.register(ContentType)
在此先感谢您的帮助。