2010-06-19 4 views
15

'through'클래스 테이블을 포함하고 m2m 데이터를 저장하는 데 문제가 있습니다. 선택한 모든 멤버 (양식에 선택된)를 쓰루 테이블에 저장하려고합니다. 하지만보기에서 '통해'테이블을 초기화하는 방법을 모르겠습니다.Django m2m form "through"테이블을 저장합니다.

내 코드 :

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() 

은 어떻게 회원 테이블의 회원을 초기화해야 잘 채워이란?

답변

19

을 필요 가능성이 높습니다 중개 테이블을 사용하는 경우 POST 데이터를 수동으로 처리하고 모든 필수 필드 (similar problem)가있는 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()) 

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) 

하지만 루프에서 일부 DB 쿼리를 수행하는 참고는하지 않은 일반적으로 (성능 측면에서) 좋은 아이디어.

+0

그게 다야! 저는 파이썬을 처음 접했을 때 정말 고민 거리가되었습니다. Thnx 많이! – dana

+0

질문 : 강의실 작성자를 구성원 (required.user)으로 추가하고 해당 목록에 추가하려면 어떻게해야합니까? 감사합니다. – dana

+1

내가 당신의 요점을 가지고 있는지 확실하지 않습니다. 당신은 새로운 멤버쉽 객체 (루프 외부)를 생성하여 사용자와 교실 간의 새로운 연결을 생성 할 수 있습니다 (membership = Membership.objects.create (member = request.user, classroom = new_obj) ) member_id를 추가로 전달할 수 있습니다. POST의 id와 request.user의 id)는 기존 코드 (for 루프)를 사용하여 생성됩니다. 두 번째 옵션의 경우 양식의 일부 숨겨진 필드에 request.user.id를 저장해야합니다. – dzida

1

는 또한 회원 교실을 지정해야합니다

membership = Membership(member = request.user, 
         classroom=new_obj) #if new_obj if your classroom 
membership.save() 

난 당신이 또한 accept = models.BooleanField(User)User을 제거해야합니다 같아요. auto_now을 사용하는 경우 절약시 날짜를 설정하지 않아도됩니다.

membership = Membership(member = HERE SELECTED ITEMS FROM FORM,classroom=new_obj) 
membership.save() 

form.save_m2m() 

로하지만 :하지만 어쩌면`auto_now_add 당신이 대체 할 수있는 (안 중간 테이블을 통해) 정상 M2M 관계를 사용하는 경우 ( http://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.DateField)

+0

감사는 자연 솔루션을 보인다 문제는 new_obj입니다 - 내 교실이 아직 생성되지 않은 것 같아요. 이제 new_obj.save() 다음에 위 선언을 추가했으며 새로운 오류는 다음과 같습니다. 중간 모델을 지정하는 ManyToManyField에 값을 설정할 수 없습니다. 대신 회원 관리자를 사용하십시오. :) – dana

+0

Memberhip.objects.create()를 시도해보십시오. 그러나 classromm 객체를 지정하는 것을 잊지 마십시오! –

+0

몇 년 전부터 질문을 다시 올리지 않아서 죄송합니다.하지만 레코드를 만들지 않고 업데이트하고 싶다면 어떻게해야합니까? 레코드가 이미 존재한다면, objects.create는 update가 아닌 새로운 레코드를 추가하지 않습니까? – nlr25

0

이것은 form_valid 메소드를 사용하는 유사하지만 다른 응용 프로그램의 일반 UpdateForm 클래스 기반보기 (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) 
1

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 = 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 classroom 
관련 문제