2011-03-24 44 views
13

this question相關,但在其上擴展 - 如何在formset中使用此技術?Django formset設置當前用戶

我想在窗體中使用當前登錄的用戶,但我在formset中使用窗體。引用的單一表單解決方案是將request.user傳遞給init中的表單和進程。如何在formset中爲每個表單添加kwargs?

實施例在我的代碼:

在forms.py

class NewStudentForm (forms.Form): 
    username = forms.RegexField(label=_("Username"), max_length=30, regex=r'^\w+$', 
     help_text = _("Required. 30 characters or fewer. Alphanumeric characters only (letters, digits and underscores)."), 
     error_message = _("This value must contain only letters, numbers and underscores.")) 
    first_name = forms.CharField(label=_('first name'), max_length=30) 
    last_name = forms.CharField(label=_('last name'), max_length=30,) 
    email = forms.EmailField(label=_('e-mail address')) 
    password = forms.CharField(label=_('password'), max_length=64,) 

    class Meta: 
     model = User 
     fields = ("username","first_name", "last_name", "email", "password") 

    def __init__(self, *args, **kwargs): 
     self._user = kwargs.pop('user') 
     super(NewStudentForm, self).__init__(*args, **kwargs) 


    def save(self, commit=True): 
     user = super(NewStudentForm, self).save(commit=False) 
     user.set_password(self.cleaned_data["password"]) 
     if commit: 
      user.save() 
      profile = Profile.objects.create_profile(user) 
      profile.activiation_key = profile.ACTIVATED_KEY 
      profile.authorized = True 
      profile.save() 
      user.is_active=True 
      user.save() 
      student = models.Student() 
      student.user = user 
      student.teacher = self._user 
      student.plaintext_pwd = self.cleaned_data["password"] 
      student.save() 
     return UserWarning 

然後

在views.py

@login_required 
def new_student(request): 
    from django.forms.formsets import formset_factory 
    try: 
     if request.method == 'GET': 
      newStudentFormset = formset_factory(forms.NewStudentForm, extra=2) 
      formset = newStudentFormset() 
      return shortcuts.render_to_response('NewStudent.html', { 'newStudentFormSet':formset, 'active_username': request.user.username }) 
     elif request.method == 'POST': 
      if LOGIN_FORM_KEY in request.POST: 
       return _handle_login(request) 
      data = request.POST.copy() 
      newStudentFormset = formset_factory(forms.NewStudentForm) 
      formset = newStudentFormset(data) ### Pass current user to formset? ### 
      if formset.is_valid(): 
       formset.save() 
       request.user.message_set.create(message="Save successful.") 
       return shortcuts.redirect(student) 
      else: 
       return shortcuts.render_to_response('NewStudent.html', { 'newStudentFormSet':formset, 'active_username': request.user.username, 'error_message':formset.errors}) 
     return http.HttpResponseNotAllowed(['GET', 'POST']) 
    except models.Student.DoesNotExist: 
     return http.HttpResponseNotFound('<h1>Requested Student not found</h1>') 

回答

18

通過添加一個擴展了BaseFormSet的類,您可以添加自定義代碼以將參數傳遞給表單。

forms.py

class NewStudentFormSet(BaseFormSet): 
    def __init__(self, *args, **kwargs): 
     self.user = kwargs.pop('user', None) 
     super(NewStudentFormSet, self).__init__(*args, **kwargs) 

    def _construct_forms(self): 
     self.forms = [] 
     for i in xrange(self.total_form_count()): 
      self.forms.append(self._construct_form(i, user=self.user)) 

然後在views.py

# ... 

data = request.POST.copy() 
newStudentFormset = formset_factory(forms.NewStudentForm, formset=forms.NewStudentFormSet) 
formset = newStudentFormset(data, user=request.user) 

# ... 

感謝Ashok Raavi

0

這裏是關於傳遞形式參數以一個formset一個類似的問題:

Django Passing Custom Form Parameters to Formset

就我個人而言,我喜歡關於在函數中動態構建表單類的第二個答案,因爲它的實現非常快並且易於理解。

5

我寧可在視圖中直接迭代形式:

for form in formset.forms: 
    form.user = request.user 
    formset.save() 
  • 它避免產生不必要的BaseFormSet
  • 它是清潔
+5

應該'formset.save()'是循環的一部分嗎?或者不應該用'form.save()'代替 – 2012-09-14 14:47:24

4

基於聖保羅檢查答案(這沒真的適合我的情況)。

我喜歡不寫自定義BaseFormSet繼承類的想法。

if formset.is_valid(): 
    new_instances = formset.save(commit=False) 
    for new_instance in new_instances: 
     new_instance.user = request.user 
     new_instance.save() 
2

我試圖自相似的解決方案,但BaseFormSet沒有在我的Django 1.6工作。

我遵循的步驟:https://code.djangoproject.com/ticket/17478和工作對我來說是這樣的:

class NewStudentFormSet(BaseFormSet): 
     def __init__(self, *args, **kwargs): 
      self.user = kwargs.pop('user',None) 
      super(NewStudentFormSet, self).__init__(*args, **kwargs) 
      for form in self.forms: 
       form.empty_permitted = False 

     def _construct_forms(self): 
      if hasattr(self,"_forms"): 
       return self._forms 
      self._forms = [] 
      for i in xrange(self.total_form_count()): 
       self._forms.append(self._construct_form(i, user=self.user)) 

      return self._forms 

     forms = property(_construct_forms)