在前面的Blog例子中我們使用的是GraphQL, 雖然GraphQL的使用處於上升趨勢,但是Rest API還是使用的更廣泛一些. 所以還是決定回到傳統的rest api framework上來, Django rest framework的官網上給了一個很好用的QuickStart, 我參考Qu ...
在前面的Blog例子中我們使用的是GraphQL, 雖然GraphQL的使用處於上升趨勢,但是Rest API還是使用的更廣泛一些.
所以還是決定回到傳統的rest api framework上來, Django rest framework的官網上給了一個很好用的QuickStart, 我參考Quick Start將前面的Blog的例子用DRF(Django Rest Framework)重新構築一遍.
搭建Blog的rest api server
創建Blog Django project
安裝DRF(Django Rest Framework)
pip install djangorestframework
創建Blog Project
django-admin startproject drf_backend
cd drf_backend
django-admin startapp blog
cd ..
python manage.py migrate #創建預設的sqlite資料庫
python manage.py createsuperuser #創建super user
python manage.py runserver #啟動服務
上述操作後可以進入http://127.0.0.1:8000/admin 查看服務
創建Blog Models
參考前面Blog的代碼在models.py加入 Post, Tag, Profile的Model代碼
在admin.py中加入預設的管理頁面,
blog/models.py
from django.db import models from django.conf import settings # Create your models here. class Profile(models.Model): user = models.OneToOneField( settings.AUTH_USER_MODEL, on_delete=models.PROTECT, ) website = models.URLField(blank=True) bio = models.CharField(max_length=240, blank=True) def __str__(self): return self.user.get_username() class Tag(models.Model): name = models.CharField(max_length=50, unique=True) def __str__(self): return self.name class Post(models.Model): class Meta: ordering = ["-publish_date"] title = models.CharField(max_length=255, unique=True) subtitle = models.CharField(max_length=255, blank=True) slug = models.SlugField(max_length=255, unique=True) body = models.TextField() meta_description = models.CharField(max_length=150, blank=True) date_created = models.DateTimeField(auto_now_add=True) date_modified = models.DateTimeField(auto_now=True) publish_date = models.DateTimeField(blank=True, null=True) published = models.BooleanField(default=False) author = models.ForeignKey(Profile, on_delete=models.PROTECT) tags = models.ManyToManyField(Tag, blank=True)
blog/admin.py
from django.contrib import admin from blog.models import Profile, Post, Tag # Register your models here. @admin.register(Profile) class ProfileAdmin(admin.ModelAdmin): model = Profile @admin.register(Tag) class TagAdmin(admin.ModelAdmin): model = Tag @admin.register(Post) class PostAdmin(admin.ModelAdmin): model = Post list_display = ( "id", "title", "subtitle", "slug", "publish_date", "published", ) list_filter = ( "published", "publish_date", ) list_editable = ( "title", "subtitle", "slug", "publish_date", "published", ) search_fields = ( "title", "subtitle", "slug", "body", ) prepopulated_fields = { "slug": ( "title", "subtitle", ) } date_hierarchy = "publish_date" save_on_top = True
構造資料庫
python manage.py makemigrations
python manage.py migrate
數據Serializers
創建 blog/serializers.py, 這裡我們使用HyperlinkedModelSerializer 類, 也可以使用ModelSerializer. 這兩者的區別在於HyperLinkedModelSerializer將id直接變成url形式,這樣可以不用在代碼中再構造url.
from blog.models import Post,Tag,Profile from django.contrib.auth.models import User from rest_framework import serializers class PostSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = Post fields = ['url','title','subtitle','slug','body','meta_description','date_created','publish_date','published','author','tags'] class TagSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = Tag fields = ['url','name'] class ProfileSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = Profile fields = ['url','profile_pic','bio','user'] class UserSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = User fields = ['url','username','email','password']
Views
對應的rest api的請求,我們在blog/views.py中加入相關的處理
from django.shortcuts import render from django.contrib.auth.models import User from blog.models import Post,Tag,Profile from rest_framework import viewsets,permissions from blog.serializers import PostSerializer,TagSerializer,ProfileSerializer class PostViewSet(viewsets.ModelViewSet): queryset = Post.objects.all().order_by('publish_date') serializer_class = PostSerializer # permission_classes = [permissions.IsAuthenticated] class TagViewSet(viewsets.ModelViewSet): queryset = Tag.objects.all() serializer_class = TagSerializer class ProfileViewSet(viewsets.ModelViewSet): queryset = Profile.objects.all() serializer_class = ProfileSerializer
*註意我們這裡先不使用permission_classes,如果使用的話,在瀏覽器上就必須Login才能取得對應的數據
配置URL
在drf_backend/urls.py加入下列代碼
from django.contrib import admin from django.urls import path,include from rest_framework import routers from blog import views router =routers.DefaultRouter() router.register(r'posts', views.PostViewSet) router.register(r'tags',views.TagViewSet) router.register(r'profile', views.ProfileViewSet) urlpatterns = [ path('admin/', admin.site.urls), path('api/', include(router.urls)), path('api-auth/', include('rest_framework.urls', namespace='rest_framework')) ]
配置drf_backend/settings/py
INSTALLED_APPSINSTALLED_APPS = [ ... "corsheaders", 'rest_framework', 'blog', ]
Pagination (配置Rest API取得每頁的數據數)
REST_FRAMEWORK = { 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', 'PAGE_SIZE': 10 }
配置可以訪問的Frontend的地址和埠
CORS_ORIGIN_ALLOW_ALL = False CORS_ORIGIN_WHITELIST = ("http://localhost:8080",)
在瀏覽器中進入http://localhost:8000/api/ 可以看到Server提供的rest api的相關url,並可以進行操作了.