Пользовательский набор Django устанавливает текущий пользователь
Связанный с этот вопрос, но расширяющийся на нем - Как бы я использовал эту технику в formet?
Я хотел бы использовать текущего зарегистрированного пользователя в форме, но я использую форму в наборе форм. Реферированное решение для одной формы - передать 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>')
Ответы
Ответ 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)
# ...
Благодаря Ашок Раави.
Ответ 2
Я скорее перебираю формы непосредственно в представлении:
for form in formset.forms:
form.user = request.user
formset.save()
- Не создавать ненужные BaseFormSet
- Чище
Ответ 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
Я попробовал решение самостоятельно, но 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 Передача настраиваемых параметров формы в формат
Лично мне нравится второй ответ о создании динамического класса формы в функции, потому что он очень быстро реализуется и легко понимается.