DEV Community

ilija
ilija

Posted on

Web3 backend and smart contract development for Python developers Musical NFTs part 9: Django backend (register new user)

Now it is time to add sign-up functionality to our app. For this to happen add to app authentication urls.py additonal path

  from django.urls import path

    from .views import HomeView, LogoutUser, RegisterUser

    urlpatterns = [
        path("", HomeView.as_view(), name="home"),
        # path("login/", LoginUser.as_view(), name="login"),
        path("logout/", LogoutUser.as_view(), name="logout"),
        # This is new path for registration process 
        path("register/", RegisterUser.as_view(), name="register"),

    ]
Enter fullscreen mode Exit fullscreen mode

Let's define SignUpForm class inside our forms.py (authentication app folder). This SignUpFrom will mainly handle all things related to new users. More details in comments of the code inside forms.py

from django.contrib.auth.forms import UserCreationForm   
    from django.contrib.auth.models import User
    from django import forms 



    class SignUpForm(UserCreationForm):
        # Here widget means form field that show up to user it is text field, text for placeholder 
        # EmailField will make basic validation if email have @ etc.
        # max_length is number of characters this field allow
        # Here we are defining 3 fields from User model
        email = forms.EmailField(label="", widget=forms.TextInput(attrs={'class':'form-control', 'placeholder': 'Email address'}), required=True)
        first_name = forms.CharField(label="", widget=forms.TextInput(attrs={'class':'form-control', 'placeholder': 'First name'}), max_length=100, required=True)
        last_name =  forms.CharField(label="", widget=forms.TextInput(attrs={'class':'form-control', 'placeholder': 'Last name'}), max_length=100, required=True)

        class Meta:
            # Django User model will be used to write to database
            model = User
            # 
            fields = [
                "username", "first_name", "last_name", "email", "password1", "password2",
            ]

        def __init__(self, *args, **kwargs):
            super(SignUpForm, self).__init__(*args, **kwargs)
            # Here we are defining 3 new addtional fields: username, password1 and password2. 
            # Reason why we have two passwords in place it's because we need to confirm that first entry was corrrect
            self.fields['username'].widget.attrs['class'] = 'form-control'
            self.fields['username'].widget.attrs['placeholder'] = 'User Name'
            self.fields['username'].label = ''
            self.fields['username'].help_text = '<span class="form-text text-muted"><small>Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.</small></span>'

            self.fields['password1'].widget.attrs['class'] = 'form-control'
            self.fields['password1'].widget.attrs['placeholder'] = 'Password'
            self.fields['password1'].label = ''
            self.fields['password1'].help_text = '<ul class="form-text text-muted small"><li>Your password can\'t be too similar to your other personal information.</li><li>Your password must contain at least 8 characters.</li><li>Your password can\'t be a commonly used password.</li><li>Your password can\'t be entirely numeric.</li></ul>'

            self.fields['password2'].widget.attrs['class'] = 'form-control'
            self.fields['password2'].widget.attrs['placeholder'] = 'Confirm Password'
            self.fields['password2'].label = ''
            self.fields['password2'].help_text = '<span class="form-text text-muted"><small>Enter the same password as before, for verification.</small></span>'    

Enter fullscreen mode Exit fullscreen mode

In authentication app view.py add new class to handle this registration process (more details on what code do again you can found in code comments)

class RegisterUser(TemplateView):

        def post(self, request): 
            # Everything what user post (means submit the forms with his detils) will be handled with this post method 
            form = SignUpForm(request.POST)
            if form.is_valid():
                form.save()
                # Authenticate use and login
                username = form.cleaned_data['username']
                password = form.cleaned_data['password1']
                user = authenticate(username=username, password=password)
                login(request, user)
                messages.success(request,  "You have been sucesfuly logged in ")
                return redirect("home")
            return render(request, "register.html", {"form": form}) 

        def get(self, request):
            form = SignUpForm()
            return render(request, "register.html", {"form": form}) 

Enter fullscreen mode Exit fullscreen mode

Then in global templates create new register.html to be used inside our view.py

{% extends 'base.html'%}

    {% block content%}

    <div class="col-md-6 offset-md-3"> 
    <h1> Register  </h1>
    <br>

    <form method="POST" action=""> 
        {% csrf_token %}
        {% if form.errors %}
                <div class="alert alert-warning alert-dismissible fade show" role="alert">
                Your Form Has Errors
                {% for field in form %}
                    {% if field.errors %}
                        {{ field.errors }}
                    {% endif %}
                {% endfor %}
                <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
                </div>
            {% endif %}

        {{ form.as_p }}
        <br>
        <button type="submit" class="btn btn-secondary">Register</button>
    </form>
    </div>
    {% endblock %}
Enter fullscreen mode Exit fullscreen mode

Then updatet existing navbar.html template with link for register.html.

 <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
        <div class="container-fluid">
        <a class="navbar-brand" href="{% url 'home' %}">Musical NFT </a>
        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarSupportedContent">
            <ul class="navbar-nav me-auto mb-2 mb-lg-0">

            {% if user.is_authenticated%}
            <li class="nav-item">
            <a class="nav-link" href="{% url 'logout'%}">Logout</a>
            </li>

            {% else %}
            <li class="nav-item">
            <a class="nav-link" href="{% url 'register'%}">Register</a>
            </li>
            <li class="nav-item">
            <a class="nav-link" href="{% url 'home'%}">Login</a>
            </li>
            {% endif%}
                </ul>
            </li>
            </ul>
        </div>
        </div>
    </nav>
Enter fullscreen mode Exit fullscreen mode

And basically this is it. With this we create new forms.py which handle relation to our user database model as well as forms user see on sign-up page (through instantiation of SignUpForm class inside our views.py and using render() function to pass it like context to our register.html template). And this is main pattern that we have here forms.py is kind of bridge between database and front-end. If everything went well on page http://127.0.0.1:8000/register/you should see something like this

Image description

Ones you enter new user data he will be able to login to his profile and in the same time you can find him in admin dashboard under users (or from Django shell by importing User model and then querying database for that concrete user)

Link to github repo

Top comments (0)