DEV Community

Cover image for Create Advanced User Sign Up View in Django | Step-by-Step

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

Rashid on September 22, 2019

This post cross-published with OnePublish Hello DEV Network! In this tutorial we will cover advanced user registration view with Django. First l...
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

Collapse
 
irfanharunk profile image
irfan harun

Hi there,

I just downloaded the code from github and i keep getting the following error :
cannot import name 'six' from 'django.utils'.

Please help me resolve the issue. Thanks

Collapse
 
sree profile image
Sreejith Muralidharan

If you are using Django3,

pip install six

add six to the settings.py INSTALLED_APPS and migrate.

from django.contrib.auth.tokens import PasswordResetTokenGenerator
from six import text_type

class AccountActivationTokenGenerator(PasswordResetTokenGenerator):
    def _make_hash_value(self, user, timestamp):
        return (
            text_type(user.pk) + text_type(timestamp) +
            text_type(user.profile.signup_confirmation)
        )

account_activation_token = AccountActivationTokenGenerator()
Enter fullscreen mode Exit fullscreen mode
Collapse
 
khoding profile image
Julien

hey this doesn't work for me... you say add six to settings.py, do you mean like this ?

INSTALLED_APPS = [
    ...
    'django.contrib.staticfiles',
    'six',
]
Enter fullscreen mode Exit fullscreen mode

Because I always get "Name 'six' is not defined"
And then what do I have to migrate ?

Thread Thread
 
sree profile image
Sreejith Muralidharan

That’s right. Can you try pip freeze and check, six was installed correctly?

Thread Thread
 
khoding profile image
Julien

I managed to fix it after a few tries, so it's good now :)

Collapse
 
jhoanmartinez profile image
Jhoan Martinez Silva

Worked great, adding to setting.py, huge thanks

Collapse
 
thedevtimeline profile image
Rashid

Hey! That's removed in Django 3.0. django-cors-headers supports Django up until 2.1 right now. So, try to use six library instead of

django.utils.six
Collapse
 
kynamd profile image
KyNam Doan

Hello CoderAsha,

Great tutorial format by the way, quite easy to follow.

On my local machine, activation works correctly using my gmail account (EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend').

Email is sent, clicking the link activates the user and sets the signup_confirmation bool value to True and the user may now login.

However, once I push it to my live google VM, it no longer works and gives me the error:
SMTPAuthenticationError at /accounts/signup/
(534, b'5.7.14 \n5.7.14 Please log in via your web browser and then try again.\n5.7.14 Learn more at\n5.7.14 support.google.com/mail/answer/78754 a6sm50520455pgg.25 - gsmtp')

Do you have any idea about this?

Thank you!

Collapse
 
thedevtimeline profile image
Rashid

Hi, I am glad you liked the tutorial. Google blocks sign-in attempts from apps which do not use modern security standard. You can however, turn on/off this safety feature by going to the link below:

google.com/settings/security/lesss...

let me know if it worked for you

Collapse
 
kynamd profile image
KyNam Doan

I just turned this off and it worked. Thanks!

Collapse
 
hasan_mahmudul profile image
Mahmudul Hasan

Image description

You already have the user when you save the form, then why do you need to call the atuhenticate().
Just for clarification can you please explain.

Collapse
 
sopulu497 profile image
Sopulu Nwafor

Awesome post!
Is it possible to modify the UserCreationForm to to include an imagefield so the user uploads an image an image when they are first registering and if they don't then just use the default image

Collapse
 
skipastyyyy profile image
skipastyyyy

yea u can

Collapse
 
msshahata profile image
Shahata

Thank you for this effort @conderasha
I have question, What if I don't use django form in signup stage? how can I insert in two models simultaneously (User & User_Profile)?? In django form I can use (.save(commit = false)). what can I do if I don't use form???

Collapse
 
sirneij profile image
John Owolabi Idogun

I have a Django application I have implemented this registration flow for but the flow has recently been changed.

The new flow requires that when a user registers, a verification email should be sent and after he/she verifies, a notification email should be sent to the admin, but he/she shouldn't be able to login until the admin approves it followed by a notification email.

How can I achieve this without using libraries/apps such as Django-registration-redux and Django-allauth? Please, include working snippets. I

Collapse
 
me24git profile image
me24-git

Hello Sir,

Great tutorial, clean and simple very easy to follow.

Sir can i use it to make an API.

If not then what will be the best way to do so?

Collapse
 
dilipsa profile image
Dilipsa

A little bit confussion ,where the condition is to check user is verified? Only boolean field enough?

Can I implement same concept to login for phone number otp verified user sir?

Thank you gor your great idea.

Collapse
 
cspat profile image
Cephas Patterson • Edited

Hello, I am a student in Ghana.

I'm really grateful and appreciate this tutorial of yours.

This tutorial has been very useful.
When are you going to release the tutorial on how to "configure a production quality email service to send actual confirmation mail".
Really looking forward to that tutorial.

Thank you.

Collapse
 
emmanuelcode profile image
Emmanuel-code

Hello,this is very easy and easy to understand,

Please how do I display the profile in views and templates????
I did a lot but still can't
Please help

Collapse
 
cavinblake profile image
cavinblake

Sir, can you tell me how to verify a profile with something like id card or driving license in django

Collapse
 
alimp5 profile image
alimp5

Thanks a lot :X
a great step by step tutorial....

Collapse
 
gurpreet78371 profile image
gurpreet78371

how will you add bio at the time of signUp?
Actually I want to create Profile along with User creation.

Collapse
 
nhantruong2712 profile image
Nhânđz

Hi coderasha, Can you write a post about Advance Login? Thank you !

Collapse
 
mickilyon profile image
Michael Lyon

Thank you for this post. It really helped me but I’m stuck on this error:

check_token() missing 1 required positional argument: 'token‘

Collapse
 
jaweherbensalah profile image
Jaweher Ben Salah

thank you som much this is so helpfull

Collapse
 
shaphel profile image
Shaphel

Hi coderasha, I couldn't see the user input in the database, please help. I'm new to django and web development

Collapse
 
sourabh9 profile image
Sourabh Dev

Hello,
when i use Registration with Profile Model i got an error type Attribute error.
AttributeError: 'User' object has no attribute 'profile'
what is the solution of this error.
i am new in Django

Collapse
 
billy_de_cartel profile image
Billy Okeyo

I'm having problems with six I have tried using it as a library but still I can't get it to work

Collapse
 
trabelsi10chaima profile image
trabelsi10chaima

hi this error occured to me

AttributeError: module 'roles.tokens.account_activation_token' has no attribute 'make_token'