RelatedObjectDoesNOTExist-Edit profile - django-views

Django==1.10.5. I have a problem RelatedObjectDoesNotExist
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()
# Create the user profile
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})
and
#login_required
def edit(request):
if request.method == 'POST':
user_form = UserEditForm(instance=request.user,
data=request.POST)
profile_form = ProfileEditForm(instance=request.user.profile,
data=request.POST,
files=request.FILES)
if user_form.is_valid() and profile_form.is_valid():
user_form.save()
profile_form.save()
else:
user_form = UserEditForm(instance=request.user)
profile_form = ProfileEditForm(instance=request.user.profile)
return render(request, 'account/edit.html', {'user_form': user_form,
'profile_form': profile_form})
The problem is that:
profile_form = ProfileEditForm(instance=request.user.profile)

I have similar experience working on this particular exercise.
The error is coming right from code below
Profile_form = ProfileForm(request.POST, instance=request.user.profile)
We are trying to get "request.user.profile" not realizing "User" in the model doesn't have a "profile" but a Profile has a"User" . Therefore a better way to get the "profile":
profile = Profile(user=request.user)
Hence your edit method should look close to this:
#login_required
def edit(request):
profile = Profile(user=request.user)
if request.method == 'POST':
user_form = UserEditForm(instance=request.user,data=request.POST)
profile_form = ProfileEditForm(instance=profile,
data=request.POST,
files=request.FILES)
if user_form.is_valid() and profile_form.is_valid():
user_form.save()
profile_form.save()
messages.success(request, 'Profile updated successfully')
else:
messages.success(request, 'Error updating your profile')
user_form = UserEditForm(instance=request.user)
profile_form = ProfileEditForm(instance=profile)
return render(request,
'accounts/edit.html',
{'user_form': user_form,
'profile_form': profile_form})

Just to answer this question, this code is a snippet from the Django By Example book from the project Building a Social Website.
I encountered the same error when I clicked on the edit your profile link in the dashboard.
So, to solve this error, if you are logged in as a superuser, then go to the admin site of your project (url: localhost/admin/) and then under the Account heading, click on Profiles and click the Add profile link on the top right corner. Select the user from the dropdown, add the profile details and click save.
Now going back to the dashboard and clicking the edit your profile link should display the desired view.

I tried another alternative this scenario is that when we update our code we have some users that registered but not have a profile. I deleted the users and in admin and signed up with account it worked
but you will have a problem when logging with facebook

Related

Why django form post with errors updates instance

I have a standard user update form like
#login_required()
def personal(request):
if request.method == 'POST':
user_form = UserForm(request.POST, instance=request.user)
if user_form.is_valid():
user = user_form.save()
update_session_auth_hash(request, user)
messages.success(request, 'Your personal data has been changed successfully!')
return redirect('profile')
else:
user_form = UserForm(instance=request.user)
context = {
'form': user_form,
}
return render(request, 'personal.html', context)
The problem here is in the line user_form.is_valid(). It runs validation logic which collects an error when username is already taken by another user. In this case we have ValidationError raised but the instance in this form is updated nevertheless due to code in django's construct_instance function logic:
def construct_instance(form, instance, fields=None, exclude=None):
"""
Construct and return a model instance from the bound ``form``'s
``cleaned_data``, but do not save the returned instance to the database.
"""
...
f.save_form_data(instance, cleaned_data[f.name])
...
I found this behavior very strange. How can I avoid updating user's instance fields with wrong values if I need, say, display initial user's username on the top of my page?

Is there a way to register new users with Django registration templates that would prevent them from logging in until admin has manually reviewed?

I'm working on login/registration views in Django in a project that requires that the admin manually reviews the application before the user can actually login...while saving the information they provided at the registration page.
In the past I didn't have projects that required the users be reviewed manually by the admins.
def register(request):
if request.method == "POST":
form = UserCreationForm(request.POST)
if form.is_valid():
new_user = form.save()
login(request, new_user)
return index(request)
else:
form = UserCreationForm()
return render(request, "registration/register.html", {"form": form})
This is what I would normally write...but even if I don't include the login(request, new_user), the new_user would be able to do so himself after the new_user is created...
I need to make sure they still can't login until the admin has manually reviewed his application to join.
Django has a semi built in way to do this. Use user.is_active, assuming that you are using the default authentication backend (you almost certainly are if you aren't sure what that is).
new_user.refresh_from_db()
new_user.is_active = False
new_user.save()
Just add these three lines after new_user = form.save()
def register(request):
if request.method == "POST":
form = UserCreationForm(request.POST)
if form.is_valid():
new_user = form.save()
new_user.refresh_from_db()
new_user.is_active = False
new_user.save()
return HttpRequest("Thank you for signing up. Your account is pending review.")
else:
form = UserCreationForm()
return render(request, "registration/register.html", {"form": form})
Administrators can login to the Admin site and manually approve the user by changing the is_active element.

AttributeError at /basic_app/register/ : 'tuple' object has no attribute 'get'

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 })

Why am I getting the error local variable 'user_form' referenced before assignment

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})

The view account.views.register didn't return an HttpResponse object

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})