I'm new with Django and Python... I'm trying to do my own registration form for add some additional fields (Following the docs about Profiles)... All fine when I test, but after save, the additional field don't save, without error, just don't save, only the User is created... but If I write manually some values on create_profile function, it's saved correct.. How I can pass fields from my UserCreateForms to create_profile routine?
Sorry for my english, and thanks for your help, I'm involved in a little project for learn and I'm stopped for this detail.. :S
Models
class UserProfile(models.Model):
user = models.OneToOneField(User)
cedula_de_identidad = models.CharField(max_length=9)
def create_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance, cedula_de_identidad='If I write here it's saved correctly')
post_save.connect(create_profile, sender=User)
Forms
class UserCreateForm(UserCreationForm):
email = forms.EmailField(required=True)
cedula_de_identidad = forms.CharField(required=True)
class Meta:
model = User
fields = ("email", "username", "password1", "password2")
def clean_username(self):
username = self.cleaned_data['username']
# if not re.search(r'^\w+$', username):
# raise forms.ValidationError('Username can contain only alphanumeric characters')
try:
User.objects.get(username=username)
except ObjectDoesNotExist:
return username
raise forms.ValidationError('Username is already taken')
def save(self, *args, **kwargs):
user = super(UserCreateForm, self).save(*args, **kwargs)
profile = UserProfile()
profile.user = user
profile.cedula_de_identidad = self.cleaned_data['cedula_de_identidad']
profile.save
return profile
Views
def nuevo_usuario(request):
if request.method == 'POST':
formulario = UserCreateForm(request.POST)
if formulario.is_valid():
formulario.save()
return HttpResponseRedirect('/')
else:
formulario = UserCreateForm()
return render_to_response('nuevousuario.html', {'formulario': formulario}, context_instance=RequestContext(request))
I'm using Python 2.7 and Django 1.4.. Regards,
Related
I have a register user form which is doing all the validation as expected. However, it is not saving. I am not able to figure out the reason. How do I debug it ? Any help ? I am a newbie to forms and formviews any good document with example would really help me.
class RegisterForm(forms.ModelForm):
phone_number = forms.IntegerField(required=True)
password1 = forms.CharField(widget=forms.PasswordInput())
password2 = forms.CharField(widget=forms.PasswordInput())
country_code = forms.IntegerField()
#schools = school.objects.all()
#school_name = forms.ModelChoiceField(queryset=school.objects.distinct())
MIN_LENGTH = 4
class Meta:
model = User
fields = ['username','country_code','phone_number', 'password1', 'password2',
'full_name' ]
def clean_phone_number(self):
phone_number = self.data.get('phone_number')
print(phone_number)
if User.objects.filter(phone_number=phone_number).exists():
raise forms.ValidationError(
_("Another user with this phone number already exists"))
if len(phone_number) == 10 and phone_number.isdigit():
pass
else:
raise forms.ValidationError(
_("Invalid Phone Number"))
return phone_number
def save(self, *args, **kwargs):
print("saving")
user = super(RegisterForm, self).save(*args, **kwargs)
user.set_password(self.cleaned_data['password1'])
print('Saving user with country_code', user.country_code)
user.save()
return user
Views.py
class RegisterView(SuccessMessageMixin, FormView):
template_name = 'register-2.html'
form_class = RegisterForm
success_message = "One-Time password sent to your registered mobile number.\
The verification code is valid for 10 minutes."
def form_valid(self, form):
full_name=self.request.POST["full_name"]
user = form.save()
print(user.id)
username = self.request.POST['username']
password = self.request.POST['password1']
user = authenticate(username=username, password=password)
kwargs = {'user': user}
self.request.method = 'POST'
print("User created")
The print in clean_phone_number works however, save does not work
I had issue in the my form. One of the field was disabled and the value was not captured because of that.
However to identify that I used
def form_invalid(self,form):
# Add action to invalid form phase
messages.error(self.request, form.errors)
return self.render_to_response(self.get_context_data(form=form))
I use a custom form inherited from django's UserCreationForm to add user. How ever i have to set different initial value for username field.It works perfectly but after hitting save button the user get saved with a different username than the initial value shown in the form.You can find the code below
from django.contrib.auth.forms import UserCreationForm
class AdminUserCreationForm(UserCreationForm):
"""
AdminForm for creating an instance of custom USER_MODEL.
"""
email = forms.EmailField(required=True)
class Meta:
model = User
fields = ("username", "email")
field_classes = {'username': UsernameField}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.initial['username'] = random_username_generator()
self.fields['username'].disabled = True
self.fields['password1'].required = False
self.fields['password2'].required = False
def clean_username(self):
username = self.cleaned_data['username'].lower()
try:
User.objects.get(username=username)
except User.DoesNotExist:
return username
raise forms.ValidationError('A user with username {} already exists'.format(username))
def clean_email(self):
email = self.cleaned_data['email'].lower()
try:
User.objects.get(email=email)
except User.DoesNotExist:
return email
raise forms.ValidationError('A user with email {} already exists'.format(email))
def save(self, commit=True):
import ipdb; ipdb.set_trace();
user = super(AdminUserCreationForm, self).save(commit=False)
# user = self.instance
qb = QuickBlox()
qb_password = reset_password_generator()
user.qb_password = qb_password + 'vx'
user.save()
attempt = LoginAttempts()
attempt.user = user
attempt.save()
send_invite_mail(user)
return user
I have SetPasswordForm that only sets user password
class SetPasswordForm(forms.Form):
password = forms.CharField(label="Password", widget=forms.PasswordInput)
def __init__(self, user, *args, **kwargs):
self.user = user
super(SetPasswordForm, self).__init__(*args, **kwargs)
def save(self, commit=True):
self.user.set_password(self.cleaned_data['password'])
if commit:
self.user.save(update_fields=['password'])
return self.user
and User model that has activate() method to make new user activate after setting a password
class User(BaseUser):
activation_code = models.CharField(max_length=100, blank=True, null=True)
activated_at = models.DateTimeField(blank=True, null=True)
def activate(self):
self.is_active = True
self.activation_code = None
self.activated_at = datetime.now()
self.save(update_fields=['is_active', 'activation_code', 'activated_at'])
In view, when user submits a form, It should sets new password and activates user
class ActivateUserView(View):
def post(self, request, activation_code):
try:
user = User.objects.get(activation_code=activation_code)
except User.DoesNotExist:
return Http404()
form = SetPasswordForm(user=user, data=request.POST)
if form.is_valid():
user = form.save(commit=False)
user.activate()
return render(request, 'users/activate_user_done.html', {'user': user})
return render(request, self.template_name, {'user': user})
Question is I don't know where to call user.activate()?
In form or in view?
I don't think form.save() should also calls this method because form will not be reusable in other places.
Call user.activate before form.save because you only want to save the user if he has activated his account.
I have a UserProfile model which is linked OneToOne with Django User model. While adding a user through a form, I wanted to have one form for both of those. I found a snippet that does exactly that, and I didn't have any problem with it, until I wanted to validate the username. The form isn't throwing a ValidationError, like I would like it to, but returns an error page with ValueError: The User could not be created because the data didn't validate..
From what I understand (which obviously could be wrong), the current setup doesn't handle ValidationErrors from the nested form.
Is there any way to add that functionality? If not, how should I tackle the issue of having one form handle to models?
Code:
class CmUserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput(),
required=False,
help_text=_("Leave empty if you don't want "
"to change it"))
def clean_password(self):
data = self.cleaned_data['password']
if data.strip():
return make_password(data)
else:
# If password field is empty, then don't change it
return self.instance.password
def clean_username(self):
username = self.cleaned_data['username']
if get_user_model().objects.filter(username=username).exists():
raise forms.ValidationError(_('This username is already in use.'))
return username
class Meta:
model = get_user_model()
fields = ('first_name', 'last_name', 'email', 'username', 'password', 'is_staff', 'is_active')
class CmUserProfileForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
# Take User if updating, None if creating
try:
self.user = kwargs['instance'].user
except AttributeError:
self.user = None
user_kwargs = kwargs.copy()
user_kwargs['instance'] = self.user
self.uf = CmUserForm(*args, **user_kwargs)
super(CmUserProfileForm, self).__init__(*args, **kwargs)
self.fields.update(self.uf.fields)
self.initial.update(self.uf.initial)
class Meta:
model = UserProfile
exclude = ['user']
def save(self, *args, **kwargs):
# Save User and pass it to UserProfile
user = self.uf.save(*args, **kwargs)
self.instance.user = user
return super().save(*args, **kwargs)
i implemented the same today. I learnt this from the this website tango with django. http://www.tangowithdjango.com/book/chapters/login.html. Also i provided my code how i achieved this. Inbuilt user model itself checks if the username already exists or not. hope this is helpful.
class Sam(models.Model):
user = model.OneToOneField(User)
#custom fields apart from the inbuilt User model
region = models.CharField(max_length=10)
designation = models.CharField(max_length=10)
#forms.py form models. Created SamProfileform to capture the custom fields which are specific to One's Profile and SamForm to capture the password and then hash later in the view.
#Please note that i didnt add any username check here. The inbuilt User does it for us. I verified it.
class SamForm(forms.ModelForm):
#form model to capture inbuilt fields of "User" model
password = forms.CharField(widget=PasswordInput())
class Meta:
model = User
fields = ('username', 'email', 'password', 'firstname', 'lastname')
class SamProfileForm(forms.ModelForm):
#form model to built the custom fields in my case region and designation
class Meta:
model = Sam
fields = ('desgination', 'mgr')
def register(request):
registered = False
if request.method == 'POST':
user_form = SamForm(data=request.POST)
profile_form = SamProfileForm(request.POST)
if user_form.is_valid() and profile_form.is_valid():
user = user_form.save()
user.set_password(user.password)
user.save()
profile = profile_form.save(commit=False)
profile.user = user
profile.save()
registered = True
else:
print user_form.errors, profile_form.errors
else:
user_form = SamForm()
profile_form = SamProfileForm()
template = loader.get_template('sam/register.html')
context = RequestContext(request, {
'user_form' : user_form, 'profile_form' : profile_form, 'registered' : registered,
})
return HttpResponse(template.render(context))
The ability for a user to edit their profile using Django Userena all of a sudden doesnt work. It just returns to the same edit page without doing anything. Can anyone see whats wrong with the code. Thanks
forms.py
class EditProfileForm(forms.ModelForm):
""" Base form used for fields that are always required """
first_name = forms.CharField(label=_(u'First name'),
max_length=30,
required=False)
last_name = forms.CharField(label=_(u'Last name'),
max_length=30,
required=False)
def __init__(self, *args, **kw):
super(EditProfileForm, self).__init__(*args, **kw)
# Put the first and last name at the top
new_order = self.fields.keyOrder[:-2]
new_order.insert(0, 'first_name')
new_order.insert(1, 'last_name')
self.fields.keyOrder = new_order
class Meta:
model = get_profile_model()
exclude = ['user']
def save(self, force_insert=False, force_update=False, commit=True):
profile = super(EditProfileForm, self).save(commit=commit)
# Save first and last name
user = profile.user
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.save()
return profile
views.py
enter code heredef profile_edit(request, username, edit_profile_form=EditProfileForm,
template_name='userena/profile_form.html', success_url=None,
extra_context=None, **kwargs):
"""
Edit profile.
Edits a profile selected by the supplied username. First checks
permissions if the user is allowed to edit this profile, if denied will
show a 404. When the profile is successfully edited will redirect to
``success_url``.
:param username:
Username of the user which profile should be edited.
:param edit_profile_form:
Form that is used to edit the profile. The :func:`EditProfileForm.save`
method of this form will be called when the form
:func:`EditProfileForm.is_valid`. Defaults to :class:`EditProfileForm`
from userena.
:param template_name:
String of the template that is used to render this view. Defaults to
``userena/edit_profile_form.html``.
:param success_url:
Named URL which will be passed on to a django ``reverse`` function after
the form is successfully saved. Defaults to the ``userena_detail`` url.
:param extra_context:
Dictionary containing variables that are passed on to the
``template_name`` template. ``form`` key will always be the form used
to edit the profile, and the ``profile`` key is always the edited
profile.
**Context**
``form``
Form that is used to alter the profile.
``profile``
Instance of the ``Profile`` that is edited.
"""
user = get_object_or_404(get_user_model(),
username__iexact=username)
profile = user.get_profile()
user_initial = {'first_name': user.first_name,
'last_name': user.last_name}
form = edit_profile_form(instance=profile, initial=user_initial)
if request.method == 'POST':
form = edit_profile_form(request.POST, request.FILES, instance=profile,
initial=user_initial)
if form.is_valid():
profile = form.save()
if userena_settings.USERENA_USE_MESSAGES:
messages.success(request, _('Your profile has been updated.'),
fail_silently=True)
if success_url: redirect_to = success_url
else: redirect_to = reverse('userena_profile_detail', kwargs={'username': username})
return redirect(redirect_to)
if not extra_context: extra_context = dict()
extra_context['form'] = form
extra_context['profile'] = profile
return ExtraContextTemplateView.as_view(template_name=template_name,
extra_context=extra_context)(request)
You have to run the following command to solve the problem
python manage.py check_permissions
i hope it will solve your problem.Cheers.