DEV Community

Discussion on: Create Advanced User Sign Up View in Django | Step-by-Step

Collapse
 
supergoogler profile image
SuperGoogler

Hello coderasha,
I have tried most of the websites where I could look for an answer, but I didn't get any. Since I am new to web development, so not able to debug the issue properly. I have scratched every part of my head with no luck. I hope you would help me.

My website workflow is as below:

1) user sign up and redirect to login screen once registration successful.
2) user login and now he/she sees a form, where he/she needs to fill in mandatory fields
3) save and then either click on "profile" link(in the navbar) to see the profile data, or "save" button will redirect to the profile page automatically.

what's working:

  • Registration page
  • login page
  • user successfully able to fill in the extra information
  • redirect to the logged in user's profile page.
  • Data getting saved in DB.

What's not working:
The profile page that is getting generated for logged in user has the data showing up for default User model, i.e(first_name, last_name, and email). However, the other information like (dob, photo, country, state) etc, is not getting populated on the profile page.

What I have tested already.
I learned that "request.user.model_name" will help to populate the information. So, for that I have to create signals. I have done that as well, but no luck.

Errors:

RelatedObjectDoesNotExist at /profile/
User has no userprofile.
Request Method: GET
Request URL: 127.0.0.1:8000/profile/
Django Version: 3.0.5
Exception Type: RelatedObjectDoesNotExist
Exception Value:

User has no userprofile.
Exception Location: C:\Python38\lib\site-packages\django\db\models\fields\related_descriptors.py in get, line 420
Python Executable: C:\Python38\python.exe
Python Version: 3.8.2
Python Path:

['C:\Users\anshu\djago-project\SkoolSkill',
'C:\Python38\python38.zip',
'C:\Python38\DLLs',
'C:\Python38\lib',
'C:\Python38',
'C:\Python38\lib\site-packages']

Server time: Sun, 3 May 2020 15:48:15 +0000

So, to test further I used "request.user"(at this point signal or no signal, the data comes for those 3 fields). So, as said, only few fields populate the data from DB, but the custom fields doesn't

Below are my django files details:

views.py

from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from .forms import SignUpForm, UserProfileForm
from django.views.decorators.csrf import csrf_exempt

def login_user(request):
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
messages.success(request, f'login success')
return redirect('bolo')
else:
messages.error(request, f'error while login, please try again')
return redirect('login')
else:
return render(request, 'authenticate\login.html', {})

def userprofileview(request): # Authenticated user filling the form to complete the registration
if request.method == 'POST':
form = UserProfileForm(request.POST, request.FILES)
if form.is_valid():
form.save()
messages.success(request, f'Profile has been updated successfully')
return redirect('/profile')
else:
messages.error(request, AssertionError)
else:
form = UserProfileForm()
return render(request, 'authenticate\bolo.html', context={'form': form})

@login_required
def profile_page(request): # Fetching data from DB to show user's complete profile page
form = UserProfileForm()
data = request.user.userprofile
context = {'form': form, 'data': data}
return render(request, 'authenticate\profile.html', context)

urls.py

urlpatterns = [
path('', home, name='home'),
path('contact/', home, name='contact'),
path("login/", login_user, name='login'),
path("logout/", logout_user, name='logout'),
path("register/", register_user, name='register'),
path("bolo/", userprofileview, name='bolo'),
path('profile/', profile_page, name='profile'),
]

models.py

from django.db import models
from django.urls import reverse
from django.contrib.auth.models import User

class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, null=True)
Photo = models.FileField(upload_to='documents/%Y/%m/%d/', null=True)
uploaded_at = models.DateTimeField(auto_now_add=True, null=True)
dob = models.DateField(max_length=20, null=True)
country = models.CharField(max_length=100, null=True)
State = models.CharField(max_length=100, null=True)
District = models.CharField(max_length=100, null=True)
phone = models.CharField(max_length=10, null=True)

def get_absolute_url(self):
    return reverse('profile', kwargs={'id': self.id})
Enter fullscreen mode Exit fullscreen mode

profile.html

        <p>Photo:</p>
        <p><img src =` {{ form_data.image.url }}` width="200" height="200" /></p>
        <p>email:`{{ data.email }}`</p>
        <p>fname:`{{ data.first_name }}`</p>
        <p>lname:`{{ data.last_name }}`</p>
        <p>DOB:`{{ form_data.dob }}`</p>
        <p>Country: `{{ form_data.country }}`</p>
        <p>State: `{{ form_data.State }}`</p>
        <p>District: `{{ form_data.District }}`</p>
Enter fullscreen mode Exit fullscreen mode

signals.py

from django.db.models.signals import post_save
from django.contrib.auth.models import User
from django.dispatch import receiver
from .models import UserProfile
+

@receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)

@receiver(post_save, sender=User)
def save_profile(sender, instance, **kwargs):
instance.userprofile.save()

apps.py

from django.apps import AppConfig

class AuthenticationConfig(AppConfig):
name = 'AUTHENTICATION'

def ready(self):
    import AUTHENTICATION.signals
Enter fullscreen mode Exit fullscreen mode

I will be very grateful to you if you could help me out.
Thank you

Collapse
 
thedevtimeline profile image
Rashid

Hey! Sorry for late answer. It seems your queryset is not correct. Can you please change

data = request.user.userprofile

to

data = UserProfile.objects.filter(user=request.user)

and finally, update your profile.html:

        <p>Photo:</p>
        <p><img src =`{{ data.image.url }}` width="200" height="200" /></p>
        <p>email:`{{ data.email }}`</p>
        <p>fname:`{{ data.first_name }}`</p>
        <p>lname:`{{ data.last_name }}`</p>
        <p>DOB:`{{ data.dob }}`</p>
        <p>Country: `{{ data.country }}`</p>
        <p>State: `{{ data.State }}`</p>
        <p>District: `{{ data.District }}`</p>
Collapse
 
supergoogler profile image
SuperGoogler

Hi,

Thank you for your reply. I followed your instructions, but now no data is getting populated at all. Just the field names are showing up. I have attached the screenshot.
Please suggest

Regards,
Amitesh

Thread Thread
 
thedevtimeline profile image
Rashid

Try this one:

from django.shortcuts import render, redirect, get_object_or_404
data = get_object_or_404(UserProfile, user=request.user)

Btw I can't see any screenshots but I think it should work now

Thread Thread
 
supergoogler profile image
SuperGoogler

Not working, and the strangest part is that the registration, and login is getting successful. The data is going to the database for User model, but now the data has stopped going for the "UserProfile" model to the DB. Before, though the data was not showing up on the web page but the data was going the DB. Below is the ORM query output

User.objects.all()
, , , , , ]>

UserProfile.objects.all()


I really appreciate your effort, and hope we rectify the issue soon. If you are comfortable, I can share my project as a compressed file with you if you would like to test in your environment.
Below is what I see on the web page:

email: email@gmail.com
fname: sam
lname: Sahay
DOB:
Country:
State:
District:

As you could see, first three fields are populating data, but rest not.

Amitesh

Thread Thread
 
supergoogler profile image
SuperGoogler

Please disregard the previous reply. My apologies. The data is showing up in the database for User model as well as the UserProfile model. I will keep you posted over the latest suggestion by you. There is some issues with the routes . I need to fix that before I see the profile page.

Thank you again.
Amitesh

Thread Thread
 
supergoogler profile image
SuperGoogler

Hi,

Ok, so there has been some progress. I followed you instructions as well as I modified the function that is responsible to let the authenticated users fill in the form. Below are the two functions that is now modified.

def userprofileview(request): # Authenticated user filling the form to complete the registration
if request.method == 'POST':
form = UserProfileForm(request.POST, request.FILES)
if form.is_valid():
pr = UserProfile()
pr.user = User.objects.get(id=request.user.id)
# pr.first_name = form.cleaned_data['first_name']
# pr.last_name = form.cleaned_data['last_name']
# pr.email = form.cleaned_data['email']
pr.dob = form.cleaned_data['dob']
pr.country = form.cleaned_data['country']
pr.State = form.cleaned_data['State']
pr.District = form.cleaned_data['District']
pr.phone = form.cleaned_data['phone']
pr.save()
messages.success(request, f'Profile has been updated successfully')
return redirect('/profile')
else:
messages.error(request, AssertionError)
else:
form = UserProfileForm()
return render(request, 'authenticate\bolo.html', context={'form': form})

@login_required
def profile_page(request): # Fetching data from DB to show user's complete profile page
data = get_object_or_404(UserProfile, user=request.user)
print('data=', data)
context = {'data': data}
return render(request, 'authenticate\profile.html', context)

1)As you could see in the "userprofileview" view, I have used the form.cleaned_data[] for all the form fields.

2) In the "profile_page", I have used your suggestion.

The change in the webpage is that, now I could see data for all the fields from the custom model UserProfile. However, now the fname, lname, and email is not populating the data.

email:
fname:
lname:
DOB:May 4, 2020
Country: India
State: Mahrashtra
District: Pune

So, I tried the form.cleaned_data() over the first_name, last_name and email. However, it didn't work.
Please suggest,

Thank you
amitesh