In my previous tutorial i wrote about building Go-lang micro-services,in this tutorial i want to us to build a single application to serve GraphQL and REST at the same time. It will be an e-commerce API and depending on the reception we might get to building a front-end store based on React or React-Native(vote below in the comments).
We will be using the python framework called Django and the tool DRF(Django Rest Framework). To authenticate our API we will be implementing one scheme that comes out of the box with Django-rest and also one more third-party scheme just for demonstration purposes.
In the front-end i intend to use react-native, to build a simple mobile front-end store or react for a simple we-app, it will entirely depend on what the readers will prefer.
I intend to break this application into three small parts:
- Build a simple Django REST API
- Build a simple Django Graphql API based on the models we define for the REST API above.
- Build a simple front-end app using React-Native/ React
You can refer to this respository if you get stuck.
Get yourself a warm cup of coffee and Lets begin.....
REST API BACK-END.
setting up our development Environment.
You either have Pipenv or Virtualenv installed in your system(if not i advice you to get those installed because they help us create an isolated development environment for our application).
if you have virtualenv installed in your system,open your terminal create a directory graphRestAPI and inside that directory create a development environment as below.
mykmyk@skynet:~/graphRestAPI$ virtualenv venv
Using base prefix '/usr'
New python executable in /home/mykmyk/graphRestAPI/venv/bin/python
Installing setuptools, pip, wheel...done.
To activate our newly created environment:
mykmyk@skynet:~/graphRestAPI$ source venv/bin/activate
(venv) mykmyk@skynet:~/graphRestAPI$
Now in this environment we install all the packages that we will be using in this application, we start with our framework Django and the django-rest tool.
(venv) mykmyk@skynet:~/graphRestAPI$ pip install Django djangorestframework
we then create a project using Django admin to house our apps, this structure while being a bit more code verbose, allows for better scaling of our applications.
We type in the following commands in our terminal.
(venv) mykmyk@skynet:~/graphRestAPI$ django-admin startproject CoreAPI
(venv) mykmyk@skynet:~/graphRestAPI$ ls
CoreAPI venv
enter into the newly created 'CoreAPI' project folder and create an app that will hold all the project specific apps.
(venv) mykmyk@skynet:~/graphRestAPI/CoreAPI$ django-admin startapp coreGraphRestAPI
(venv) mykmyk@skynet:~/graphRestAPI/CoreAPI$ ls
CoreAPI coreGraphRestAPI manage.py
move into the newly created 'coreGraphRestAPI' and delete the files , admin.py, models.py, tests.py,views.py
(venv) mykmyk@skynet:~/graphRestAPI/CoreAPI/coreGraphRestAPI$ ll
total 32
drwxrwxr-x 3 mykmyk mykmyk 4096 Jun 19 09:55 ./
drwxrwxr-x 4 mykmyk mykmyk 4096 Jun 19 09:55 ../
-rw-rw-r-- 1 mykmyk mykmyk 63 Jun 19 09:55 admin.py
-rw-rw-r-- 1 mykmyk mykmyk 164 Jun 19 09:55 apps.py
-rw-rw-r-- 1 mykmyk mykmyk 0 Jun 19 09:55 __init__.py
drwxrwxr-x 2 mykmyk mykmyk 4096 Jun 19 09:55 migrations/
-rw-rw-r-- 1 mykmyk mykmyk 57 Jun 19 09:55 models.py
-rw-rw-r-- 1 mykmyk mykmyk 60 Jun 19 09:55 tests.py
-rw-rw-r-- 1 mykmyk mykmyk 63 Jun 19 09:55 views.py
(venv) mykmyk@skynet:~/graphRestAPI/CoreAPI/coreGraphRestAPI$ rm admin.py models.py tests.py views.py
We then move into the 'CoreAPI' folder containing our 'settings.py' that houses our Django configurations, we then add our main app and our django-rest to the INSTALLED_APPS:
#CoreAPI/settings.py
33 INSTALLED_APPS = [
34 'django.contrib.admin',
35 ....
39 'django.contrib.staticfiles',
40 'rest_framework',
41 'coreGraphRestAPI'
42 ]
Create User Application:
We will now create a user application for our project, To create a user application
(venv) mykmyk@skynet:~/graphRestAPI/CoreAPI$ ls
CoreAPI coreGraphRestAPI manage.py
(venv) mykmyk@skynet:~/graphRestAPI/CoreAPI$ cd coreGraphRestAPI/ && python ../manage.py startapp Users
now if we move into the 'coreGraphRestAPI' folder we see:
(venv) mykmyk@skynet:~/graphRestAPI/CoreAPI/coreGraphRestAPI$ ll
total 24
drwxrwxr-x 5 mykmyk mykmyk 4096 Jun 19 10:24 ./
drwxrwxr-x 4 mykmyk mykmyk 4096 Jun 19 09:55 ../
-rw-rw-r-- 1 mykmyk mykmyk 164 Jun 19 09:55 apps.py
-rw-rw-r-- 1 mykmyk mykmyk 0 Jun 19 09:55 __init__.py
drwxrwxr-x 2 mykmyk mykmyk 4096 Jun 19 09:55 migrations/
drwxrwxr-x 2 mykmyk mykmyk 4096 Jun 19 10:24 __pycache__/
drwxrwxr-x 3 mykmyk mykmyk 4096 Jun 19 10:24 Users/
we now have to add this application to our settings.py
INSTALLED_APPS = [
34 'django.contrib.admin',
...
40 'rest_framework',
41 'coreGraphRestAPI',
42 'coreGraphRestAPI.Users',
43 ]
we then move into the file 'coreGraphRestAPI/Users' and open the file apps.py and add in the following
1 from django.apps import AppConfig
2
3
4 class UsersConfig(AppConfig):
5 default_auto_field = 'django.db.models.BigAutoField'
6 name = 'coreGraphRestAPI.Users'
7 label = 'coreGraphRestAPI_Users'
And then open the file "init.py " in the same folder and add the following:
1 default_app_config = 'coreGrapRestAPI.Users.apps.UsersConfig'
Sewing Our User Logic Together.
Django Auth System
Django comes with a built-in user authentication system. It handles user accounts, groups, permissions and cookie-based sessions. Django's authentication system handles both authentication and authorization.
However, we usually find that this out of the box solution doesn't cover all our use cases and we need to extend it to fit our specific project needs
User Model
In this case we will be creating a Custom user model by wrapping the Django AbstractBaseUser class. Our custom user will extend AbstractBaseUser and we will rewrite the UserManager to customize creation of a user in our database.
Lets dive into it.....
open the file "graphRestAPI/CoreAPI/coreGraphRestAPI/Users/models.py" and add the following code to it.
1 from django.db import models
2 from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManager
3
4
5 class UserManager(BaseUserManager):
6 def create_user(self, email, password, **extra_fields):
7 if not email:
8 raise ValueError("Email is required")
9
10 email = self.normalize_email(email)
11 user = self.model(email=email, **extra_fields)
12 user.set_password(password)
13 user.save()
14 return user
15
16 def create_superuser(self, email, password, **extra_fields):
17 extra_fields.setdefault('is_staff', True)
18 extra_fields.setdefault('is_superuser', True)
19 extra_fields.setdefault('is_active', True)
20 extra_fields.setdefault('first_name', "admin")
21 extra_fields.setdefault('last_name', "admin")
22
23 if not extra_fields.get("is_staff", False):
24 raise ValueError('Superuser must have is_staff=True.')
25
26 if not extra_fields.get("is_superuser", False):
27 raise ValueError('Superuser must have is_staff=True.')
28
29 return self.create_user(email, password, **extra_fields)
30
31
32
33 class ImageUpload(models.Model):
34 image = models.ImageField(upload_to="images")
35
36 def __str__(self):
37 return str(self.image)
38
39
40 class UserProfile(models.Model):
41 #user = models.OneToOneField(User, related_name="user_profile", on_delete=models.CASCADE)
42 profile_picture = models.ForeignKey(ImageUpload, related_name="user_images", on_delete=models.SET_NULL, null=True)
43 dob = models.DateField()
44 phone = models.PositiveIntegerField()
45 country_code = models.CharField(default="+234", max_length=5)
46 created_at = models.DateTimeField(auto_now_add=True)
47 updated_at = models.DateTimeField(auto_now=True)
48
49 def __str__(self):
50 return self.user.email
51
52
53 class UserAddress(models.Model):
54 user_profile = models.ForeignKey(UserProfile, related_name="user_addresses", on_delete=models.CASCADE)
55 street = models.TextField()
56 city = models.CharField(max_length=100)
57 state = models.CharField(max_length=100)
58 country = models.CharField(max_length=100, default="Nigeria")
59 is_default = models.BooleanField(default=False)
60
61 created_at = models.DateTimeField(auto_now_add=True)
62 updated_at = models.DateTimeField(auto_now=True)
63
64 def __str__(self):
65 return self.user_profile.user.email
66
67
68
69 class User(AbstractBaseUser, PermissionsMixin):
70 email = models.EmailField(unique=True)
71 first_name = models.CharField(max_length=100, default="yourfirstname")
72 last_name = models.CharField(max_length=100, default="yourlastname")
73 user_address = models.OneToOneField(UserAddress, related_name="user_address",blank=True, null=True, on_delete=models.CASCADE)
74 created_at = models.DateTimeField(auto_now_add=True)
75 updated_at = models.DateTimeField(auto_now=True)
76
77 is_staff = models.BooleanField(default=False)
78 is_active = models.BooleanField(default=True)
79
80 USERNAME_FIELD = "email"
81 objects = UserManager()
82
83 def __str__(self):
84 return self.email
85
86 def save(self, *args, **kwargs):
87 super().full_clean()
88 super().save(*args, **kwargs)
Then head to your "settings.py" file in the folder "graphRestAPI/CoreAPI/CoreAPI" , in hat file add the following line , what it does is it now uses our extension of the Django User as the application user for things like authentication, cookie-based session management etc.
*settings.py *
AUTH_USER_MODEL = 'coreGraphRestAPI_Users.User'
The next logical step is serialization of our data, i.e our recently defined models.Serialization refers to the process of converting a data object (e.g., Python objects, Tensorflow models) into a format that allows us to store or transmit the data and then recreate the object when needed using the reverse process of de-serialization. In this case we will be serializing our data from python native objects to JSON for transmission and then de-serializing from JSON format into python native data types for storage.
create a file "serializer.py" in the folder "graphRestAPI/CoreAPI/coreGraphRestAPI/Users", open that file and add in the following code:
serializer.py
1 from django.contrib.auth import get_user_model
2 from rest_framework import serializers
3 from rest_framework.reverse import reverse
4 from .models import UserProfile, UserAddress, ImageUpload
5 from drf_writable_nested import WritableNestedModelSerializer
6
7
8
9 User = get_user_model()
10
11
12 class ImageUploadSerializer(serializers.ModelSerializer):
13 class Meta:
14 model = ImageUpload
15 fields = ('image',)
16
17
18 class UserProfileSerializer(WritableNestedModelSerializer, serializers.ModelSerializer):
19 profile_picture = ImageUploadSerializer(read_only = False)
20 class Meta:
21 model = UserProfile
22 fields = ('profile_picture','dob','phone','country_code')
23
24
25 class UserAddressSerializer(WritableNestedModelSerializer, serializers.ModelSerializer):
26 user_profile = UserProfileSerializer(read_only = False)
27
28 class Meta:
29 model = UserAddress
30 fields = ('user_profile','street','city','state','country','is_default')
31
32
33
34 class UserSerializer(WritableNestedModelSerializer, serializers.ModelSerializer):
35 links = serializers.SerializerMethodField('get_links')
36 user_address = UserAddressSerializer(read_only=False)
37
38 class Meta:
39 model = User
40 fields = ('id', User.USERNAME_FIELD,'password','first_name','last_name','user_address','is_active','links')
41
42
43 def get_links(self, obj):
44 request = self.context['request']
45 username = obj.get_username()
46
47 return {
48 #'self': reverse('user-detail',
49 #kwargs = {User.USERNAME_FIELD: username}, request=request),
50 }
run the command below to install the drf_writable tool
pip install drf_writable_nested
All we are doing in the above code is creating serializer and deserializer classes for our three models: User model, UserProfile model, UserAddress model.
We are using the tool "drf_writable_nested" to serialize our nested classes, because of the one_to_one and one_to_many relationship between our model classes.
Next on the table is to create viewsets. Now, there are many ways to go about this but to make the process simple , i will be using viewsets.ModelViewSet, The ModelViewSet class inherits from GenericAPIView and includes implementations for various actions, by mixing in the behavior of the various mixin classes.
The actions provided by the ModelViewSet class are .list(), .retrieve(), .create(), .update(), .partial_update(), and .destroy().
Also note that although this class provides the complete set of create/list/retrieve/update/destroy actions by default, you can restrict the available operations by using the standard permission classes.
open the file "views.py" in the folder "graphRestAPI/CoreAPI/coreGraphRestAPI/Users",
views.py
1 from django.contrib.auth import get_user_model
2 from rest_framework import authentication, permissions, viewsets, filters
3 from .serializer import UserSerializer
4 from django_filters.rest_framework import DjangoFilterBackend
5
6
7
8 from oauth2_provider.contrib.rest_framework import TokenHasReadWriteScope, TokenHasScope
9
10
11 User = get_user_model()
12
13 class DefaultsMixin(object):
14 """Default settings for view authentication, permissions, filtering and pagination."""
15 authentication_classes = (
16 authentication.BasicAuthentication,
17 authentication.TokenAuthentication,
18 )
19 permission_classes = (
20 permissions.IsAuthenticated,
21 #TokenHasReadWriteScope,
22 )
23 paginate_by = 25
24 paginate_by_param = 'page_size'
25 max_paginate_by = 100
26 filter_backends = (
27 DjangoFilterBackend,
28 filters.SearchFilter,
29 filters.OrderingFilter
30 )
31
32 class UserViewSet(DefaultsMixin, viewsets.ModelViewSet):
33 """API endpoint for listing users."""
34
35 lookup_field = User.USERNAME_FIELD
36 lookup_url_kwarg = User.USERNAME_FIELD
37 queryset = User.objects.order_by(User.USERNAME_FIELD)
38 serializer_class = UserSerializer
run the following in your terminal
pip install django-filter==21.1 django-oauth-toolkit==2.0.0
Notice Our DefaultsMixin Class above.A mixin is a class that provides method implementations for reuse by multiple related child classes. However, the inheritance is not implying an is-a relationship. A mixin doesn't define a new type.
Connecting to the Router
At this point the Users app has the basic data model and view logic in place, but it has not been connected to the URL routing system. Django-rest-framework has its own URL routing extension for handling ViewSets, where each ViewSet is registered with the router for a given URL prefix. This will be added to a new file in graphRestAPI/CoreAPI/coreGraphRestAPI/urls.py.
So create a urls.py file in the folder "graphRestAPI/CoreAPI/coreGraphRestAPI" and add the following code:
1 from rest_framework.routers import DefaultRouter
2 from .Users.views import UserViewSet
3
4
5 router = DefaultRouter()
6
7 router.register(r'users', UserViewSet)
8
Finally, this router needs to be included in the root URL configuration in /urls.py.
1 from django.contrib import admin
2 from django.urls import path
3 from django.conf.urls import include, url
4 from rest_framework.authtoken.views import obtain_auth_token
5 from coreGraphRestAPI.urls import router
6
7
8
9 urlpatterns = [
10 url(r'^admin/', admin.site.urls),
11 url(r'^api/token/', obtain_auth_token, name='api-token'),
12 url(r'^api/', include(router.urls)),
13
14 ]
Create Product application
Next we want to create the second application called Products, the first application was Users application.
We follow the same flow as we just did to create the user app:
Go to the folder "graphRestAPI/CoreAPI", then run the command below to create the app:
(venv) mykmyk@skynet:~/graphRestAPI/CoreAPI$ cd coreGraphRestAPI/ && python ../manage.py startapp Products
then to create Businesses app:
(venv) mykmyk@skynet:~/graphRestAPI/CoreAPI$ cd coreGraphRestAPI/ && python ../manage.py startapp Businesses
Then to create the Cart app
(venv) mykmyk@skynet:~/graphRestAPI/CoreAPI$ cd coreGraphRestAPI/ && python ../manage.py startapp Cart
Then to create the Wish app
(venv) mykmyk@skynet:~/graphRestAPI/CoreAPI$ cd coreGraphRestAPI/ && python ../manage.py startapp Wish
now if you cd into the folder "graphRestAPI/CoreAPI/coreGraphRestAPI", it looks like below:
(venv) mykmyk@skynet:~/graphRestAPI/CoreAPI/coreGraphRestAPI$ ll
total 40
drwxrwxr-x 8 mykmyk mykmyk 4096 Jun 20 12:03 ./
drwxrwxr-x 6 mykmyk mykmyk 4096 Jun 20 13:52 ../
-rw-rw-r-- 1 mykmyk mykmyk 164 Jun 19 09:55 apps.py
drwxrwxr-x 4 mykmyk mykmyk 4096 Jun 20 13:47 Businesses/
drwxrwxr-x 4 mykmyk mykmyk 4096 Jun 20 14:17 Cart/
-rw-rw-r-- 1 mykmyk mykmyk 0 Jun 19 09:55 __init__.py
drwxrwxr-x 4 mykmyk mykmyk 4096 Jun 20 12:39 Products/
drwxrwxr-x 2 mykmyk mykmyk 4096 Jun 20 12:07 __pycache__/
-rw-rw-r-- 1 mykmyk mykmyk 486 Jun 20 12:03 urls.py
drwxrwxr-x 4 mykmyk mykmyk 4096 Jun 20 13:52 Users/
drwxrwxr-x 4 mykmyk mykmyk 4096 Jun 20 14:17 Wish/
proceed into the folder "graphRestAPI/CoreAPI/coreGraphRestAPI/Products", and the open the "apps.py" just as we did in the Users app above, then add the following code:
apps.py
1 from django.apps import AppConfig
2
3
4 class ProductsConfig(AppConfig):
5 default_auto_field = 'django.db.models.BigAutoField'
6 name = 'coreGraphRestAPI.Products'
7 label = 'coreGraphRestAPI_Products'
Next, open the file "init.py" in the same folder and add the following code:
init.py
1 default_app_config = 'coreGraphRestAPI.Products.apps.ProductsConfig'
Repeat the two processes above for the three new apps that we have created i.e Cart , Wish, Businesses
then we head to our settings.py file in the folder : graphRestAPI/CoreAPI/CoreAPI
settings.py
33 INSTALLED_APPS = [
34 'django.contrib.admin',
....
40 'rest_framework',
41 'django_filters',
42 'coreGraphRestAPI',
43 'coreGraphRestAPI.Users',
44 'coreGraphRestAPI.Products',
45 'coreGraphRestAPI.Businesses',
46 'coreGraphRestAPI.Cart',
47 'coreGraphRestAPI.Wish',
48 ]
Notice above we have added the second application "coreGraphRestAPI.Products", the third Businesses , fourth Cart and finally Wish.
The next task is defining the models for this "Products" application, to do this we head to the folder: graphRestAPI/CoreAPI/coreGraphRestAPI/Products
open the file "models.py" and add the following code,
models.py
1 from django.db import models
2 from coreGraphRestAPI.Users.models import ImageUpload
3 from coreGraphRestAPI.Businesses.models import Business
4 from django.contrib.auth import get_user_model
5
6 User = get_user_model()
7
8 class Category(models.Model):
9 name = models.CharField(max_length=100, unique=True)
10 created_at = models.DateTimeField(auto_now_add=True)
11
12 def __str__(self):
13 return self.name
14
15 class ProductImage(models.Model):
16 image = models.ForeignKey(ImageUpload, related_name="product_image", on_delete=models.CASCADE)
17 is_cover = models.BooleanField(default=False)
18 created_at = models.DateTimeField(auto_now_add=True)
19 update_at = models.DateTimeField(auto_now=True)
20
21 def __str__(self):
22 return f"{self.product.business.name} - {self.product.name} - {self.image}"
23
24 class ProductComment(models.Model):
25 user = models.ForeignKey(User, related_name="user_comments_on_product", on_delete=models.CASCADE)
26 comment = models.TextField()
27 rate = models.IntegerField(default=3)
28 created_at = models.DateTimeField(auto_now_add=True)
29
30 class Product(models.Model):
31 category = models.ForeignKey(Category, related_name="product_categories", on_delete=models.CASCADE)
32 business = models.ForeignKey(Business, related_name="belongs_to_business", on_delete=models.CASCADE)
33 name = models.CharField(max_length=100)
34 price = models.FloatField()
35 total_available = models.PositiveIntegerField()
36 total_count = models.PositiveIntegerField()
37 description = models.TextField()
38 product_images = models.ForeignKey(ProductImage, related_name="product_images", on_delete=models.CASCADE)
39 product_comments = models.ForeignKey(ProductComment, related_name="product_comments", on_delete=models.CASCADE)
40 created_at = models.DateTimeField(auto_now_add=True)
41 update_at = models.DateTimeField(auto_now=True)
42
43 def __str__(self):
44 return f"{self.business.name} - {self.name}"
45
46 class Meta:
47 ordering = ("-created_at",)
After defining the model Product the next natural step is to define the serializer. Create a file "serializer.py" open it and add the following code:
serializer.py
1 from django.contrib.auth import get_user_model
2 from rest_framework import serializers
3 from rest_framework.reverse import reverse
4 from .models import Product, ProductImage, ProductComment, Category, ImageUpload
5 from drf_writable_nested import WritableNestedModelSerializer
6
7 User = get_user_model()
8
9 class CategorySerializer(serializers.ModelSerializer):
10 class Meta:
11 model = Category
12 fields = "__all__"
13
14 class ImageUploadSerializer(serializers.ModelSerializer):
15 class Meta:
16 model = ImageUpload
17 fields = "__all__"
18
19 class ProductImageSerializer(WritableNestedModelSerializer, serializers.ModelSerializer):
20 image = ImageUploadSerializer(read_only = False)
21 class Meta:
22 model = ProductImage
23 fields = "__all__"
24
25 class ProductCommentSerializer(serializers.ModelSerializer):
26 class Meta:
27 model = ProductComment
28 fields = "__all__"
29
30 class ProductSerializer(WritableNestedModelSerializer, serializers.ModelSerializer):
31 links = serializers.SerializerMethodField('get_links')
32 category = CategorySerializer(read_only = False)
33 product_images = ProductImageSerializer(read_only = False)
34 product_comments = ProductCommentSerializer(read_only = False)
35 class Meta:
36 model = Product
37 fields = ['id','category','business','name','price','total_available','total_count','description','product_images','product_comments','links']
38
39 def get_links(self, obj):
40 request = self.context['request']
41 links = {
42 'self': reverse('product-detail',
43 kwargs = {'pk': obj.pk}, request=request),
44 'business': None,
45 }
46
47 if obj.business:
48 links['business'] = reverse('business-detail',
49 kwargs = {'pk': obj.business}, request=request)
50 return links
After the serializing our data the next logical step is to piece together our Filters, create a file called "forms.py"
Open it and add the following code:
1 from django_filters.rest_framework import BooleanFilter, FilterSet, DateFilter
2 from django.contrib.auth import get_user_model
3 from .models import Product
4
5
6 class NullFilter(BooleanFilter):
7 """ Filter on a field set as null or not."""
8 def filter(self, qs, value):
9 if value is not None:
10 return qs.filter(**{'%s__isnull' % self.name: value})
11 return qs
12
13
14 class ProductFilter(FilterSet):
15 class Meta:
16 model = Product
17 fields = ('business','total_count','price','category')
The above file is uses to define our filters that will be used on our API data.
Next logical step is to create our viewsets, similar to the ones we defined when creating our Users.
open the "views.py" file and add the following code :
views.py
1 from django.contrib.auth import get_user_model
2 from rest_framework import authentication, permissions, viewsets, filters
3 from .serializer import ProductSerializer
4 from .models import Product
5 from .forms import ProductFilter
6 from django_filters.rest_framework import DjangoFilterBackend
7 from oauth2_provider.contrib.rest_framework import TokenHasReadWriteScope, TokenHasScope
8
9
10 class DefaultsMixin(object):
11 """Default settings for view authentication, permissions, filtering and pagination."""
12 authentication_classes = (
13 authentication.BasicAuthentication,
14 authentication.TokenAuthentication,
15 )
16 permission_classes = (
17 permissions.IsAuthenticated,
18 #TokenHasReadWriteScope,
19 )
20 paginate_by = 25
21 paginate_by_param = 'page_size'
22 max_paginate_by = 100
23 filter_backends = (
24 DjangoFilterBackend,
25 filters.SearchFilter,
26 filters.OrderingFilter
27 )
28
29
30 class ProductViewSet(DefaultsMixin, viewsets.ModelViewSet):
31 """API endpoint for listing Products."""
32
33 queryset = Product.objects.order_by('name',)
34 serializer_class = ProductSerializer
35 filter_class = ProductFilter
36 search_fields = ('name','price','business')
37 ordering_fields = ('price','name','total_available')
To finally add this view to our urls.py file in our root application "coreGraphRestAPI" folder , it will then look like this together with the other new applications:
CoreAPI/coreGraphRestAPI/urls.py
1 from rest_framework.routers import DefaultRouter
2 from .Users.views import UserViewSet
3 from .Products.views import ProductViewSet
4 from .Businesses.views import BusinessViewSet
5 from .Cart.views import CartViewSet
6 from .Wish.views import WishViewSet
7
8 router = DefaultRouter()
9
10 router.register(r'users', UserViewSet)
11 router.register(r'products', ProductViewSet)
12 router.register(r'businesses',BusinessViewSet)
13 router.register(r'carts', CartViewSet)
14 router.register(r'wishes', WishViewSet)
~
Now to avoid repeating myself, the code for the models, serializers, views and Filters for the Businesses, Cart, Wishes applications can be found at the following repository:
e-commerce repo
In this part we will be using dbsqlite, but we will migrate to postgresql in the next chapter, so dont worry about that.
After you finish creating the above applications you can run the following command to migrate your data
python manage.py makemigrations
python manege.py migrate
Then create a superuser to log into your browsable API
python manage.py createsuperuser
Then launch the application
python manage.py runserver
Next, before we proceed to the next part of this series there are things we have to get out of the way
- We need to move our data to postgresql or mysql (help me choose which one)
- We need to wire up token authentication for our API
- We need to write tests for our API application
- Containerze our app using docker Till then, Keep Safe and stay curious.
Top comments (2)
rest is architecture!!! you cannot serve architecture.
duly adviced,i will change the title to fit closely with the topic.