I'm currently working on an application for user registration on a Django CMS site.
My registration form is working just fine and creates the user, plus adds my custom fields to my registration model.
What I'd like to know is how to update auth_user to contain the user's first and last name.
Currently the user is being created in this manner:
import newform
from betaregistration.newform import RegistrationFormZ
def user_created(sender, user, request, **kwargs):
form = RegistrationFormZ(request.POST)
data = newform.BetaProfile(user=user)
data.first_name = form.data["first_name"]
data.last_name = form.data["last_name"]
data.address = form.data["address"]
data.city = form.data["city"]
data.state = form.data["state"]
data.postal_code = form.data["postal_code"]
data.country = form.data["country"]
data.phone= form.data["phone"]
data.email = form.data["email"]
data.save()
# this was the solution
user.first_name = form_data['first_name']
user.last_name = form_data['last_name']
user.save()
# end solution
from registration.signals import user_registered
user_registered.connect(user_created)
Any help is appreciated. I'm using django-registration for my registration.
Since you are passing user into user_created could you simply modify things as the following:
data.first_name = user.first_name = form.data["first_name"]
data.last_name = user.last_name = form.data["last_name"]
....
user.save()
I may be missing something but if you really do have access to user in user_created that should work. You could also potentially do the same using request.user instead of user.
Related
When logging in, create a profile, But when logging out and then logging in with that same username, It again says to me to create a profile and creates two profiles instead of one.
#For Cystomer Registration
class CustomerRegistrationView(View):
def get(self,request):
form = CustomerRegistrationForm()
return render(request,'mp/register.html',{'form':form})
def post(self,request):
form = CustomerRegistrationForm(request.POST)
if form.is_valid():
messages.success(request,'Congratulations Registerd Succesfuly ')
form.save()
success_url = reverse_lazy('profilecreate')
return render(request,'mp/register.html',{'form':form})
#For Creating Profile
class ProfileCreate(LoginRequiredMixin,CreateView):#ye hogia hamara upload wala
model = Profile
fields =
['user_name','user_ethnicity','SelectGender','user_job','user_age','mother_additionalinfo']
success_url = reverse_lazy('profile')
def form_valid(self,form):
form.instance.user = self.request.user
success_url = reverse_lazy('profile')
return super(ProfileCreate,self).form_valid(form)
here are my URLs
#for register
path('register/',views.CustomerRegistrationView.as_view(),name= 'register'),
#for CreateProfile
path('profilecreate/',views.ProfileCreate.as_view(),name= 'profilecreate'),
when User Created and I remove the loginrequiredmixin from profilecreateview. It give me an error of Page No Found With This Url:127.0.0.1:8000/accounts/login/?next=/profilecreate. It does not go to Profile Create View because it is not logged in but just Registered. And I want the User Go to Profilecreateview only one time. Later he can Update it. –
I am looking to add email account verification in Django. I have attempted using the django-registration app to do so, but it doesn't appear that it has been updated to be fully compatible with custom user models which causes too many problems. Is there another reliable and well-documented app out there which will allow me to send a verification email on user registration in django?
How I handle the email registration personally:
First of all, my Profile extending Django Users (models.py):
class Profile(models.Model):
user = models.OneToOneField(User, related_name='profile') #1 to 1 link with Django User
activation_key = models.CharField(max_length=40)
key_expires = models.DateTimeField()
In forms.py, the Registration class :
class RegistrationForm(forms.Form):
username = forms.CharField(label="",widget=forms.TextInput(attrs={'placeholder': 'Nom d\'utilisateur','class':'form-control input-perso'}),max_length=30,min_length=3,validators=[isValidUsername, validators.validate_slug])
email = forms.EmailField(label="",widget=forms.EmailInput(attrs={'placeholder': 'Email','class':'form-control input-perso'}),max_length=100,error_messages={'invalid': ("Email invalide.")},validators=[isValidEmail])
password1 = forms.CharField(label="",max_length=50,min_length=6,
widget=forms.PasswordInput(attrs={'placeholder': 'Mot de passe','class':'form-control input-perso'}))
password2 = forms.CharField(label="",max_length=50,min_length=6,
widget=forms.PasswordInput(attrs={'placeholder': 'Confirmer mot de passe','class':'form-control input-perso'}))
#recaptcha = ReCaptchaField()
#Override clean method to check password match
def clean(self):
password1 = self.cleaned_data.get('password1')
password2 = self.cleaned_data.get('password2')
if password1 and password1 != password2:
self._errors['password2'] = ErrorList([u"Le mot de passe ne correspond pas."])
return self.cleaned_data
#Override of save method for saving both User and Profile objects
def save(self, datas):
u = User.objects.create_user(datas['username'],
datas['email'],
datas['password1'])
u.is_active = False
u.save()
profile=Profile()
profile.user=u
profile.activation_key=datas['activation_key']
profile.key_expires=datetime.datetime.strftime(datetime.datetime.now() + datetime.timedelta(days=2), "%Y-%m-%d %H:%M:%S")
profile.save()
return u
#Sending activation email ------>>>!! Warning : Domain name is hardcoded below !!<<<------
#The email is written in a text file (it contains templatetags which are populated by the method below)
def sendEmail(self, datas):
link="http://yourdomain.com/activate/"+datas['activation_key']
c=Context({'activation_link':link,'username':datas['username']})
f = open(MEDIA_ROOT+datas['email_path'], 'r')
t = Template(f.read())
f.close()
message=t.render(c)
#print unicode(message).encode('utf8')
send_mail(datas['email_subject'], message, 'yourdomain <no-reply#yourdomain.com>', [datas['email']], fail_silently=False)
Now, in views.py, we need to handle all that, let's go :
The register view:
def register(request):
if request.user.is_authenticated():
return redirect(home)
registration_form = RegistrationForm()
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
datas={}
datas['username']=form.cleaned_data['username']
datas['email']=form.cleaned_data['email']
datas['password1']=form.cleaned_data['password1']
#We generate a random activation key
salt = hashlib.sha1(str(random.random())).hexdigest()[:5]
usernamesalt = datas['username']
if isinstance(usernamesalt, unicode):
usernamesalt = usernamesalt.encode('utf8')
datas['activation_key']= hashlib.sha1(salt+usernamesalt).hexdigest()
datas['email_path']="/ActivationEmail.txt"
datas['email_subject']="Activation de votre compte yourdomain"
form.sendEmail(datas)
form.save(datas) #Save the user and his profile
request.session['registered']=True #For display purposes
return redirect(home)
else:
registration_form = form #Display form with error messages (incorrect fields, etc)
return render(request, 'siteApp/register.html', locals())
The activation views :
#View called from activation email. Activate user if link didn't expire (48h default), or offer to
#send a second link if the first expired.
def activation(request, key):
activation_expired = False
already_active = False
profile = get_object_or_404(Profile, activation_key=key)
if profile.user.is_active == False:
if timezone.now() > profile.key_expires:
activation_expired = True #Display: offer the user to send a new activation link
id_user = profile.user.id
else: #Activation successful
profile.user.is_active = True
profile.user.save()
#If user is already active, simply display error message
else:
already_active = True #Display : error message
return render(request, 'siteApp/activation.html', locals())
def new_activation_link(request, user_id):
form = RegistrationForm()
datas={}
user = User.objects.get(id=user_id)
if user is not None and not user.is_active:
datas['username']=user.username
datas['email']=user.email
datas['email_path']="/ResendEmail.txt"
datas['email_subject']="Nouveau lien d'activation yourdomain"
salt = hashlib.sha1(str(random.random())).hexdigest()[:5]
usernamesalt = datas['username']
if isinstance(usernamesalt, unicode):
usernamesalt = usernamesalt.encode('utf8')
datas['activation_key']= hashlib.sha1(salt+usernamesalt).hexdigest()
profile = Profile.objects.get(user=user)
profile.activation_key = datas['activation_key']
profile.key_expires = datetime.datetime.strftime(datetime.datetime.now() + datetime.timedelta(days=2), "%Y-%m-%d %H:%M:%S")
profile.save()
form.sendEmail(datas)
request.session['new_link']=True #Display: new link sent
return redirect(home)
Finally, in urls.py:
url(r'^register/$', 'register'),
url(r'^activate/(?P<key>.+)$', 'activation'),
url(r'^new-activation-link/(?P<user_id>\d+)/$', 'new_activation_link'),
With all that you should have something to start with, use the appropriate templatetags in the .txt emails and HTML and it should work.
NB: This code isn't perfect, there is duplication (for instance, the generation of the random key could be defined in a function), but it does the job. Also: the activation key is not generated using proper cryptographic functions. An alternative is to use a function like the following to generate the keys:
from django.utils.crypto import get_random_string
def generate_activation_key(username):
chars = 'abcdefghijklmnopqrstuvwxyz0123456789!##$%^&*(-_=+)'
secret_key = get_random_string(20, chars)
return hashlib.sha256((secret_key + username).encode('utf-8')).hexdigest()
NB2: Django send_mail doesn't provide any tools to authenticate your emails. If you want to authenticate your emails (DKIM, SPF), I advise you to look into this: https://djangosnippets.org/snippets/1995/
NB3: There is a security issue with the view new_activation_link: it should check if the user requesting the re-send is the right one and also if he isn't already authenticated. I let you correct that.
You may also be interested in the simple but powerful django-verified-email-field.
Simply use VerifiedEmailField in Your forms:
from django import forms
from verified_email_field.forms import VerifiedEmailField
class RegistrationForm(forms.ModelForm):
email = VerifiedEmailField(label='email', required=True)
Or in Your models:
from django.db import models
from verified_email_field.models import VerifiedEmailField
class User(models.Model):
email = VerifiedEmailField('e-mail')
It renders two input fields: e-mail and verification code. The verification code is sent to the e-mail address using AJAX or during field's clean if there is no valid code for given e-mail, so it works even without javascript.
with django 1.5.1 I try to use the django form for one of my models.
I dont want to add the "user" field (Foreignkey) somewhere in the code instead of letting the user deceide whoes new character it is.
My Code:
Model:
class Character(models.Model):
user = models.ForeignKey(User)
creation = models.DateTimeField(auto_now_add=True, verbose_name='Creation Date')
name = models.CharField(max_length=32)
portrait = models.ForeignKey(Portrait)
faction = models.ForeignKey(Faction)
origin = models.ForeignKey(Origin)
The form:
class CreateCharacterForm(forms.ModelForm):
class Meta:
model = Character
fields = ['name', 'portrait', 'faction', 'origin']
The view:
def create_character(request, user_id):
user = User.objects.get(id=user_id)
if request.POST:
new_char_form = CreateCharacterForm(request.POST)
if new_char_form.is_valid():
new_char_form.save()
return HttpResponseRedirect('%s/characters/' % user_id)
else:
return render_to_response('create.html',
{'user': user, 'create_char':new_char_form},
context_instance=RequestContext(request))
else:
create_char = CreateCharacterForm
return render_to_response('create.html',
{'user': user, 'create_char': create_char},
context_instance=RequestContext(request))
I have tried to use a instance to incluse the userid already. i've tried to save the userid to the form before saving it, or changing the save() from my form.
I keep getting the error that character.user cant be null
I have to tell that im pretty new to django and im sure one way or another it should be possible
Can someone please help me out?
Its explained well in document model form selecting fields to use
You have to do something like this in your view
...
if request.POST:
new_char_form = CreateCharacterForm(request.POST)
if new_char_form.is_valid():
#save form with commit=False
new_char_obj = new_char_form.save(commit=False)
#set user and save
new_char_obj.user = user
new_char_obj.save()
return HttpResponseRedirect('%s/characters/' % user_id)
else:
...
I'm using Django 1.4 with Python 2.7 and Ubunutu 12.04.
I have a form that will update a user's profile. The last item in the form is the password. I pre-populate the form with the existing user's data. The password field does not get pre-populated - and that's fine.
The problem is that when I "save" the data it overwrites the password to be a null or empty field (I can't tell which). Bad.
What can I do to prevent this?
I've tried to make it a required field (forms.py):
password = forms.CharField(widget = forms.PasswordInput(), required = True)
Didn't work.
I've tried to check that the password is not None before updating it (views.py):
if (request.POST.get('password') is not None):
user.set_password(request.POST.get('password'))
Didn't work.
Does an empty form value come back as None? If not, what does it come back as and how can I check if it's empty?
EDIT 1:
I updated my one of my views to check for validation - maybe I did this wrong?
#login_required
def profile(request):
"""
.. function:: profile()
Provide the profile page, where it can be updated
:param request: Django Request object
"""
if request.user.is_authenticated():
user = User.objects.get(username = request.user.username)
user_dict = createUserProfileDict(user)
form = ProfileForm(initial = user_dict);
data = { 'user' : request.user }
data.update({ 'form' : form })
data.update(csrf(request))
if form.is_valid():
return render_to_response("profile.html", data)
Now I receive the following error:
The view rsb.views.profile didn't return an HttpResponse object.
So, it appears my form is not valid? How can I find out why?
Here is the update_profile view:
#login_required
def update_profile(request):
"""
.. function:: profile()
provide the profile page
:param request: Django Request object
"""
if request.user.is_authenticated():
user = User.objects.get(username = request.user)
user.first_name = request.POST.get('first_name')
user.last_name = request.POST.get('last_name')
user.email = request.POST.get('email')
if (request.POST.get('password') is not None):
user.set_password(request.POST.get('password'))
user.save()
# Update the additional user information tied to the user
user_info = UserProfile.objects.get(user_id = user.id)
user_info.company_name = request.POST.get('company_name')
user_info.client_type = request.POST.get('client_type')
user_info.address1 = request.POST.get('address1')
user_info.address2 = request.POST.get('address2')
user_info.city = request.POST.get('city')
user_info.state = request.POST.get('state')
user_info.country = request.POST.get('country')
user_info.zip_code = request.POST.get('zip_code')
user_info.phone_number = request.POST.get('phone_number')
user_info.save()
return profile(request)
First of all, remember to control if your form "is_valid()"
To theck if your form has been submitted with empty values or not, use
MyForm.has_changed()
too bad this is not a documented functionality :(
If you want a default password, i suggest you check if the field is valid then use something like
''.join([choice(string.letters + string.digits) for i in range(7)])
to generate a new password for the user (range(7) is the length you want). Then use an opt-in method (see: send a user an email with his temporary password)
edit based on new context:
from the django docs:
If a Field has required=False and you pass clean() an empty value,
then clean() will return a normalized empty value
rather than raising ValidationError.
For CharField, this will be a Unicode empty string.
For other Field classes, it might be None. (This varies from field to field.)
That's it, your password field should have required=False, so you can treat that as an empty string
Then in your view you could do:
if input_password != '' and input_password != saved_password:
saved_password = input_password
It's just pseudocode, but it should give you a clear idea
I currently have a form that allows the user to edit their profile (django-profiles). The form is working great, except that I've put a switch in place for States and Provinces depending on whether ot not the user picks Canada or the US.
In my model, I have both State and Province set so that in the table there are 2 separate fields.
In my save method I have the following:
def user_created(sender, user, request, **kwargs):
form = RegistrationFormZ(request.POST)
....stuff here.....
if form.data["country"] == 'US':
data.state = form.data["state"]
data.provinces = None
if form.data["country"] == 'CA':
data.provinces = form.data["provinces"]
data.state = None
....stuff here....
data.save()
user.first_name = form.data['first_name']
user.last_name = form.data['last_name']
user.save()
from registration.signals import user_registered
user_registered.connect(user_created)
The if statements are not working as I expected they would on save.
What's happening is that it correctly saves the value of the option that was selected (state/province) but then fails to update the opposing one to an empty value.
So for example let's say I had a user who had a Canadian address, and then updated it to the US address. The US state gets properly saved, but province does not get updated to None.
Perhaps a more elegant way to accomplish this is using dictionaries. As an aside, are you sure your field name is provinces (plural) instead of singular? Here's an example how to do this with dictionaries, note you could add more fields for different countries without any more if statements and you could even write a separate getter function to return these dictionaries:
def user_created(sender, user, request, **kwargs):
form = RegistrationFormZ(request.POST)
....stuff here.....
data.state = None
data.provinces = None
state_field = {}
state_field['US'] = {}
state_field['US']['src'] = form.data['state']
state_field['US']['dest'] = data.state
state_field['CA'] = {}
state_field['CA']['src'] = form.data['province']
state_field['CA']['dest'] = data.province
state_field[form.data['country'].upper()]['dest'] = state_field[form.data['country'].upper()]['src']
....stuff here....
data.save()
user.first_name = form.data['first_name']
user.last_name = form.data['last_name']
user.save()
from registration.signals import user_registered
user_registered.connect(user_created)