代码之家  ›  专栏  ›  技术社区  ›  ElectRocnic

Django ModelMultipleChoiceField未保存

  •  0
  • ElectRocnic  · 技术社区  · 6 年前

    我在django管理员那里有很多地方 ModelMultipleChoiceField 工作:

    Working ManyToMany Admin UI Element

    当我从左到右添加一个元素并在管理用户界面中单击“保存”,然后重新加载详细信息页面,其中 多回波场模型

    此工作模型的代码如下所示:

    # project/account/models.py
    from django.db import models
    from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
    from model_utils import Choices
    
    class User(AbstractBaseUser, PermissionsMixin):
        following = models.ManyToManyField('self', related_name='followers', blank=True, symmetrical=False)
    
    # project/account/forms.py
    from django import forms
    from django.contrib.auth import get_user_model
    from django.contrib.admin.widgets import FilteredSelectMultiple
    from .models import User
    
    class UserChangeForm(forms.ModelForm):
        following = forms.ModelMultipleChoiceField(
            queryset=User.objects.all(),
            required=False,
            widget=FilteredSelectMultiple(
                verbose_name='Following',
                is_stacked=False
            )
        )
        followers = forms.ModelMultipleChoiceField(
            queryset=User.objects.all(),
            required=False,
            widget=FilteredSelectMultiple(
                verbose_name='Followers',
                is_stacked=False
            )
        )
    
        class Meta:
            model = get_user_model()
            fields = ('following', 'followers')
    
        def __init__(self, *args, **kwargs):
            super(UserChangeForm, self).__init__(*args, **kwargs)
    
            if self.instance and self.instance.pk:
                self.fields['following'] = forms.ModelMultipleChoiceField(
                    queryset=User.objects.all().exclude(pk=self.instance.pk),
                    required=False,
                    widget=FilteredSelectMultiple(
                        verbose_name='Following',
                        is_stacked=False
                    )
                )
                self.fields['followers'] = forms.ModelMultipleChoiceField(
                    queryset=User.objects.all().exclude(pk=self.instance.pk),
                    required=False,
                    widget=FilteredSelectMultiple(
                        verbose_name='Followers',
                        is_stacked=False
                    )
                )
                self.fields['followers'].initial = self.instance.followers.all()
    
    # project/account/admin.py
    from django.contrib.auth import get_user_model
    from django.contrib import admin
    from django.contrib.auth.models import Group
    from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
    from .models import User
    from .forms import UserChangeForm, UserCreationForm
    
    class Admin(BaseUserAdmin):
        form = UserChangeForm
        model = get_user_model()
    
        fieldsets = (
            ('Following / Followers', {'fields': ('following', 'followers')}),
        )
    
    admin.site.register(User, Admin)
    admin.site.unregister(Group)
    

    这将按预期在管理面板中保存修改的不动产。

    但现在我有了另一个用例,我想有三个不同的 多回波场模型 对于同一型号:

    # project/account/models.py
    from django.db import models
    from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
    from model_utils import Choices
    from shared_models.models import Badge
    
    class User(AbstractBaseUser, PermissionsMixin):
        badges = models.ManyToManyField(Badge, related_name='owners', blank=True)
    
    # project/shared_models/models.py
    from django.db import models
    from model_utils import Choices
    
    class Badge(models.Model):
        BADGE_TYPES = Choices('bronze', 'silver', 'gold')
    
        type = models.CharField(choices=BADGE_TYPES, max_length=10)
        description = models.CharField(blank=False, max_length=1500)
    
        class Meta:
            app_label = 'shared_models'
    
        def __set__(self, instance, value):
            self.description = value
    
    # project/account/forms.py
    from django import forms
    from django.contrib.auth import get_user_model
    from django.contrib.admin.widgets import FilteredSelectMultiple
    from shared_models.models import Badge
    from .models import User
    
    def general_model_multiple_choice_field_filter_type(model, verbose_name, filter_by_type):
        queryset = model.objects.all()
        if filter:
            queryset = queryset.filter(type=filter_by_type)
        return forms.ModelMultipleChoiceField(
            queryset=queryset,
            required=False,
            widget=FilteredSelectMultiple(
                verbose_name=verbose_name,
                is_stacked=False
            )
        )
    
    class UserChangeForm(forms.ModelForm):
        bronze_badges = general_model_multiple_choice_field_filter_type(model=Badge, verbose_name='Bronze Badges', filter_by_type='bronze')
        silver_badges = general_model_multiple_choice_field_filter_type(model=Badge, verbose_name='Silver Badges', filter_by_type='silver')
        gold_badges = general_model_multiple_choice_field_filter_type(model=Badge, verbose_name='Gold Badges', filter_by_type='gold')
    
        class Meta:
            model = get_user_model()
            fields = ('bronze_badges',
                      'silver_badges',
                      'gold_badges')
    
        def __init__(self, *args, **kwargs):
            super(UserChangeForm, self).__init__(*args, **kwargs)
    
            if self.instance and self.instance.pk:
                self.fields['bronze_badges'] = general_model_multiple_choice_field_filter_type(Badge,
                                                'Bronze Badges',
                                                filter_by_type='bronze')
                self.fields['silver_badges'] = general_model_multiple_choice_field_filter_type(Badge,
                                                'Silver Badges',
                                                filter_by_type='silver')
                self.fields['gold_badges'] = general_model_multiple_choice_field_filter_type(Badge,
                                                'Gold Badges',
                                                filter_by_type='gold')
    
    # project/account/admin.py
    from django.contrib.auth import get_user_model
    from django.contrib import admin
    from django.contrib.auth.models import Group
    from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
    from .models import User
    from django.db.models import Q
    from .forms import UserChangeForm, UserCreationForm
    
    class Admin(BaseUserAdmin):
        form = UserChangeForm
        model = get_user_model()
    
        fieldsets = (
            ('Badges', {'fields': ('bronze_badges', 'silver_badges', 'gold_badges')}),
        )
    
    admin.site.register(User, Admin)
    admin.site.unregister(Group)
    

    但是现在,当我尝试在UI元素的“choosed”部分添加一些徽章,然后单击“Save”,重新加载页面时,所选项目仍然在左侧,右侧将保持空白。post请求以302响应。

    Not saving ModelMultipleChoiceField

    那么如何让django保存对用户徽章领域?

    编辑 找到了一个完美地回答我需要什么的问题: Is there a model MultiField (any way to compose db models Fields in Django)? Or why would not that be a useful concept?

    0 回复  |  直到 6 年前