题
我有麻烦中救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')
和看法:
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()
我应该如何初始化的成员资格为成员资格表,以填充的吗?
解决方案
在情况下的使用正常的m2m关系(不是通过中介表)你可以代替:
membership = Membership(member = HERE SELECTED ITEMS FROM FORM,classroom=new_obj)
membership.save()
与
form.save_m2m()
但在的情况下使用中间表需要以手工方式处理后的数据和创建成员资格的目的与所有需要的领域(类似的问题).最基本的解决方案是改变你的看法是这样的:
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())
注意如何请求。后操纵(.getlist).这是因为员额而得到的是 QueryDict 对象,其中有一些影响(请求。后["成员"]将返回总是一个对象!).
你可以修改这个代码,以获得更可靠的(错误处理,等等), 更详细,例如:
member = get_object_or_404(User, pk = member_id)
membership = Membership.objects.create(member = member , classroom = new_obj)
但请注意,正在执行一些数据库中的查询一个循环,这不是一个好主意,在一般的(在条款的性能)。
其他提示
就像dzida所做的一样,但使用form.cleaned_data而不是请求。
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())
您还需要考虑可能会删除某些会员资格,因此:
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())
如果您使用模型表格(例如在通用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
您还需要指定会员资格的教室:
membership = Membership(member = request.user,
classroom=new_obj) #if new_obj if your classroom
membership.save()
我想你也应该删除 User
在 accept = models.BooleanField(User)
. 。如果您正在使用,则不必在保存时设置日期 auto_now
呢但是也许`auto_now_add更可能需要(http://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.datefield)
这就是我使用Form_valid方法的类似但不同的应用程序中的基于通用更新的类别视图(DJANGO 1.8)中进行的。
def form_valid(self, form):
"""
If the form is valid, save the associated model.
"""
self.object.members.clear()
self.object = form.save(commit=False)
self.object.user = self.request.user
self.object.save()
list_of_members = form.cleaned_data['members']
ClassRoom.objects.bulk_create([
Membership(
Course=self.object,
member=member_person,
order=num)
for num, member_person in enumerate(list_of_members)
])
return super(ModelFormMixin, self).form_valid(form)