16

我有一个具有 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_CHOICESMyModelAdmin.

我是否覆盖小部件?我需要覆盖整个表格吗?

4

7 回答 7

24
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

于 2012-09-27T16:54:42.560 回答
5

您需要覆盖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的 's中__init__定义MY_CHOICES将要发生的事情并在那里分配表单实例:

祝你好运!:)

于 2012-09-27T16:56:46.210 回答
5

您可以覆盖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)

formfield_for_choice_field

于 2018-03-29T14:06:07.420 回答
5

您不需要自定义表单。

这是您需要的最低要求:

# 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)
于 2018-12-29T21:08:05.363 回答
0

杰拉德的回答中,如果您保留:

def __init__(self, stuff_choices=(), *args, **kwargs):

那么当您尝试从管理员添加新模型时,您将始终得到“此字段是必需的”。对于所有必填字段。

您应该stuff_choices=()从初始化中删除:

def __init__(self,*args, **kwargs):
于 2014-01-21T09:20:36.193 回答
0

您需要考虑如何在数据库级别存储数据。我建议这样做:

  1. 运行这个 pip 命令:pip install django-multiselectfield
  2. 在您的 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)
    
  3. 在您的 settings.py 中:

     INSTALLED_APPS = (
          'django.contrib.auth',
          'django.contrib.contenttypes',
          'django.contrib.sessions',
          'django.contrib.sites',
          'django.contrib.admin',
    
          #.....................#
    
          'multiselectfield',
    )
    
  4. 观看魔法发生!

资源:

于 2016-12-14T16:43:11.583 回答
0

下面的解决方案可以立即与 Postgres 的 special 一起使用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)

于 2020-07-31T14:08:02.733 回答