使用Django Rest framework搭建Blog

发布时间 2023-04-19 16:39:46作者: magicduan

在前面的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_APPS
INSTALLED_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,并可以进行操作了.