Django admin choice field

前端 未结 7 1641
日久生厌
日久生厌 2020-12-18 22:48

I have a model that has a CharField and in the admin I want to add choices to the widget. The reason for this is I\'m using a proxy model and there are a bunch of models tha

相关标签:
7条回答
  • 2020-12-18 22:51

    in Gerard's answer, if you keep :

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

    then when you will try to add new model from admin, you will always get 'This field is required.' for all required fields.

    you should remove stuff_choices=() from initialization:

    def __init__(self,*args, **kwargs):
    
    0 讨论(0)
  • 2020-12-18 22:51

    Below a solution that works immediately with 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)

    0 讨论(0)
  • 2020-12-18 22:53
    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)
    

    See: https://docs.djangoproject.com/en/dev/ref/forms/fields/#choicefield

    0 讨论(0)
  • 2020-12-18 22:56

    You need to override the form the ModelAdmin is going to use:

    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
    

    If you need your choices to be dynamic, maybe you could do something similar to:

    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
    

    and in your ModelAdmin's __init__ define what MY_CHOICES is going to be and assign the form instance there instead:

    Good luck! :)

    0 讨论(0)
  • 2020-12-18 23:04

    You can override formfield_for_choice_field() that way you don't need to create a new form.

    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)
    

    See formfield_for_choice_field

    0 讨论(0)
  • 2020-12-18 23:07

    You don't need a custom form.

    This is the minimum you need:

    # 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)
    
    0 讨论(0)
提交回复
热议问题