简体   繁体   中英

Django forms

I had asked a question pertaining to this. But I think it would be better to ask my question directly. I have a "User" table with manytomany relationship with two other tables "Domain" and "Groups". So in the admin interface I see the Groups and Domains as 2 ModelMultipleChoiceFields. But I want to present them on the UI in a more user friendly way. I would like to show each available choice in Domain and Group with a checkbox that is selected/unselected depending on the User properties. Was wondering if I can do this in admin or I need to write my own view independent of admin.

I think the built-in widget CheckboxSelectMultiple does what you want. If it doesn't, you're going to have to create your own widget. The documentation for widgets is a good place to start. The easiest way to start is by copying an existing widget from the Django source and modifying it.

Well to be precise its the widget that Django Admin choses to show in case of ManyToManyField. Here in this case its SelectMultiple widget which you feel, is less user friendly.

Well easy part is, you can always chose the widget while using your own ModelForm. But in case you want that in Django Admin you need a roundtrip. Check this out.

from django.forms import widgets
from django.contrib import admin

class MyModelAdmin(admin.ModelAdmin):
    def formfield_for_manytomany(self, db_field, request=None, **kwargs):
    """
    Get a form Field for a ManyToManyField.
    """
    # If it uses an intermediary model, don't show field in admin.
    if db_field.rel.through is not None:
        return None

    if db_field.name in self.raw_id_fields:
        kwargs['widget'] = admin.widgets.ManyToManyRawIdWidget(db_field.rel)
        kwargs['help_text'] = ''
    elif db_field.name in (list(self.filter_vertical) + list(self.filter_horizontal)):
        kwargs['widget'] = admin.widgets.FilteredSelectMultiple(db_field.verbose_name, (db_field.name in self.filter_vertical))
    else:
        kwargs['widget'] = widgets.CheckboxSelectMultiple()
        kwargs['help_text'] = ''

    return db_field.formfield(**kwargs)

Now, define your routine admin in admin.py as

class SomeModelAdmin(MyModelAdmin):
    search_fields = ['foo', 'bar']
    list_display   = ('foo',)
    ordering       = ('-bar',)

admin.site.register(SomeModel, SomeModelAdmin)

You will get checkboxes in DJango Admin now. Of course you will need some CSS changes.

It actually uses model form by default in the admin. So, you need to overwrite it.

from django import forms
from django.forms import widgets

class DomainForm(forms.ModelForm):

    field2 = YourField(widget=widgets.CheckboxSelectMultiple)

    class Meta:
        model = Domain()
        fields = ('field1', 'field2')

So, In this case i have overwritten the default FIELD2 field type.

You can change django admin interface field widget

from django.forms import widgets

class UserAdmin(admin.ModelAdmin):
    model = User

    def formfield_for_manytomany(self, db_field, request=None, **kwargs):
        if db_field.name == 'domain' or db_field.name == 'groups':
        kwargs['widget'] = widgets.CheckboxSelectMultiple()

        # or just make all the manytomany fields as checkbox

        kwargs['widget'] = widgets.CheckboxSelectMultiple()

        return db_field.formfield(**kwargs)

    # for other field
    def formfield_for_dbfield(self, db_field, **kwargs):
        .....
        return super(UserAdmin, self).formfield_for_dbfield(db_field, **kwargs)

admin.site.register(User, UserAdmin)

I'm not completely sure I understand what you are attempting to do, but perhaps something like filter_horizontal would do what you want.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM