【问题标题】:Django formset set current userDjango formset 设置当前用户
【发布时间】:2011-07-22 12:19:26
【问题描述】:

this question 相关,但对其进行扩展 - 我将如何在表单集中使用此技术?

我想在表单中使用当前登录的用户,但我在表单集中使用该表单。单个表单的参考解决方案是将 request.user 传递给表单并在 init 中处理。如何为表单集中的每个表单添加 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>')

【问题讨论】:

    标签: django django-forms django-views


    【解决方案1】:

    通过添加扩展 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

    【讨论】:

      【解决方案2】:

      我宁愿直接在视图中迭代表单:

      for form in formset.forms:
          form.user = request.user
          formset.save()
      
      • 避免创建不必要的 BaseFormSet
      • 更干净

      【讨论】:

      • 应该formset.save() 成为循环的一部分吗?或者不应该是form.save()
      【解决方案3】:

      基于 Paulo Check 的答案(这对我的情况并不适用)。

      我喜欢不编写自定义 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()
      

      【讨论】:

        【解决方案4】:

        我尝试了 selfsimilar 的解决方案,但 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)
        

        【讨论】:

          【解决方案5】:

          这是一个关于将表单参数传递给表单集的类似问题:

          Django Passing Custom Form Parameters to Formset

          就个人而言,我喜欢那里关于在函数中动态构建表单类的第二个答案,因为它实现起来非常快且易于理解。

          【讨论】:

            猜你喜欢
            • 2021-09-26
            • 2011-05-07
            • 1970-01-01
            • 2016-01-09
            • 1970-01-01
            • 2016-03-23
            • 1970-01-01
            • 2017-05-08
            • 2016-06-01
            相关资源
            最近更新 更多