Getting the authenticated username to a function view in django - python

Im trying to modify the current user's data but with no sucess, need some help.
def account_admin(request):
if request.method == 'POST':
mod_form = ModificationForm(request.POST)
if mod_form.is_valid():
user = User.objects.get(request.user)
user.set_password(form.cleaned_data['password1'])
user.email = form.cleaned_data['email']
user.save
return HttpResponseRedirect('/register/success/')
else:
mod_form = ModificationForm()
variables = RequestContext(request, {
'mod_form': mod_form
})
return render_to_response('registration/account.html', variables)

request.user is already an instance of User, there's no point in doing another query.
Plus, you actually need to call save().

Your issue is here:
user = User.objects.get(request.user)
Ideally, it would have been
user = User.objects.get(id=request.user.id)
You dont need a query to retrieve the user object here, since request.user evaluates to an instance of the logged in user object.
user = request.user
user.set_password(form.cleaned_data['password1'])
user.email = form.cleaned_data['email']
user.save()
Should work
Also, make sure you have the #login_required decorator to the account_admin method

You seem to have you answer from the above posts but I notice that you did not authenticate the user (you may have done it elsewhere that I don't know about). In case you want to do so, try the login_reqired decorator https://docs.djangoproject.com/en/1.5/topics/auth/default/#django.contrib.auth.decorators.login_required

Thanks so much karthikr and Daniel! Heres how i got it to work:
def account_admin(request):
if request.method == 'POST':
mod_form = ModificationForm(request.POST)
if mod_form.is_valid():
user = User.objects.get(id=request.user.id)
user.set_password(mod_form.cleaned_data['password1'])
user.email = mod_form.cleaned_data['email']
user.save()
return HttpResponseRedirect('/register/success/')
else:
mod_form = ModificationForm()
variables = RequestContext(request, {
'mod_form': mod_form
})
return render_to_response('registration/account.html', variables)
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
karthikr, iam still learning django, i dont get your sugestion of the decorator #login_required. What does it do?

Related

Django method exists() not working, error "referenced before assignment"

after long time passed at searched a solution, i not advanced for a reason.
I try of make operate the functionality "if exists():" for "User.username" of the user, and so avoid the duplicate username in my webSite,but this is not work.
this is my code in views.py :
def edit_profil(request, pk=id):
error_name = reverse_lazy('profil_edit')
template_name="blog/edit_profil.html"
if request.method == "POST":
form = EditProfilForm(data=request.POST, instance=request.user)
if form.is_valid():
usernameDatas = form.cleaned_data['username']
if User.objects.filter(username=usernameDatas).exists():
messages.error(request, 'This is Username already exists !')
return redirect(error_name)
else:
user = form.save(commit=False)
user.email = form.cleaned_data['email']
user.username=usernameDatas
user.save()
return redirect('/blog/profil')
else:
form = EditProfilForm(instance=request.user)
return render(request, template_name, locals())
The error received is:
"local variable 'usernameDatas' referenced before assignment"
Where is my error ? thanks all.
.exists() is not the origin of the problem. This is a rather generic error in Python. It means that you use a variable before you assigned a value to it. Now in the .exists() line, only one local variable is used: usernameDatas. So it is likely that this variable is not assigned.
If we now look at possible scenario's where it is not valid, we see that this can happen if the form.is_valid() fails (returns False). The most straightforward way to handle this is by inlining the part:
def edit_profil(request, pk=id):
error_name = reverse_lazy('profil_edit')
template_name="blog/edit_profil.html"
if request.method == "POST":
form = EditProfilForm(data=request.POST, instance=request.user)
if form.is_valid():
usernameDatas = form.cleaned_data['username']
# inline relevant parts
if User.objects.filter(username=usernameDatas).exists():
messages.error(request, 'This is Username already exists !')
return redirect(error_name)
else:
user = form.save(commit=False)
user.email = form.cleaned_data['email']
user.username=usernameDatas
user.save()
return redirect('/blog/profil')
else:
form = EditProfilForm(instance=request.user)
return render(request, template_name, locals())
Note however that the above is an elegant way to tackle the problem. If you specify unique=True for the username field of the related Django model, then the form will automatically validate this. Furthermore you specify paths in the redirct(..) instead of the name of a view, which makes it senstive to URL changes. Finally using locals() is a severe anti-pattern: it is better to pass a dictionary with the variables you use.

django best way of managing template and it's views

In django is it the only way to have only one view for one whole page/url. And whatever functions(upload/post/update/log-in) that page contains just needs to pass inside that view. I found this is the only way as i can only return one url with one view.
I am wondering if there has any way where i can make different view(may be classed base or normal) for each function and at last add all of them on one single view(that view return that url also). If it is possible than how ? Because having all the functions of a url inside one view is looking weird and messy to me.
##################
def logInRegisterUser(request):
###################login##################
loginForm = UserLoginForm(request.POST or None)
if loginForm.is_valid() and 'log-in' in request.POST:
username = loginForm.cleaned_data.get("username")
password = loginForm.cleaned_data.get("password")
user = authenticate(username = username, password = password)
# if not user or not user.check_password(password):
# raise validation error
login(request, user)
print(request.user.is_authenticated())
###################registration###################
registrationForm = RegistrationForm(request.POST or None)
if registrationForm.is_valid() and 'sign-up' in request.POST:
user2 = registrationForm.save(commit = False)
password2 = registrationForm.cleaned_data.get('password')
user2.set_password(password2)
user2.save()
new_user = authenticate(username = user2.username, password = password2)
login(request, new_user)
###################log-out###################
###################search-post###################
####################voting-post##################
context = {
"loginForm":loginForm,
"registrationForm":registrationForm,
"re":request.POST
}
###################return###################
return render(request,"enter.html",context)
you can merge the response from another class. You can merge multiple class response into to a single view.
Django - Having two views in same url

Django: authenticate the user

I have the following code:
# creating user:
def create_user(request):
if request.method == 'POST':
user_info = forms.UserInfoForm(request.POST)
if user_info.is_valid():
cleaned_info = user_info.cleaned_data
User.objects.create_user(username=cleaned_info['username'], password=cleaned_info['password'])
render(.......)
This works. I can check the auth_user and I see the username and password along with all the other fields created and added.
Now, I try to authenticate the user with the following code after creating user with username='testcase' and password='test': using above code.
# Authenticate User
def get_entry(request):
if request.method == 'POST':
user = authenticate(username='testcase', password='test')
if user:
.........
The user is always returned as none. What is going on? I am running django 1.10.2.
Update:
I can see the user created by create_user function when I log in admin. The status was not staff(as it was supposed to be). I changed that to staff to see if that was causing problem but still the get_entry method yields none for user.
It is frustrating. I don't really know what I am doing wrong.
Save the user in one var, and then call user.save() because User can't call the method save() try it:
def create_user(request):
if request.method == 'POST':
user_info = forms.UserInfoForm(request.POST)
if user_info.is_valid():
cleaned_info = user_info.cleaned_data
user = User.objects.create_user(username=cleaned_info['username'], password=cleaned_info['password'])
user.save()
render(.......)
Then you need to call auth.authenticate in your function get_entry:
def get_entry(request):
if request.method == 'POST':
user = auth.authenticate(username='testcase', password='test')
if user:
.........
Your code seems to be correct.
The problem might be in the way the params are being passed to your create_user view (Param passing in get_entry view highly unlikely to be a problem since the params username and password are hard-coded).
Try printing out username and password before passing them to User.objects.create_user(), since it's possible that the password field is not being saved properly and/or empty password is being passed, and Django might be creating a hash for the empty password.
P.S.: This is just a speculation, need your response over this for further diagnosis of the issue.

Django, redirect to another view with data

I'm sending a form. So if it's valid i'm setting a variable message with a message. So if the form is valid, I would like to redirect to another view but also pass the message variable. It should be a syntax issue.
On successful submission, it redirects to a view with a url membership/enroll/studies.views.dashboard which of course is wrong.
views.py
def enroll(request):
user = request.user
if request.method == 'POST':
form = SelectCourseYear(request.POST)
if form.is_valid():
student = form.save(commit=False)
student.user = request.user
student.save()
message = 'Successfully Enrolled'
return redirect('studies.views.dashboard', {'message': message,})
else:
form = SelectCourseYear()
return render(request, 'registration/step3.html',)
Consider making use of sessions to store arbitrary data between requests: https://docs.djangoproject.com/en/dev/topics/http/sessions/
request.session['message'] = 'Successfully Enrolled'
Alternatively, if you just want to display a message to the user, you might be happy with the contrib.messages framework: https://docs.djangoproject.com/en/dev/ref/contrib/messages/
from django.contrib import messages
messages.success(request, 'Successfully Enrolled')
Based on your use case above, I'm guessing that contrib.messages is more appropriate for your scenario.

Django Email Change Form Setup

My email change form for users works, but I feel like my code is not written correctly. If I did it the way I have done below, I'd need a thousand else statements so that the page would return a response. Can someone tell me how I can make this more efficient/better? I'm not sure of the conventional way to do this
Views.py
def email_change(request):
form = Email_Change_Form()
if request.method=='POST':
form = Email_Change_Form(request.POST)
if form.is_valid():
if request.user.is_authenticated:
if form.cleaned_data['email1'] == form.cleaned_data['email2']:
user = request.user
u = User.objects.get(username=user)
# get the proper user
u.email = form.cleaned_data['email1']
u.save()
return HttpResponseRedirect("/accounts/profile/")
else:
return render_to_response("email_change.html", {'form':form}, context_instance=RequestContext(request))
I would suggest a complete change on how you looked at this. In my opinion, you should have all the implementation on the form side.
forms.py
I've implemented a class based on the SetPasswordForm that is more complete:
class EmailChangeForm(forms.Form):
"""
A form that lets a user change set their email while checking for a change in the
e-mail.
"""
error_messages = {
'email_mismatch': _("The two email addresses fields didn't match."),
'not_changed': _("The email address is the same as the one already defined."),
}
new_email1 = forms.EmailField(
label=_("New email address"),
widget=forms.EmailInput,
)
new_email2 = forms.EmailField(
label=_("New email address confirmation"),
widget=forms.EmailInput,
)
def __init__(self, user, *args, **kwargs):
self.user = user
super(EmailChangeForm, self).__init__(*args, **kwargs)
def clean_new_email1(self):
old_email = self.user.email
new_email1 = self.cleaned_data.get('new_email1')
if new_email1 and old_email:
if new_email1 == old_email:
raise forms.ValidationError(
self.error_messages['not_changed'],
code='not_changed',
)
return new_email1
def clean_new_email2(self):
new_email1 = self.cleaned_data.get('new_email1')
new_email2 = self.cleaned_data.get('new_email2')
if new_email1 and new_email2:
if new_email1 != new_email2:
raise forms.ValidationError(
self.error_messages['email_mismatch'],
code='email_mismatch',
)
return new_email2
def save(self, commit=True):
email = self.cleaned_data["new_email1"]
self.user.email = email
if commit:
self.user.save()
return self.user
This class checks both if the e-mail have in fact changed (very useful if you need to validate the e-mail or update mail chimp for example) and produce the appropriate errors, so they are helpful for the user in the form view.
views.py
Your code adapted to my class:
#login_required()
def email_change(request):
form = EmailChangeForm()
if request.method=='POST':
form = EmailChangeForm(user, request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect("/accounts/profile/")
else:
return render_to_response("email_change.html", {'form':form},
context_instance=RequestContext(request))
As you can see the view is simplified, assuring everything on the form level.
To ensure the login I set a decorator (See the docs).
Ps: I changed email1 and email2 to new_email1 and new_email2 to be consistent with the Django approach on passwords. I also changed the form Email_Change_Form to EmailChangeForm according to Python guidelines for classes.
I would suggest moving the validation to the form clean method:
#form
class EmailChangeForm():
..
..
def clean(self):
if self.cleaned_data.get('email1', None) != self.cleaned_data.get('email1', None):
raise forms.ValidationError('Validation Failed')
#login_required('/login/') //You can check the user is logged in using the decorator
def email_change(request):
form = Email_Change_Form()
if request.method=='POST':
form = Email_Change_Form(request.POST)
if form.is_valid():
user = request.user //Don't know why you want to get the object from database when you already have it
user.email = form.cleaned_data['email1']
user.save()
return HttpResponseRedirect("/accounts/profile/")
else:
return render_to_response("email_change.html", {'form':form}, context_instance=RequestContext(request))
Update:
Doing this is redundant:
user = request.user
u = User.objects.get(username=user.username)
Because user is going to be the same as u i.e. user = u
You will create more complicated code with nested if, if you write every bit of logic in your views. You need to break them in appropriate sections. Like, for every form related validations, do it in forms like -
if `email1` is same as `email2`,
and if email1 is valid
check it in your form. You should check that in clean or clean_FieldName methods. Refer here: https://docs.djangoproject.com/en/dev/ref/forms/validation/#cleaning-and-validating-fields-that-depend-on-each-other
Another check you applied for authentication - if the user is authenticated or not. In this case, can a Unauthorised user change his email - well no. So why should I let my code run for it. It would be better to check this condition as soon as possible and then send the user to login page. #login_required is used to check this condition as a decorator of your view. See here : https://docs.djangoproject.com/en/dev/topics/auth/#the-login-required-decorator
If you really want to check your user authentication in your view, I think the good approach would be -
def email_change(request):
if not request.user.is_authenticated:
// Do what you need to say to user or send them to login
// return HttpResponse object / HttpResponseRedirect
form = Email_Change_Form(request.POST)
if request.method=='POST':
if form.is_valid():
...
else:
... // Display form.

Categories