Django 学习记录 —— 接口设计初体验
本文基于以下环境展开:
Django: v3.0.4(djangorestframework v3.11.0)
Python: v3.7.4
前期准备
在展开正文内容之前,除了要准备基础的环境(python、django以及数据库)之外,还有项目框架的构建,这部分主要简要的写一下这点。
创建工程
django 命令: django-admin startproject project_name [directory]
django-admin startproject mysite
# or
django-admin startproject mysite . # 当前目录
生成的目录结构如下:
创建应用
工程复杂度比较高的时候,可以构建多个 app 的形式,也方便以后复用
django 命令:
python manage.py startapp app_name
or django-admin startapp app_name
python manage.py startapp news
# or
django-admin startapp news
以上两种方式生成的目录结构如下:
四大步实现接口
Django 有很成熟的写 Web APIs 框架 —— Django REST framework(DRF),官方总结了很多 DRF 的优点,就不再赘述,这里主要从自身使用角度来讲:
-
对新手来说,DRF 非常友好,model -> serializer -> view -> url 一条线的实现路径,只需要了解一些基础知识就可以实现 restful api;
-
对有基础的同学来说,DRF 认证、权限等都支持多种方式,可选择性大,可扩展性强,可以满足多种需求。
step1: model
根据数据库存储字段需求来设计
官方举例的模型很具代表性,在此借用官方例子
构建模型
# mysite/news/models.py
from django.db import models
class Reporter(models.Model):
full_name = models.CharField(max_length=70)
# 模型显示,默认为 id
# eg. <QuerySet [<Reporter: Smith>, <Reporter: Lily>]>
def __str__(self):
return self.full_name
# 可对要存储到数据库的数据进行处理
def save(self, *args, **kwargs):
super(Reporter, self).save(*args, **kwargs)
# 序列中增加一个字段,但不会写入数据库
@property
def keyword(self):
return self.full_name
class Article(models.Model):
pub_date = models.DateField()
headline = models.CharField(max_length=200)
content = models.TextField()
reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)
def __str__(self):
return self.headline
字段 : CharField、TextField 为数据库表字段类型,ForeignKey
外键使不同表之产生关联
字段选项 : max_length(字符串长度)是 CharField 必选项 ;
注:
- primary_key 未指定字段时,会自动生成一个整型自动递增的字段 id;
- 一个model(一张表)只能指定一个字段为 primary_key。
新建表
前提:
- 将 app 加入到配置文件的 INSTALLED_APPS;
- 配置目标数据库信息;
# settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework', # 使用 DRF,需要加上此项
'news', # 新创建应用
]
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', # 数据库类型
'NAME': 'mysite', # 数据库名称
'USER': 'root', # 数据库用户
'PASSWORD': '123456', # 数据库密码
'HOST': 'localhost', # 数据库所在主机
'PORT': '3306' # 主机端口
}
}
配置完成后,执行以下两步实现数据库迁移和表生成:
# 在项目路径下执行
python manage.py makemigrations news
python manage.py migrate news
注:若DATABASES配置了多个数据库, 执行 migrate 过程中要使用 --database
参数指明
数据库新生成的表如下(数据库中表名生成格式:appName_modelName
)
step2: serializer
与 model.py 字段对应,进行序列化
from rest_framework import serializers
from news.models import Reporter, Article
class ReporterSerializer(serializers.ModelSerializer):
class Meta:
model = Reporter
fields = ['id', 'full_name', 'keyword']
class ArticleSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = ['id', 'pub_date', 'headline', 'content', 'reporter']
step3: view
根据需求进行处理,实现 CURD - (create、update、retrieve、delete) 操作,DRF 都有对应的 viewset,非复杂性功能的实现可以直接框架提供的类 详见DRF官方文档
from rest_framework import generics
from news.models import Reporter, Article
from news.serializer import ReporterSerializer, ArticleSerializer
class ReporterViewSet(generics.ListCreateAPIView, generics.UpdateAPIView):
"""
该视图实现 Reporter model 的 CUR
"""
queryset = Reporter.objects.all()
serializer_class = ReporterSerializer
lookup_field = 'id'
def put(self, request, *args, **kwargs):
setattr(self, 'kwargs', request.data)
return self.update(request, *args, **kwargs)
class ArticleViewSet(generics.ListCreateAPIView):
"""
该视图实现 Article model 的 CR
"""
queryset = Article.objects.all()
serializer_class = ArticleSerializer
def get_serializer(self, *args, **kwargs):
""" if an array is passed, set serializer to many """
if isinstance(kwargs.get('data', {}), list):
kwargs['many'] = True
return super(ArticleViewSet, self).get_serializer(*args, **kwargs)
step4: url
请求 url
个人推荐在应用下接口比较多的情况下添加 urls.py 文件
- 在应用下的 urls.py 文件下添加接口;
- 在工程下的 urls.py 文件下将对应应用 urls.py 文件包括进去。
应用urls.py添加
# news/urls.py
from django.conf.urls import url
from news.views import ReporterViewSet, ArticleViewSet
urlpatterns = [
url('^reporter$', ReporterViewSet.as_view(), name='reporter'),
url('^article', ArticleViewSet.as_view(), name='article'),
]
工程urls.py添加
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('news/', include('news.urls'), name='news')
]
测试接口
完成以上四大步,最简单的接口就完成了,执行 python manage.py runserver
即可在本地进行调试,调用。
以测试新建 reporter 接口为例:
Request Headers: Content-Type: application/json
Response Body:
参考资料
因为项目需要接触了 Django,趁着周末记录一下也让自己再巩固一下,今天就先写到这了,之后再慢慢的把这段时间积累的东西整理出来,如有什么问题欢迎大家指正。
[1]DRF文档: https://www.django-rest-framework.org/
[2]Django文档: https://docs.djangoproject.com/en/3.0/