In this part we will try to show inside user profile all musical NFTs user own as set of cards. For this to happen we will need one more model NFTmetadata
. In this model we will add basic informations about existing NFTs (name, description etc.). Inside our already existing file authentication/models.py
we should add following code
from django.contrib.postgres.fields import ArrayField
from django.db import models
class NFTMetadata(models.Model):
name = models.CharField(max_length=100)
description = models.CharField(max_length=2000)
cover_file_name = models.CharField(max_length=50)
def __str__(self):
return (f"{self.name}")
class Customer(models.Model):
CRYPTO = "CRYPTO"
CREDIT = "CREDIT"
OPTIONS = [
(CRYPTO, "cypto buyer"),
(CREDIT, "credit card buyer")
]
created_at = models.DateTimeField(auto_now=True)
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)
type = models.CharField(
max_length = 20,
choices = OPTIONS,
# default="CRYPTO"
)
total_no_of_nfts = models.IntegerField(default=0)
nft_ids = ArrayField(models.IntegerField(null=True, blank=True), null=True, blank=True)
nft_metadata_ids = ArrayField(models.IntegerField(null=True, blank=True), null=True, blank=True)
nft_metadata = models.ManyToManyField(NFTMetadata)
def __str__(self):
return (f"{self.first_name} {self.last_name}")
Now in models.py
we have two new things. First is NFTMetadata
class which will be used to create different NFTMetadata
entries in database. We need this information when we show to user which NFTs he own. Inside our old Customer
class we added one many-to-many filed which will allow us to connect this new NFTMetadata
entries with individual Customer
.
Now for test purpose we will go to Django console and add few NFTMetadata
entries by hand. Just to have some informations to show on front-end. In the same time this is good opportunity for us to demonstrate how powerful can be Django shell
in this development phase.
Inside bash terminal project root directory:
$python managa.py shell
Python 3.8.10 (default, May 26 2023, 14:05:08)
Type 'copyright', 'credits' or 'license' for more information
IPython 8.11.0 -- An enhanced Interactive Python. Type '?' for help.
In [1]: user = Customer.objects.get(username="denis")
Now inside this shell we can work with our models, create them, update, delete and all other things we can do in normal Python class inside views.py
In [1]: from authentication.models import Customer, NFTMetadata
# Here we are grabing user from our database
In [2]: user = Customer(username="denis")
# Now we create few entries for NFTMetadata class
In [3]: nft1 = NFTMetadata(name="Gang of four", description="British post-punk band", cover_file_name="gang_of_four.jpg")
In [4]: nft2 = NFTMetadata(name="Kesih Jones", description="Nigerian singer-songwriter and guitarist.", cover_file_name="kezih_jones.jpg")
In [5]: nft3 = NFTMetadata(name="Cesaria Evora", description="Cesaria Evora, Cape Verdean singer who was known for her rich, haunting voice", cover_file_name="cesaria_evora.jpg")
# Now we need to save our entris in database
In [5] nft1.save()
In [6] nft2.save()
In [7] nft3.save()
# With this we have 3 new entris
# Now we will asigne this three instancies to our denis customer (later to be shown inside his persaonl profile)
In [8] user.nft_metadata.add(nft1, nft2, nft3)
# With this we associate this 3 NFTs metadata to denis user (for test
# purpose only to be shown in his user profile page)
# if we want to check if everything whent well we can type
In [8] metadata = user.nft_metadata.all()
In [9] for x in metadata:
print(x)
Gang of four
Kesih Jones
Cesaria Evora
Ok, now denis user have 3 NFTs associated with his account. Here is important to point out that later on nft_metadata
will be filled automaticaly when user buy new NFT. For now we will do that by hand.
What we need in this moment is to show data as a cards every time user login into his account. For this to happen we will need to render information's about NFTs he own to the front-end. If you can recall we already have customer date of logged in user assigned to variable user inside our HomeView
class. And then in second step from user we will extract all nft_metadata instancies assigned to this profile. What means our views.py
will mainly stay the same except few minor adjustments. Here is new code with inline comments (look at get method)
class HomeView(TemplateView):
def post(self, request):
if "username" in request.POST:
# 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")
else:
user = Customer.objects.get(username=request.user)
form = OrderForm(instance=user, data=request.POST)
if form.is_valid():
form.save()
messages.success(request, "You successfully update payment method")
return redirect("home")
messages.success(request, "There was an error in updating of your payment method")
return redirect("home")
def get(self, request):
if str(request.user) == "AnonymousUser":
return render(request, "home.html", {})
name = str(request.user)
customer = Customer.objects.get(username=name)
# This is new part of code. Here we pull all instancies of
# NFTMetadata class and pass as new contex varibale inside
# `metadata` key
nft_metadata = customer.nft_metadata.all()
form = OrderForm()
return render(request, "home.html", {"customer": customer, "form": form, "metadata": nft_metadata})
class LogoutUser(TemplateView):
def get(self, request):
logout(request)
messages.success(request, "You have been logged out!")
return redirect("home")
class RegisterUser(TemplateView):
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)
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})
What we need to do now is to loop over this value from contex we pass iniside our home.html
template card and to list all things user have inside his user profile. In attempt for all this to work we will need to add one more thing inside home.html
, namely one for loop. Here is how our home.html
file should look like now (later on we will celan up a bit this file)
{% 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>
</tr>
</thead>
<tbody>
<tr>
<td> {{ customer.first_name }} {{ customer.last_name }} </td>
<td> {{ customer.email }} </td>
<td> {{ customer.total_no_of_nfts }} </td>
<td><form action="" method="post">
{%csrf_token%}
{{form.as_p}}
<input type="submit" value="Save" class="btn btn-secondary">
</form>
</td>
</tr>
</tbody>
</table>
{% for card in metadata%}
{% if forloop.counter0|divisibleby:3 %} <div class="row">{% endif %}
<div class="card m-5 p-2" style="width: 18rem;">
{% load static %}
<img src="{% static 'nft/'%}{{card.cover_file_name}}" class="card-img-top" alt="..." width="50" height="200"/>
<div class="card-body">
<h5 class="card-title">{{card.name}}</h5>
<br>
<p class="card-text">{{card.description}}</p>
</div>
</div>
{% if forloop.counter|divisibleby:3 or forloop.last %}</div> {% endif %}
<br>
{% endfor %}
{% else %}
<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>
</tr>
</thead>
<tbody>
<tr>
<td> {{ customer.first_name }} {{ customer.last_name }} </td>
<td> {{ customer.email }} </td>
<td> {{ customer.total_no_of_nfts }} </td>
<td><form action="" method="post">
{%csrf_token%}
{{form.as_p}}
<input type="submit" value="Save" class="btn btn-secondary">
</form>
</td>
</tr>
</tbody>
</table>
{% for card in metadata%}
{% if forloop.counter0|divisibleby:3 %} <div class="row">{% endif %}
<div class="card m-5 p-2" style="width: 18rem;">
{% load static %}
<img src="{% static 'nft/'%}{{card.cover_file_name}}" class="card-img-top" alt="..." width="50" height="200"/>
<div class="card-body">
<h5 class="card-title">{{card.name}}</h5>
<br>
<p class="card-text">{{card.description}}</p>
</div>
</div>
{% if forloop.counter|divisibleby:3 or forloop.last %}</div> {% endif %}
<br>
{% endfor %}
<p> credit card </p>
{% endif %}
{% else %}
<div class="col-md-6 offset-md-3">
<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>
</div>
{% endif %}
{% endblock content%}
As you can see above {% load static %}
we added one for loop to loop over all NFT metadata user have. Ones we pick up first entry we will fill in our card and go to next till the end. Now if you run your Django server and go to browser on http://127.0.0.1:8000
you should see something like this
Github code
Top comments (0)