我有一个具有CharField的模型,在管理员中我想向窗口小部件添加选项。原因是我使用的是代理模型,并且有很多模型共享这个CharField,但它们各有不同的选择。
class MyModel(MyBaseModel):
stuff = models.CharField('Stuff', max_length=255, default=None)
class Meta:
proxy = True
class MyModelAdmin(admin.ModelAdmin):
fields = ('stuff',)
list_display = ('stuff',)
admin.site.register(MyModel, MyModelAdmin)
对于此模型,我想在MY_CHOICES
中使用MyModelAdmin
。
我是否覆盖小部件?我是否需要覆盖整个表单?
答案 0 :(得分:18)
from django.contrib import admin
from django import forms
class MyModel(MyBaseModel):
stuff = models.CharField('Stuff', max_length=255, default=None)
class Meta:
proxy = True
class MyModelForm(forms.ModelForm):
MY_CHOICES = (
('A', 'Choice A'),
('B', 'Choice B'),
)
stuff = forms.ChoiceField(choices=MY_CHOICES)
class MyModelAdmin(admin.ModelAdmin):
fields = ('stuff',)
list_display = ('stuff',)
form = MyModelForm
admin.site.register(MyModel, MyModelAdmin)
请参阅:https://docs.djangoproject.com/en/dev/ref/forms/fields/#choicefield
答案 1 :(得分:4)
您需要覆盖ModelAdmin
将要使用的表单:
class MyForm(forms.ModelForm):
stuff = forms.CharField('Stuff', max_length=255, choices=MY_CHOICES, default=None)
class Meta:
model = MyModel
fields = ('stuff', 'other_field', 'another_field')
class MyModelAdmin(admin.ModelAdmin):
fields = ('stuff',)
list_display = ('stuff',)
form = MyForm()
如果你需要你的选择是动态的,也许你可以做类似的事情:
class MyForm(forms.ModelForm):
stuff = forms.CharField('Stuff', max_length=255, choices=MY_CHOICES, default=None)
def __init__(self, stuff_choices=(), *args, **kwargs):
# receive a tupple/list for custom choices
super(MyForm, self).__init__(*args, **kwargs)
self.fields['stuff'].choices = stuff_choices
并在ModelAdmin
的{{1}}中定义__init__
将会是什么,并在那里指定表单实例:
答案 2 :(得分:3)
您可以以不需要创建新表单的方式覆盖formfield_for_choice_field()
。
class MyModelAdmin(admin.ModelAdmin):
def formfield_for_choice_field(self, db_field, request, **kwargs):
if db_field.name == 'status':
kwargs['choices'] = (
('accepted', 'Accepted'),
('denied', 'Denied'),
)
if request.user.is_superuser:
kwargs['choices'] += (('ready', 'Ready for deployment'),)
return super().formfield_for_choice_field(db_field, request, **kwargs)
答案 3 :(得分:2)
您不需要自定义表单。
这是您的最低要求:
# models.py
from __future__ import unicode_literals
from django.db import models
class Photo(models.Model):
CHOICES = (
('hero', 'Hero'),
('story', 'Our Story'),
)
name = models.CharField(max_length=250, null=False, choices=CHOICES)
# admin.py
from django.contrib import admin
from .models import Photo
class PhotoAdmin(admin.ModelAdmin):
list_display = ('name',)
admin.site.register(Photo, PhotoAdmin)
答案 4 :(得分:0)
在Gerard's answer,如果你保留:
def __init__(self, stuff_choices=(), *args, **kwargs):
然后当您尝试从管理员添加新模型时,您将始终获得“此字段是必需的”。对于所有必填字段。
您应该从初始化中删除stuff_choices=()
:
def __init__(self,*args, **kwargs):
答案 5 :(得分:0)
您需要考虑如何在数据库级别存储数据。 我建议这样做:
pip install django-multiselectfield
在models.py文件中:
from multiselectfield import MultiSelectField
MY_CHOICES = (('item_key1', 'Item title 1.1'),
('item_key2', 'Item title 1.2'),
('item_key3', 'Item title 1.3'),
('item_key4', 'Item title 1.4'),
('item_key5', 'Item title 1.5'))
class MyModel(models.Model):
my_field = MultiSelectField(choices=MY_CHOICES)
在您的settings.py中:
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.admin',
#.....................#
'multiselectfield',
)
观看MAGIC的发生!
来源:
答案 6 :(得分:0)
下面的解决方案可立即与Postgres的特殊ArrayField
一起使用:
# models.py
class MyModel(models.Model):
class Meta:
app_label = 'appname'
name = models.CharField(max_length=1000, blank=True)
ROLE_1 = 'r1'
ROLE_2 = 'r2'
ROLE_3 = 'r3'
ROLE_CHOICES = (
(ROLE_1, 'role 1 name'),
(ROLE_2, 'role 2 name'),
(ROLE_3, 'role 3 name'),
)
roles = ArrayField(
models.CharField(choices=ROLE_CHOICES, max_length=2, blank=True),
default=list
)
# admin.py
class MyModelForm(ModelForm):
roles = MultipleChoiceField(choices=MyModel.ROLE_CHOICES, widget=CheckboxSelectMultiple)
@admin.register(MyModel)
class MyModelAdmin(admin.ModelAdmin):
form = MyModelForm
list_display = ("pk", "name", "roles")
(Django 2.2)