Django: why the manytomany choice box only has on

2019-08-03 05:30发布

I have extended the group model, where I added some manytomany fields, and in the admin page, it likes this:

enter image description here

However, what I expected is this:

enter image description here

Here is how I implemented the m2m field:

class MyGroup(ProfileGroup):
    mobile = models.CharField(max_length = 15)
    email = models.CharField(max_length = 15)
    c_annotates = models.ManyToManyField(Annotation, verbose_name=_('annotation'), blank=True, null=True)
    c_locations = models.ManyToManyField(Location, verbose_name=_('locations'), blank=True, null=True)

And in the database there is a relational form which contains the pairs of group_id and location_id.

Is there anyone who knows how to do it? Thanks!

EDIT:

enter image description here

I implemented as above, the multiple select box actually shows up, but it cannot save... (Sorry, I was working on a virtual machine and it's offline now, so I have to clip the code from screen)

3条回答
聊天终结者
2楼-- · 2019-08-03 06:00

Problem solved. It can save the multiple choice field now.

class GroupAdminForm(forms.ModelForm):
    users = forms.ModelMultipleChoiceField(queryset=User.objects.all(),
                                       widget=FilteredSelectMultiple('Users', False),
                                       required=False)
    locations = forms.ModelMultipleChoiceField(queryset=Location.objects.all(),
                                       widget=FilteredSelectMultiple('Location', False),
                                       required=False)
    class Meta:
        model = Group

    def __init__(self, *args, **kwargs):
        instance = kwargs.get('instance', None)
            if instance is not None:
            initial = kwargs.get('initial', {})
            initial['users'] = instance.user_set.all()
            initial['locations'] = instance.c_locations.all()
            kwargs['initial'] = initial
        super(GroupAdminForm, self).__init__(*args, **kwargs)

    def save(self, commit=True):
        group = super(GroupAdminForm, self).save(commit=commit)

        if commit:
            group.user_set = self.cleaned_data['users']
            group.locations = self.cleaned_data['locations']
        else:
            old_save_m2m = self.save_m2m
            def new_save_m2m():
                old_save_m2m()
                group.user_set = self.cleaned_data['users']
                group.location_set = self.cleaned_data['locations']
            self.save_m2m = new_save_m2m
        return group
查看更多
\"骚年 ilove
3楼-- · 2019-08-03 06:12

latest 2017

govt_job_post is model having qualification as ManyToMany field.

class gjobs(admin.ModelAdmin):
    filter_horizontal = ('qualification',)

admin.site.register(govt_job_post, gjobs)

查看更多
乱世女痞
4楼-- · 2019-08-03 06:14

Either I am overlooking something that makes your situation unusual or you are making it harder than it needs to be. Since you're using the admin, the vast majority of the code necessary to use the admin's more convenient multiselects is already available. All you should need to do is declare your ManyToMany fields, as you have, and then include those fields in your admin class's filter_horizontal attribute. Or filter_vertical if you want the boxes stacked, but your screenshot shows the horizontal case.

This by itself does not require a custom form for your admin.

查看更多
登录 后发表回答