My Journey on how I built a marketplace part 2

·

4 min read

This article continues from the first series which can be found here in part 1. After creating the custom user and the product app, I created the database for the product using this method.

from django.db import models
from django.conf import settings
from django.utils.translation import gettext_lazy as _
# Create your models here.

User = settings.AUTH_USER_MODEL
class Category(models.Model):
    name = models.CharField(_('Create Name of Category'), 
                            max_length=100,
                            unique=True)

    class Meta:
        verbose_name_plural = 'Categories'

    def __str__(self):
        return self.name


class Product(models.Model):
    STATUS = (
        ("Available", "Available"),
        ("Uavailable", "Unavailable")
    )
    user = models.ForeignKey(User, null=True, on_delete=models.CASCADE, related_name='user')
    name = models.CharField(_('Enter product name'), max_length=100)
    image = models.ImageField(upload_to='media/product')
    price = models.DecimalField(max_digits=8, decimal_places=2, default=0)
    quantity = models.IntegerField(default=0)
    stock = models.CharField(choices=STATUS, default='available', max_length=100)
    category = models.ForeignKey(Category, on_delete=models.PROTECT, related_name='products',
                                 null=True,
                                 blank=True)
    description = models.TextField()
    created = models.DateTimeField(auto_now_add=True)

    class Meta:
        indexes = [ 
            models.Index(fields=['-created'])
        ]
        ordering = ['-created']

    def __str__(self):
        return self.name

Then I added it to the admin page by going to the admin.py file of the product folder. One of the reasons I had to add it to the admin.py file is to make changes possible using the superuser.

from django.contrib import admin
from . models import Product

# Register your models here.
admin.site.register(Product)
admin.site.register(Category)

now if we run the server, we should see the product page and category page on the admin page like this.

I created categories and products on their respective pages and saved them.

Creating the Product and Category API

I created a file in my product app called serializers.py then I made use of serializers which as built with the Django rest framework. Before I proceed any further, let me try to explain what serializers are. Serializers allow complex data such as query sets and model instances to be converted to native Python datatypes that can then be easily rendered into JSON, XML or other content types. Now that we have an understanding of what serializers are, it's time to implement them in our project.

so in the serializers.py file of the product app, I wrote this code there

from rest_framework import serializers
from rest_framework.reverse import reverse

from .models import (Product,
                            Category,
)

class CategorySerializer(serializers.ModelSerializer):
    class Meta:
        model = Category
        fields = ('name', 'products')
        depth = 1

class ProductListSerializer(serializers.ModelSerializer):
    user = UserSerializer(read_only=True)
    url = serializers.SerializerMethodField()
    category = CategorySerializer()
    class Meta:
        model = Product
        fields = [
                  'user',
                  'name',
                  'category',
                  'image',
                  'price',                  
                  'quantity',
                  'stock',
                  'url',
                  ]


    def get_url(self, obj):
        request = self.context['request']
        return {
            'url': reverse('product-detail', 
                           kwargs={'pk':obj.pk},
                           request=request)
        }


class ProductDetailSerializer(serializers.ModelSerializer):
    user = UserSerializer(read_only=True)
    class Meta:
        model = Product
        fields = ['user', 
                  'name',
                  'image',
                  'price',
                  'quantity',
                  'stock',
                  'description',
                  'category',
                  ]

then I created views on the product app using this code

from django.shortcuts import render
from rest_framework.viewsets import ModelViewSet


# importing serializers and models
from . import serializers
from .models import (
    Product, Category
)

# Create your views here.
class CategoryViewApi(ModelViewSet):
    queryset = Category.objects.all()
    serializer_class = serializers.CategorySerializer    

class ProductViewApi(ModelViewSet):
    queryset = Product.objects.all()
    serializer_class = serializers.ProductDetailSerializer

    def get_serializer_class(self):
        if self.action in ['list']:
            return serializers.ProductListSerializer
        return super().get_serializer_class()

Then I created a URL for the API that was created. One amazing thing about Django is that it makes it possible to view the API using something called browsable API, theirs is no need to use an external application before you can view the API.

So I created a url.py file in the product app and then I included it in my project app as well.

Product app

from django.urls import path
from rest_framework.routers import DefaultRouter
from . import views

router = DefaultRouter()

router.register('product', 
                views.ProductViewApi, 
                basename='product')

router.register('category', views.CategoryViewApi, 
                basename='category')

urlpatterns = router.urls

and in the project urls.py file, I added this code

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', include('product.urls')),
]

Now when I run the server, I get the following screen

The beautiful thing about using DefaultRouter is that it makes it possible to get a clickable URL. So when I click on the product URL I get the below result

I'll round up with this, the next part would come soon.

Please if you have any suggestions, I would love to know, help me grow and get better thanks.