37

I have a model with a boolean value like that:

class TagCat(models.Model):
    by_admin = models.BooleanField(default=True) 

This appears as a checkbox in admin.

  1. How could I use this as a radio button in admin?
  2. Also, how do I make it be always with a certain selected value in admin?
  3. Also, I want the default value to be the opposite, when a non-admin user adds a TagCat. This field should be hidden from him.

Can someone tell me how to do this? Django documentation doesn't seem to go in such details.

webjunkie
  • 6,891
  • 7
  • 46
  • 43
mgPePe
  • 5,677
  • 12
  • 52
  • 85
  • Your first question is answered in http://stackoverflow.com/questions/854683/django-booleanfield-as-radio-buttons – Dominic Rodger Dec 02 '10 at 17:02
  • I did read that question. The answers seem to say how to replace it in general, while I want that specific case only to be radio. The last answer seem to be what I want, and I tried it and didn't work, because in the admin, only the label appears. I will paste my code as 'UPDATE 1' – mgPePe Dec 02 '10 at 17:15

4 Answers4

56

UPDATE 1: Code that gets me done with 1) (don't forget tot pass CHOICES to the BooleanField in the model)

from main.models import TagCat
from django.contrib import admin
from django import forms

class MyTagCatAdminForm(forms.ModelForm):
    class Meta:
        model = TagCat
        widgets = {
            'by_admin': forms.RadioSelect
        }
        fields = '__all__' # required for Django 3.x
    
class TagCatAdmin(admin.ModelAdmin):
    form = MyTagCatAdminForm


admin.site.register(TagCat, TagCatAdmin)

The radio buttons appear ugly and displaced, but at least, they work

  1. I solved with following info in MyModel.py:
BYADMIN_CHOICES = (
    (1, "Yes"),
    (0, "No"),
)

class TagCat(models.Model):
    by_admin = models.BooleanField(choices=BYADMIN_CHOICES,default=1)
M Somerville
  • 4,499
  • 30
  • 38
mgPePe
  • 5,677
  • 12
  • 52
  • 85
51

There is another way to do this that is, IMO much easier if you want every field of the same type to have the same widget. This is done by specifying a formfield_overrides to the ModelAdmin. For example:

from django.forms.widgets import Textarea

class MyModelAdmin(admin.ModelAdmin):
    formfield_overrides = {
        models.TextField: {'widget': Textarea},
    }

More in the docs: https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.formfield_overrides

ropable
  • 1,547
  • 1
  • 19
  • 31
joshcartme
  • 2,717
  • 1
  • 22
  • 34
  • Use `form_class` if you want to override field type; e.g. ignore commas in Decimals: `formfield_overrides = {models.DecimalField: {'form_class': MyDecimalField}}` – Dispenser Feb 21 '20 at 14:13
  • https://stackoverflow.com/questions/910169/resize-fields-in-django-admin. probably help with the code – Michael Halim Sep 25 '22 at 04:38
15

Here is a more dynamic extension of mgPePe's response:

class MyAdminForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(MyAdminForm, self).__init__(*args, **kwargs)

        self.fields['by_admin'].label = 'My new label'
        self.fields['by_admin'].widget = forms.RadioSelect()


    class Meta:
        model = TagCat

class MyAdmin(admin.ModelAdmin):
    fields = ['name', 'by_admin']
    form = MyAdminForm

This way you get full control over the fields.

merwok
  • 6,779
  • 1
  • 28
  • 42
0

You can also override this in the Admin class via the get_form() method.


class MyAdmin(admin.ModelAdmin):
    fields = ['name', 'by_admin']
    form = MyAdminForm

    def get_form(self, request, obj=None, change=False, **kwargs):
         form = super().get_form(request, obj, change, **kwargs)
         form.base_fields["by_admin"].label = 'My new label'
         form.base_fields["by_admin"].widget = forms.RadioSelect()
         return form

monkut
  • 42,176
  • 24
  • 124
  • 155