使用多对多模型字段时如何在 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
,问题已解决。
出于某种原因,我的 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
,问题已解决。