我在保存m2m数据方面遇到了麻烦,其中包含一个"通过"类表.我想在直通表中保存所有选定的成员(在表单中选择).但我不知道如何在视图中初始化"通过"表.
我的代码:
class Classroom(models.Model):
user = models.ForeignKey(User, related_name = 'classroom_creator')
classname = models.CharField(max_length=140, unique = True)
date = models.DateTimeField(auto_now=True)
open_class = models.BooleanField(default=True)
members = models.ManyToManyField(User,related_name="list of invited members", through = 'Membership')
class Membership(models.Model):
accept = models.BooleanField(User)
date = models.DateTimeField(auto_now = True)
classroom = models.ForeignKey(Classroom, related_name = 'classroom_membership')
member = models.ForeignKey(User, related_name = 'user_membership')
Run Code Online (Sandbox Code Playgroud)
并在视图中:
def save_classroom(request):
classroom_instance = Classroom()
if request.method == 'POST':
form = ClassroomForm(request.POST, request.FILES, user = request.user)
if form.is_valid():
new_obj = form.save(commit=False)
new_obj.user = request.user
new_obj.save()
membership = Membership(member = HERE SELECTED ITEMS FROM FORM,classroom=new_obj)
membership.save()
Run Code Online (Sandbox Code Playgroud)
我应该如何初始化成员资格表的成员资格?
dzi*_*ida 22
如果使用正常m2m关系(不通过中间表),您可以替换:
membership = Membership(member = HERE SELECTED ITEMS FROM FORM,classroom=new_obj)
membership.save()
Run Code Online (Sandbox Code Playgroud)
同
form.save_m2m()
Run Code Online (Sandbox Code Playgroud)
但是在使用中间表的情况下,您需要手动处理POST数据并创建包含所有必填字段的Membership对象(类似问题).最基本的解决方案是将您的视图更改为:
def save_classroom(request):
if request.method == 'POST':
form = ClassroomForm(request.POST, request.FILES)
if form.is_valid():
new_obj = form.save(commit=False)
new_obj.user = request.user
new_obj.save()
for member_id in request.POST.getlist('members'):
membership = Membership.objects.create(member_id = int(member_id), classroom = new_obj)
return HttpResponseRedirect('/')
else:
form = ClassroomForm()
return render_to_response('save_classroom.html', locals())
Run Code Online (Sandbox Code Playgroud)
请注意如何操作request.POST(.getlist).这是因为post和get是QueryDict对象,它们有一些含义(request.POST ['members']将始终返回一个对象!).
您可以修改此代码以使其更可靠(错误处理等),并且更详细,例如:
member = get_object_or_404(User, pk = member_id)
membership = Membership.objects.create(member = member , classroom = new_obj)
Run Code Online (Sandbox Code Playgroud)
但请注意,您正在循环中执行一些数据库查询,这通常不是一个好主意(在性能方面).
就像dzida所做的一样,但是使用form.cleaned_data而不是request.post:
def save_classroom(request):
if request.method == 'POST':
form = ClassroomForm(request.POST, request.FILES)
if form.is_valid():
new_obj = form.save(commit=False)
new_obj.user = request.user
new_obj.save()
for member in form.cleaned_data['members'].all():
Membership.objects.create(member = member, classroom = new_obj)
return HttpResponseRedirect('/')
else:
form = ClassroomForm()
return render_to_response('save_classroom.html', locals())
Run Code Online (Sandbox Code Playgroud)
您还需要考虑一些成员资格可能会被删除,因此:
def save_classroom(request):
if request.method == 'POST':
form = ClassroomForm(request.POST, request.FILES)
if form.is_valid():
new_obj = form.save(commit=False)
new_obj.user = request.user
new_obj.save()
final_members = form.cleaned_data['members'].all()
initial_members = form.initial['members'].all()
# create and save new members
for member in final_members:
if member not in initial_members:
Membership.objects.create(member = member, classroom = new_obj)
# delete old members that were removed from the form
for member in initial_members:
if member not in final_members:
Membership.objects.filter(member = member, classroom = new_obj).delete()
return HttpResponseRedirect('/')
else:
form = ClassroomForm()
return render_to_response('save_classroom.html', locals())
Run Code Online (Sandbox Code Playgroud)
如果使用模型形式(例如在通用CBV:中form_class=ClassroomForm
),请覆盖保存逻辑并将其放在save
方法中,例如:
ClassroomForm(forms.ModelForm):
members = ModelMultipleChoiceField(
queryset=Classroom.objects.all(),
widget=SelectMultiple
)
def save(self, commit=True):
classroom = super().save(commit=False)
if commit:
classroom.save()
if 'members' in self.changed_data:
final_members = self.cleaned_data['members'].all()
initial_members = self.initial['members']
# create and save new members
for member in final_members:
if member not in initial_members:
Membership.objects.create(member = member, classroom = new_obj)
# delete old members that were removed from the form
for member in initial_members:
if member not in final_members:
Membership.objects.filter(member = member, classroom = new_obj).delete()
return classroom
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
8483 次 |
最近记录: |