Django-Userena: agregar campos extra no nulos al perfil de un usuario

Is there an easy way to allow for required profile fields?

I am using userena in my current django project. I have a custom profile called UserProfile which has a start_year none-blank, non-null field as defined below.

class UserProfile(UserenaBaseProfile, PybbProfile):
    user = models.OneToOneField(User, unique=True,
                        verbose_name=_('user'),
                        related_name='user_profile')

    start_year = models.IntegerField(max_length=4)

I need this to be filled-in on signup. I created a SignupExtraForm as defined below, to override the default form.

class SignupFormExtra(SignupForm):
    start_year = forms.IntegerField(label=_(u'Initiation Year'),
                            min_value=1800,
                            max_value=datetime.now().year,
                            required=True)

    def save(self):
        new_user = super(SignupFormExtra, self).save()

        new_user_profile = new_user.get_profile()

        new_user_profile.start_year = self.cleaned_data['start_year']
        new_user_profile.save()

        # Userena expects to get the new user from this form, so return the new
        # user.
        return new_user

When I attempt to add a new user thru the now modified form I get the below error:

profile_userprofile.start_year may not be NULL

With the stack trace pointing at new_user = super(SignupFormExtra, self).save()), in the code above.

I think this has to do with the user profile being created and saved before I am able to give it the required data from the form. Is there an easy way of supplying this data to the user_creation process, or delaying the creating of the user profile?

Gracias Shon

preguntado el 30 de enero de 12 a las 20:01

1 Respuestas

UserProfile is created after the User is saved by a post_save signal. Even if you override it with your own signal, you won't have access to the form data from there.

The easiest solution is to just allow start_year to be NULL. It's not necessary to enforce this at the database level, and you can make the field required in all forms either way:

start_year = models.IntegerField(max_length=4, blank=False, null=True)

Your custom form already enforces that the field is required, so you're done.

UPDATE (from comment)

Custom form, yes, but you can still use a ModelForm:

class MyModelForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(MyModelForm, self).__init__(*args, **kwargs)
        self.fields['start_year'].required = True

UPDATE (again)

Actually, I didn't think before my last update. I put blank=False al start_year field in my example. That will force that the field is required in all ModelForms by default. You don't need a custom ModelForm at all. However, I left the previous update for posterity.

Respondido el 31 de enero de 12 a las 19:01

Userena doesn't use the post_save signal.The UserProfile is actually created in the when UserenaManager.create_user(), is called in the SignupForm.save(). - sarkybogmozg

Your are correct and I have thought of this, but it just seems dirty to me. I am hoping that I missed some setting or something else... - sarkybogmozg

Sorry thought of a problem with this. When setting up editing for the profile i will be forced to use custom form instead of a ModelForm, because the field will not force validation. - sarkybogmozg

See my updates above. I gave you a sample ModelForm you can use if you really need it, but the blank=False argument makes the field required for the purposes of forms, so it's unnecessary. - Chris Pratt

Thanks! I didn't understand the how blank vs null worked with regards to ModelForms. - sarkybogmozg

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.