DEV Community

ilija
ilija

Posted on

Web3 backend and smart contract development for Python developers Musical NFTs part 10: Django backend (user profile)

Having in mind that we want user to be able to see what he own and few more details we should develop user profile page. We will have two type of users: credit card buyer (the ones who want to buy NFT with credit card). And second, crypto buyer who wants to pay his musical NFT directly in USDC (in our case MockUSDC). Part of all users profile page will be the same and part will have different elements (one with credit cards will have Stripe integration for example) and then for crypto buyers we will need direct integration to smart contract. For all this to happen we need to create one new models.py with Customer class. This model will be used to write in our postgres database details about user as well as to track how many NFTs he own. Then we will update get method of our HomeView class to return information about currently logged-in user as context to our template. Then we need to update our template home.html where first we will check if user is crypto buyer (and offer him one type of page with crypto relevant buttons) or credit card buyer where we will offer him functionalitey they need to perform desired operations.

Now let's move first to our database. For now we should define new Customer class model inside authenticatio/models.py. Class can look something like this (details are explained in code comments)

from django.contrib.postgres.fields import ArrayField
from django.db import models



    class Customer(models.Model):

        # Here we define options user will ahve as payment method
        CRYPTO = "CRYPTO"
        CREDIT = "CREDIT"

        OPTIONS = [
            (CRYPTO, "cypto buyer"),
            (CREDIT, "credit card buyer")
        ]

        # Moment when user register 
        created_at = models.DateTimeField(auto_now=True)
        # Some general informations
        first_name = models.CharField(max_length=50, blank=True)
        last_name  = models.CharField(max_length=50, blank=True)
        username = models.CharField(max_length=50, blank=True) 
        email = models.EmailField(max_length=250, blank=True)
        # posibbile means of payment
        type = models.CharField( 
            max_length = 20, 
            choices = OPTIONS, 
            default = 'CRYPTO'
            ) 
        # total number of NFTs bought
        total_no_of_nfts = models.IntegerField(default=0)
        # IDs of bought NFTs
        nft_ids = ArrayField(models.IntegerField(null=True, blank=True), null=True, blank=True) 
        # ID of NFT metadata from NFTs ser bought (more on this in next part of this blog) 
        nft_metadata_ids = ArrayField(models.IntegerField(null=True, blank=True), null=True, blank=True) 

        # This is used just to return user name and last name when we print
        def __str__(self):
            return (f"{self.first_name} {self.last_name}")


Enter fullscreen mode Exit fullscreen mode

Now when we have model lets makemigration and migrate (this basically means to prepare our database for new customers entry). From project root directory

$py manage.py makemigrations
$py manage.py migrate

Enter fullscreen mode Exit fullscreen mode

If we want to see our newly created model inside admin panel we need to add inside authentication/admin.py

from django.contrib import admin

    from .models import Customer

    admin.site.register(Customer)
Enter fullscreen mode Exit fullscreen mode

Now if you go to admin and log as admin user (superuser we create on begining of this serias) you should be able to see new customer. Here is example:

Image description

With our new model in place let's turn to view.py and update existig classes there. For model to work properly here is how our updated class can look like:

rom django.shortcuts import render, redirect
    from django.views.generic import TemplateView
    from django.contrib.auth import authenticate, login, logout
    from django.contrib import messages
    from .forms import SignUpForm
    from .models import Customer



    class HomeView(TemplateView):
        template_name="home.html"

        def post(self, request):
                # check to see if loggin in
                user_name = request.POST["username"]
                password = request.POST["password"]
                user = authenticate(request, username=user_name, password=password)
                if user is not None:
                    login(request, user)
                    messages.success(request, "You have been logged in!")
                    return redirect("home")    
                else:
                    messages.success(request, "There was An Error login in, please try again")
                    return redirect("home")  

        def get(self, request):
            # This is new part compared with previous version of this class
            # Here we get Customer base don logged in user and pass to 
            # template to be render as part of his personal profile ones he is 
            # logged in
            if str(request.user) == "AnonymousUser":
                return render(request, "home.html", {})
            name = str(request.user)
            customer = Customer.objects.get(username=name)
            return render(request, "home.html", {"customer": customer})

    class LogoutUser(TemplateView):    
        def get(self, request):
            logout(request)
            messages.success(request, "You have been logged out!")
            return redirect("home")  


    class RegisterUser(TemplateView):
        # template_name="register.html"

        def post(self, request): 
            # Everything what user send pass to our SignUpForm
            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)
                # We also added this part as I way to update Customer database
                # in the moment when user register himself
                Customer.objects.create(username=user, email=user.email, first_name=user.first_name, last_name=user.last_name)
                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

And last thing in this moment is to updated our home.html template. New thing here is fact that beside check if user is authenticated we also need to check if he is crypto buyer or credit card buyer. Reason for this is fact that we need to show to different users different set of buttons (depending from their payment methods status). Here is new updated code in our home.html

 {% extends "base.html" %}

    {% block content%}


    {% if user.is_authenticated %}

        {% if customer.type == "CRYPTO"%}
        <table class="table  table-hover">
        <thead class="table-dark">
            <tr>
            <th scope="col">Name</th>
            <th scope="col">Email</th>
            <th scope="col">Total no. NFTs</th>
            <th scope="col">Means of payment</th>
            <th scope="col"></th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td> {{ customer.first_name }} {{ customer.last_name }} </td>
                <td> {{ customer.email }} </td>
                <td> {{ customer.total_no_of_nfts }} </td>
                <td> {{ customer.type }} </td>
            </tr>
            </tbody>
        </table>


        <br>
        <h1> Records crypto.. </h1>
        {% else %}

        <table class="table table-striped">
            <thead>
            <tr>
                <th scope="col">Name</th>
                <th scope="col">Email</th>
                <th scope="col">Total no. NFTs</th>
                <th scope="col">Means of payment</th>
                <th scope="col"></th>
            </tr>
            </thead>
            <tbody>
            <tr>
                <td> {{ customer.first_name }} {{ customer.last_name }} </td>
                <td> {{ customer.email }} </td>
                <td> {{ customer.total_no_of_nfts }} </td>
                <td> {{ customer.type }} </td>
            </tr>
        </tbody>
        </table>
        <h1> Records credit card... <h1/>
        {% endif %}
        {% else %}
        <h1> Login </h1>
        <br/>
        <form method="POST" action="{% url 'home' %}"> 
            {% csrf_token %}        
                <div class="mb-3">
                <input type="text" class="form-control" aria-describedby="emailHelp" placeholder="Username" name="username" required>
                </div>
                <div class="mb-3">
                <input type="password" class="form-control" placeholder="Password" name="password" required>
                </div>
                <button type="submit" class="btn btn-secondary">Login</button>

            </form> 

    {% endif %}
    {% endblock content%}
Enter fullscreen mode Exit fullscreen mode

We add in home.html one more if/else statment (to detemrin if he/she is cypto or credit card buyer) and we returned proper page accordingly. And then we just added some bootstrap tables which will be populated with customer context we pass to our template from our view.py. And basiccally that is it. Now when user register himself and login he should see something like this for David Davidson crypto user:

Image description

Link to github code

Top comments (0)