i'm new in django and i'm trying to create an application that user can change his/her password based on his/her id. So far is good, but when i'm trying to passing an argument from my views.py, there is a trouble that an argument can't passing to the html template.
This is my views:
def tambah_user(request, template_name='form_user.html'):
if 'username' in request.session:
username = User.objects.all()
data = {}
data['object_list'] = username
if request.method == 'POST':
user_form = UserForm(data=request.POST)
profile_form = UserProfileForm(data=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()
return redirect('manajemen_user')
else:
print user_form.errors, profile_form.errors
else:
user_form = UserForm()
profile_form = UserProfileForm()
return render(request, template_name,
{'user_form': user_form, 'profile_form': profile_form, 'data': data},)
else:
return HttpResponseRedirect('/simofa/login')
with that code, data can't passing to the html template.
when i changed render like this
return render(request, template_name,data)
it works properly, but user_form and profile_form isn't passing to the template.
My question:
Can i passing data, user_form, profile_form together to the template?
if can, how? if not, is there any other way ?
I really appreciate your input. so please help me. Thanks ^__^
The render statement isn't expecting a trailing comma like when you're defining a tuple, which is most likely what's causing the error, however your code could use some refactoring....
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
# assuming you're using your own form here for some reason...
from .forms import UserForm
# use the login_required decorator instead of manually checking for the session
#login_required
def tambah_user(request, template_name='form_user.html'):
# `users` just makes more sense here for the variable name
users = User.objects.all()
# no need for the extra if clause to create unbound forms
user_form = UserForm(request.POST or None)
profile_form = UserProfileForm(request.POST or None)
if request.method == 'POST':
if user_form.is_valid() and profile_form.is_valid():
user = user_form.save()
# you need to pass in the raw password here,
# otherwise you're hashing the already hashed password
# if you were to be editing an instance
user.set_password(user_form.cleaned_data('password'))
user.save()
profile = profile_form.save(commit=False)
profile.user = user
profile.save()
# you need to use reverse by name to do this
return redirect(reverse('manajemen_user'))
else:
print user_form.errors, profile_form.errors
# notice I have omitted the trailing comma after the context
# dictionary
return render(request, template_name, {'user_form': user_form,
'profile_form': profile_form, 'data': users})
I hope you've read the documentation for authentication in Django, because there are built-in forms and views to do pretty much everything you'd ever need to do for users instead of writing your own.
Related
I know this question have been asked alot and most of the time its due to render or HttpResponse in the views.py, i double checked mine but the code looks good to me, dont know where the problem is.
This is a views.py file for a very basic django form but i can't get it to work
def register(request):
registered = False
if request.method == 'POST':
user_form = UserForm(data = request.POST)
profile_form = UserProfileInfoForm(data = request.POST)
if user_form.is_valid() and profile_form.is_valid():
user = user_from.save()
user.set_password(user.password)
user.save()
profile = profile_form.save(commit = False)
profile.user = user
if 'profile_pic' in request.FILES:
profile.profile_pic = request.FILES['profile_pic']
profile.save()
registered = True
else:
return (user_form.errors,profile_form.errors)
else:
user_form = UserForm()
profile_form = UserProfileInfoForm()
return render(request,'basic_app/register.html',{'user_form': user_form,
'profile_form':profile_form,
'registered':registered})
You can not return (user_form.errors, profile_form.errors), since that is not a HttpResponse object. What response should the server return in that case.
Usually in case the form is invalid, the server will rerender the content. The form will, if you render it properly display the errors.
Note that in case the POST request was successful, you usually should redirect to implement the Post/Redirect/Get pattern [wiki]. You furthermore probably want to use a UserCreationForm [Django-doc]. This will set the password of the user in the correct way (with .set_password(..)), and run a password validator if you configured this.
You thus can rewrite your view as follows, but you probably should replace UserForm with UserCreationForm:
from django.shortcuts import redirect
def register(request):
if request.method == 'POST':
user_form = UserForm(data=request.POST)
profile_form = UserProfileInfoForm(data=request.POST)
if user_form.is_valid() and profile_form.is_valid():
user = user_from.save(commit=False)
user.set_password(user.password)
user.save()
profile = profile_form.save(commit=False)
profile.user = user
if 'profile_pic' in request.FILES:
profile.profile_pic = request.FILES['profile_pic']
profile.save()
return redirect('name-of-view')
else:
user_form = UserForm()
profile_form = UserProfileInfoForm()
return render(
request,
'basic_app/register.html',
{'user_form': user_form, 'profile_form':profile_form })
In the code, why am I getting "local variable 'user_form' referenced before assignment" error?
from django.shortcuts import render
from basic_app.forms import UserForm,UserProfileInfoForm
def index(request):
return render(request,'basic_app/index.html')
def register(request):
registered=False
if request.method=="POST":
user_form=UserForm(data=request.POST)
profile_form=UserProfileInfoForm(data=request.POST)
if user_form.is_valid() and profile_form.is_valid():
user=user_form.save()
user.set_password(user.password) #Hashing the password
user.save()
profile=profile_form.save(commit=False)
profile.user=user #Sets up one to one relationship
if 'profile_pic' in request.FILES:
profile.profile_pic=request.FILES['profile_pic']
profile.save()
registered=True
else:
print(user_form.errors,profile_form.errors)
else:
user_form=UserForm()
profile_form=UserProfileInfoForm()
return render(request,'basic_app/registration.html',{'user_form':user_form,'profile_form':profile_form,'registered':registered})
This is in the views.py file.
Have been stuck on this project since a while. Please help?
Your second else block is indented too far. Move it back one level.
You have indenting issue.. Check the edited one here
from django.shortcuts import render
from basic_app.forms import UserForm, UserProfileInfoForm
def index(request):
return render(request, 'basic_app/index.html')
def register(request):
registered = False
if request.method == "POST":
user_form = UserForm(data=request.POST)
profile_form = UserProfileInfoForm(data=request.POST)
if user_form.is_valid() and profile_form.is_valid():
user = user_form.save()
user.set_password(user.password) # Hashing the password
user.save()
profile = profile_form.save(commit=False)
profile.user = user # Sets up one to one relationship
if 'profile_pic' in request.FILES:
profile.profile_pic = request.FILES['profile_pic']
profile.save()
registered = True
else:
print(user_form.errors, profile_form.errors)
else:
user_form = UserForm()
profile_form = UserProfileInfoForm()
return render(request, 'basic_app/registration.html', {'user_form': user_form, 'profile_form': profile_form, 'registered': registered})
Good day everyone, i'm new to django, i'm working on a project were users can create accounts, i'm using the django registration model. Here's the problem,during registration, if the username the guest wants to use is taken or the passwords entered don't match, it gives this error 'The view account.views.register didn't return an HttpResponse object. It returned None instead.' instead of informing the guest about the errors.
views.py
def register(request):
if request.method == 'POST':
user_form = UserRegistrationForm(request.POST)
if user_form.is_valid():
# Create a new user object but avoid saving it yet
new_user = user_form.save(commit=False)
# # Set the chosen password
new_user.set_password(
user_form.cleaned_data['password'])
# Save the User object
new_user.save()
profile = Profile.objects.create(user=new_user)
return render(request, 'account/register_done.html', {'new_user': new_user})
else:
user_form = UserRegistrationForm()
return render(request, 'account/register.html', {'user_form': user_form})
As Selcuk suggested in the comment, add an else clause in your views as below,
from django.http import HttpResponse
def register(request):
if request.method == 'POST':
user_form = UserRegistrationForm(request.POST)
if user_form.is_valid():
# Create a new user object but avoid saving it yet
new_user = user_form.save(commit=False)
# # Set the chosen password
new_user.set_password(
user_form.cleaned_data['password'])
# Save the User object
new_user.save()
profile = Profile.objects.create(user=new_user)
return render(request, 'account/register_done.html', {'new_user': new_user})
else: # form is not valid
return HttpResponse("Form is not valid")
else:
user_form = UserRegistrationForm()
return render(request, 'account/register.html', {'user_form': user_form})
I have the following functions to change a password and display the users profile, but upon submitting the form instead of being redirected to the 'profile/' page I get an error saying The view core.views.change_password didn't return an HttpResponse object. It returned None instead., why is this?
from django.contrib.auth.forms import UserChangeForm, PasswordChangeForm
from django.contrib.auth import update_session_auth_hash
def change_password(request):
if request.method == "POST":
form = PasswordChangeForm(data= request.POST, user = request.user)
if form.is_valid():
form.save()
update_session_auth_hash(request, form.user) #this function keeps the user logged in afte they change their password
# request.user could not have been passed in because that would pass in 'AnonymousUser', however
#form.user gets the user who was filling in the form and passes it to the function
return redirect('/profile')
else:
form = PasswordChangeForm(user = request.user)
args = {'form': form} # gives access to the form in the template
return render(request, 'core/change_password.html', args)
def view_profile(request):
args = {'user': request.user} #
return render(request, 'core/profile.html', args)
Note: The profile page does work on other parts of the site, for example after logging in the user is redirected to their profile page with no issue.
You should move the last two lines out of the else block. This way, you will return a response for POST requests when the form is not valid.
def change_password(request):
if request.method == "POST":
form = PasswordChangeForm(data= request.POST, user = request.user)
if form.is_valid():
...
return redirect('/profile')
else:
form = PasswordChangeForm(user = request.user)
args = {'form': form} # gives access to the form in the template
return render(request, 'core/change_password.html', args)
I've this:
def profile(request, username):
if request.method == 'POST':
if request.user.is_authenticated():
new_message = Message(author = request.user)
form = MessagesForm(request.POST, instance = new_message)
else:
form = MessagesForm(request.POST)
if form.is_valid():
form.save()
else:
to_user = User.objects.get(username = username)
form = MessagesForm(initial = {'user': to_user.pk})
return render(request, "profile.html", {
'username': username,
'form': form,
'messages': messages,
})
This form submit a message and return the same page. My problem is that after the submit I see again my field filled with my information. How to clear it after the submit?
After saving form instead of showing post dict assign the empty form
form = EmployeeForm()
if request.method == "POST":
pDict = request.POST.copy()
form = EmployeeForm(pDict) #if not valid shows error with previous post values in corresponding field
if form.is_valid():
form.save()
form = EmployeeForm() # show empty form no need to give HttpResponseRedirect()
It's standard to redirect after form submission to prevent duplicates.
Just return a redirect to your form on success.
if form.is_valid():
form.save()
return http.HttpResponseRedirect('')
after save() you can return 'form' key with MessagesForm(request.GET) value.
return render(request, "profile.html", {
'username': username,
'form': MessagesForm(request.GET),
'messages': messages,
})
Usually you can initialize the same empty form after you have saved datas:
if request.method == "POST":
rf = RegistrationForm(request.POST)
if rf.is_valid():
print 'Saving datas..'
#logic to save datas
rf = PreRegistrationForm()
return render_to_response('registration/confirmation_required.html', {'settings': settings}, context_instance=RequestContext(request))
Try using HttpResponseRedirect('/') instead of HttpResponseRedirect('') in #Karthikkumar's answer, especially if your home view is an empty path, for instance you have in your urls.py file:
urlpatterns = [path('',views.home_view),]
I had similar issues as those discussed above where HttpResponseRedirect('') directed me to a blank page. Let me know if adding the slash works for you!
You can use this:
Sometimes you can use this idea take attrs={ "autocomplete":"off"} for each inputs.
You can redirect back to the initial post
post_url = request.build_absolute_uri(post.get_absolute_url())
return HttpResponseRedirect(post_url)
please note that 'post' is an instance of the model created
I am hoping you have already defined a logic for GET methods. In the case that you have, all you can do is simply add return request.META['HTTP_REFERER'] at the end.
See what I mean:
def profile(request, username):
if request.method == 'POST':
if request.user.is_authenticated():
new_message = Message(author = request.user)
form = MessagesForm(request.POST, instance = new_message)
else:
form = MessagesForm(request.POST)
if form.is_valid():
form.save()
else:
to_user = User.objects.get(username = username)
form = MessagesForm(initial = {'user': to_user.pk})
return HttpResponseRedirect(request.META['HTTP_REFERER'])
This should work, I just tested it.
**Maybe I am late but for Django 4.x developers can use: **
from .forms import TodoForm
from django.contrib import messages
from django.http import HttpResponseRedirect
def mytodos(request):
form = TodoForm()
if request.method =='POST':
form=TodoForm(request.POST)
if form.is_valid:
form.save()
messages.success(request,'Task saved successfully')
return HttpResponseRedirect('/todo/')
mycontext={'form':form}
return render(request, 'todo/todo.html',mycontext)
in my urls.py: , i have set path('todo/',views.mytodo, name='todolist')
As you can see, after saving form, mycode will redirect to /todo/ which is automatically refreshed after every submit and a fresh form comes again everytime. If you are a good django dev, you will understand what I did. Make sure to reply if you have any queries .Thanks :)
When we reload the page (F5 or ctrl+shift+R), it submits the previously sent data. so instead of refreshing, we will directly hit the url using return HttpResponseRedirect('/posts/')
This way it will show the page with empty form (now even if you refresh it will only show data, won't submit it previous data again)
from django.shortcuts import render, HttpResponseRedirect
from django.views import View
from .models import Post
from .forms import PostForm
class PostListView(View):
def post(self, request, *args, **kwargs):
posts = Post.objects.filter(author=request.user).order_by('-created_on')
form = PostForm(request.POST)
if form.is_valid():
new_post = form.save(commit=False)
new_post.author = request.user
new_post.save()
return HttpResponseRedirect('/posts/')
context = {
'post_list': posts,
'form': form
}
return render(request, 'social/post_list.html', context)