Джанго Формсет установил текущего пользователя - PullRequest
14 голосов
/ 25 марта 2011

Относится к к этому вопросу , но подробно его расскажу - как бы я использовал эту технику в наборе форм?

Я хотел бы использовать текущего зарегистрированного пользователя в форме,но я использую форму в форме.Ссылочное решение для одной формы - передать 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>')

Ответы [ 5 ]

19 голосов
/ 28 марта 2011

Добавляя класс, который расширяет 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)

# ...

Благодаря Ашок Раави .

6 голосов
/ 28 марта 2012

Я предпочитаю итерировать формы непосредственно в представлении:

for form in formset.forms:
    form.user = request.user
    formset.save()
  • Это позволяет избежать создания ненужных BaseFormSet
  • Это чище
4 голосов
/ 05 декабря 2013

Основано на ответе Пауло Чека (который действительно не работал для моего случая).

Мне понравилась идея не писать пользовательский унаследованный класс 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 голосов
/ 13 января 2015

Я пытался найти решение, похожее на самоподобное, но 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)
0 голосов
/ 25 марта 2011

Вот аналогичный вопрос о передаче параметров формы в набор:

Django Передача пользовательских параметров формы в набор форм

Лично мне нравится второй ответ о динамическом построении класса формы в функции, потому что это очень быстро реализовать и легко понять.

...