使用多对多模型字段时如何在 Django UpdateView 中获取所有表单字段数据?

How to get all form field data in Django UpdateView when working with many-to-many model field?

出于某种原因,我的 UpdateView 没有显示选定的关联。该表单仅预填充了第一个表单字段数据结果、用户名和其他字段数据的 none。我怀疑这是由于查询了 ManytoMany 字段。我已经搜索并尝试了可能的解决方案,但没有任何效果。有什么想法吗?

Models.py

class Company(models.Model):
    """All company specific details. For each main manager, a company is created. The main manager can then add company members, creating for them their user accounts."""
    members = models.ManyToManyField(
        settings.AUTH_USER_MODEL, related_name='teams', through='CompanyMembership'
    )
    ...

class CompanyMembership(models.Model):
    """Acts as a gateway between User model and Company model"""
            STAFF = "STAFF", "Staff"
            MANAGERS = "MANAGERS", "Managers"
    my_company = models.ForeignKey(Company, on_delete=models.CASCADE)
    my_identity = models.ForeignKey(User, on_delete=models.CASCADE)
    my_role = models.CharField(max_length=100, choices=MemberTypes.choices, default=None)

class User(models.Model):
    """Users can be main managers or staff. Each main manager has their own Company. Many staff can belong to a single Company associated with a main manager."""
    username = models.CharField(_("Login Name"), blank=True, null=True, max_length=155, unique=True)
    ...
Views.py

class TeamMembersView(LoginRequiredMixin, CompanyMembershipCheckMixin, UserPassesTestMixin, ListView):
    """Lists all the company team members for the specific company"""
    model = Company
    template_name = 'users/dashboard/team.html'

    def test_func(self):
        user_obj = User.objects.get(id=self.request.user.id)
        return user_obj.groups.filter(name='Company_Main_Manager').exists()

    def get_context_data(self, **kwargs):
        context = super(TeamMembers, self).get_context_data(**kwargs)
        user_obj = User.objects.get(id=self.request.user.id)
        companymembership_obj = CompanyMembership.objects.get(my_identity=user_obj)
        company_obj = Company.objects.get(id=companymembership_obj.my_company.id)
        slug = company_obj.slug
        context['members'] = ecosystem_obj.members.all()
        context['slug'] = slug
        return context

class TeamMemberUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
    """Allows the main manager to change or update the specific staff member's user data"""
    model = User
    template_name = 'users/dashboard/user_create.html'
    form_class = TeamMemberCreateForm

    def test_func(self):
        user_obj = User.objects.get(id=self.request.user.id)
        return user_obj.groups.filter(name='Company_Main_Manager').exists()

    def get_context_data(self, **kwargs):
        data = super(TeamMemberUpdateView, self).get_context_data(**kwargs)
        if self.request.POST:
            data['member'] = TeamMemberCreateForm(self.request.POST, self.request.FILES)
        else:
            data['member'] = TeamMemberCreateForm()
        return data
   
    def form_valid(self, form):
        context = self.get_context_data()
        member = context['member']
        with transaction.atomic():
            form.instance.created_by = self.request.user
            self.object = form.save()
            if member.is_valid():
                member.instance = self.object
                member.save()
        return super(TeamMemberUpdateView, self).form_valid(form)

Forms.py
class TeamMemberCreateForm(ModelForm):
    """Allows the main manager to create (and update) a user account for additional staff members."""
    first_name = forms.CharField(max_length=200, help_text="Enter member's first name", required=True)
    last_name = forms.CharField(max_length=200, help_text="Enter member's last name")
    email = forms.EmailField(max_length=200, help_text="Member's primary email address")
    phone = forms.CharField(max_length=100, help_text="Primary phone number")
    position_title = forms.CharField(max_length=200, help_text="Member's job position or title for the company")

    class Meta(UserCreationForm.Meta):
        model = User
        exclude = ['company_name']

    @transaction.atomic
    def save(self):
        member_user = super().save(commit=False)
        member_user.firstname = self.cleaned_data.get('first_name')
        member_user.lastname = self.cleaned_data.get('last_name')
        member_user.email = self.cleaned_data.get('email')
        member_user.phone = self.cleaned_data.get('phone')
        member_user.is_company_main_manager = False
        member_user.is_active = True
        member_user.user_type = User.UserTypes.STAFF
        member_user.save()
        CompanyMembership.objects.create(my_company=ecosystem_create, my_identity=user, my_role=CompanyMembership.MemberTypes.STAFF)
        return member_user

例如,如果我是主要经理,我可以通过上面的表格为我的员工创建一个用户帐户。对于工作人员帐户,我输入 username="username_example", first_name="pete", last_name="smith", phone="333-333-3333" ,... 等等。 CreateView 按预期工作。创建、保存用户帐户等。不过,UpdateView 在本例中显示如下:

    username: username_example
    first name: 
    last name: 
    phone: 
    ... 
   # The first field of the form is pre-populated but none of the others... why?

您必须超级初始化您的表单并使用

重写该字段

def init(self, *args, **kwargs):

super(TeamMemberCreateForm, self).__init__(*args, **kwargs)

self.fields[your_field] = forms.ModelMultipleChoiceField(
                           queryset=Company.objects.all(),  
                           widget=forms.CheckboxSelectMultiple(attrs=
                     {'dir': 'ltr', 'type': "checkbox",'switch':"bool"}))

通过在 UpdateView 中使用 fields = ['username', 'firstname', 'lastname', 'email', 'phone'] 而不是 form_class = TeamMemberCreateForm,问题已解决。