2011-03-24 23 views
13

Relacionado con this question, pero expandiéndolo - ¿Cómo usaría esta técnica en un formset?Conjunto de formularios de Django usuario actual

Me gustaría usar el usuario que ha iniciado sesión actualmente en un formulario, pero estoy usando el formulario en un formset. La solución a la que se hace referencia para un único formulario es pasar request.user a la forma y proceso en init. ¿Cómo agrego a los kwargs para cada formulario en el formset?

ejemplo en mi código:

en 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 

después en 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>') 

Respuesta

18

Al agregar una clase que se extiende a BaseFormSet, puede agregar un código personalizado para pasar un parámetro al formulario.

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

Luego, en views.py:

# ... 

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

# ... 

Gracias a Ashok Raavi.

0

Aquí hay una pregunta similar sobre el paso de parámetros de formulario a un juego de formularios:

Django Passing Custom Form Parameters to Formset

Personalmente, me gusta la segunda respuesta sobre cómo construir dinámicamente la clase de formulario en una función porque es muy rápida de implementar y fácil de entender.

5

que en lugar de iterar formas directamente en la vista:

for form in formset.forms: 
    form.user = request.user 
    formset.save() 
  • Se evitar la creación innecesaria BaseFormSet
  • Es más limpio
+5

En caso de 'formset.save()' ser parte del bucle? ¿O no debería ser 'form.save()' en su lugar –

4

Sobre la base de Paulo Ver respuesta (que no lo hizo realmente funciona para mi caso).

Me encantó la idea de no escribir una clase heredada BaseFormSet personalizada.

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

He intentado la solución de autosimilaridad pero el BaseFormSet no funcionaba en mi Django 1.6.

que siguieron los pasos de: https://code.djangoproject.com/ticket/17478 y la forma en que trabajó para mí es:

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) 
Cuestiones relacionadas