原文: www.valentinog.com/blog/tutori…html
翻译版实践教程: Django Rest 与 React(Django2.1 加 一点小测试 加一点译者的小额外功能)前端
最终构建了一个有后台管理 + 提供api服务 + Mysql数据库 + 在线api文档的Lead系统。python
一个实用(自认为)的介绍: 实用Django REST 与 React,特性! Django2.1!mysql
现在(可供开发选择的)web框并不匮乏。react
想要构建一个API服务? 这里列举出一些你能够立马想到说出名字的: Laravel, Rails, Node.js and Koa 2, Phoenix。webpack
可是摆在咱们面前的现实是: 客户想要一个尽量快的原型,这时我该如何作?git
我选择了一个web 框架,他:github
请信我! 当涉及到开发速度时,Django是很好的一个选择。 可是如何去建立一个简单的Django Rest API呢?如何去 组织构建 一个Django 项目 与 React呢?web
不要惧怕,咱们将在下面的教程中一块儿探索。sql
在下面的教程中你将会学到:
咱们将要作个啥嘞? 在这个项目里,咱们将会构建一个简单的 API 来列出并存储领导。
为了能继续跟进下面的教程,你应该拥有:
准备好了?让咱们一块儿出发吧!
首要的是来确认你拥有一个虚拟的Python环境,你能够在Python3中使用 pipenv,pyenv,或者venv模块。 (译者推荐使用pipenv)
pip install pipenv
mkdir django-drf-react-quickstart && cd django-drf-react-quickstart
pipenv shell
复制代码
而后安装依赖: 安装Django 和 Django REST framework 经过下面命令:
pipenv install django djangorestframework
复制代码
当安装结束,你能够经过下面命令建立一个新的Django 项目:
django-admin startproject drf_react .
复制代码
如今咱们能够开始构建咱们的第一个Django app 来 列出与存储leads
一个Django项目包含许多的 applications(应用)。理想状态下 每一个应用应该只作一件事。
Django applications(应用) 是模块化的,可重用的。 例如: 我建立了一个lead 应用用来建立和列出领导。
若是其余项目须要一个相同的app,我能够经过 package manager(INSTALLED_APPS) 来安装leads。嗯,没错,这就是所有。
我建议去阅读 How to write reusable apps,并观看 DjangoCon 2008: Reusable Apps 来学习关于app的最佳实践。
在Django中建立一个新的application,你应该运行:
django-admin startapp app_name
复制代码
为了在项目的文件夹中建立leads app:
cd django-drf-react-quickstart
复制代码
而后初始化咱们的app:
django-admin startapp leads
复制代码
注意: 我须要假设你位于 /YOUR_CODE_DIR/django-drf-react-quickstart/
来运行的上述命令! 以及这些命令是在pipenv shell启动的虚拟环境下执行的。
你将看到一个新的名字为leads的文件夹,在你的/YOUR_CODE_DIR/django-drf-react-quickstart/目录中。
就像上图这样。
如今让咱们告诉Django如何使用这个新的app
打开 ./drf_react/settings.py 并添加这个app在 INSTALLED_APPS中:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'leads', # 添加leads app
]
复制代码
到目前为止一切顺利。
# 起手式
git init
# 添加当前文件进入式
git add .
# commit文件式
git commit -m "初始化项目目录,添加leads app"
# 设置要上哪一个云端式
git remote add origin https://github.com/mtianyan/django-drf-react-quickstart.git
# 把网页新建拉下来式
git pull --rebase origin master
# push真的上云式
git push --set-upstream origin master
复制代码
首次使用才如上面N连环般麻烦。
# 第一全,文件全添加
git add .
# 第二全,commit信息要全
git commit -m "巴啦啦小魔仙balala"
# 第三全,全网速推上云
git push
复制代码
注意: 在进行下一步以前,请确保你仍然位于: /YOUR_CODE_DIR/django-drf-react-quickstart/
随着app的安装,咱们是时候来建立咱们的第一个model了,一个model 是一个对象用来表示你的表数据。几乎每一个web 框架都拥有models这个概念。 Django 也不例外。
一个Django模型能够拥有一个或多个字段: 每一个字段是你数据表中的一列,当进行下一步以前,让咱们为咱们的lead app 定义它的依赖。
首先咱们须要一个 Lead model
因为我收集了leads的信息,我认为一个Lead model 应该拥有如下字段:
(感受添加额外的字段也很轻松,例如咱们想再加个手机号)
请不要忘记一个 时间戳 字段! Django 不会默认的为你添加一个 created_at 列。
很好!
打开 ./leads/models.py
而后建立Lead model:
from django.db import models
class Lead(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField()
message = models.CharField(max_length=300)
created_at = models.DateTimeField(auto_now_add=True)
复制代码
这里有一个关于models的快速指南: 花时间看看 -> Django fields documentation
当计划一个model时,请尽力选择对于你的案例最适合的那些字段。
pipenv install mysqlclient
复制代码
新建一个mysql数据库
settings -> 修改成使用mysql数据库:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'drf_react',
'USER': 'root',
'PASSWORD': '密码',
'HOST':'127.0.0.1'
}
}
复制代码
settings -> 设置本地化
# 语言改成中文
LANGUAGE_CODE = 'zh-hans'
# 时区改成上海
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = True
# 数据库存储使用时间,True时间会被存为UTC的时间
USE_TZ = False
复制代码
在model定义就位以后,让咱们一块儿建立一个migration(迁移) 经过运行:
python manage.py makemigrations leads
复制代码
并最终 migrate 到数据库使用下面命令:
python manage.py migrate
复制代码
能够看到mysql中生成的表:
很是棒, 下一小节咱们将讨论序列化器和试图,可是首先咱们须要一点小小的测试。
此时此刻,你或许在惊叹"Valentino(做者名), 咋测试这个app"
不会让TDD(测试驱动开发) 教程来把你搞崩溃,我将给你一些小技巧(tips)
我见过大量的Django 教程里都是这样开始写的:
class SomeModelModelTest(TestCase):
def setUp(self):
SomeModel.objects.create(
name=fake.name(),
email=fake.email(),
phone=fake.phone_number(),
message=fake.text(),
source=fake.url()
)
def test_save_model(self):
saved_models = SomeModel.objects.count()
self.assertEqual(saved_models, 2)
复制代码
不要这样作,这对于测试Django model 或 Django ORM 都是没踩对点的(没啥用的)。
对于Django里的测试,这里有一个好的出发点:
总的来讲: 不要测试那些已经被测试过的!
那我该测些啥呢? 你是否在Django的model中添加了一个 custom method(自定义的方法)? 测它!
你是否有一个custom view(自定义的视图)呢? 测它! 可是我怎么知道要去测试啥呢?
经过安装工具 coverage 来帮本身一点忙
pipenv install coverage
复制代码
而后,每当你添加一些代码到你的应用时,运行coverage:
coverage run --source='.' manage.py test
复制代码
而后会产生报告:
coverage html
复制代码
用浏览器打开 /YOUR_CODE_DIR/django-drf-react-quickstart/htmlcov/index.html
,你将看到你须要测试啥。
若是你更想在命令行里看到测试报告,你能够运行:
coverage report
复制代码
等会! 你坚持看到了这? 我感动死了。
不要停! 牢牢抱住个人大腿, 下一节咱们将看看序列化器(serializers)!
breakpoint: 夺命三全 -> push
注意: 开始下面以前,请确保你仍然在/YOUR_CODE_DIR/django-drf-react-quickstart/
目录。
什么是序列化? 什么是Django REST 序列器?
序列化是转换一个对象到另外一种数据格式的一种动做。在对象转换完成后,咱们能够将它保存到文件,或者在互联网中发送它。
为何序列化如此必要呢?
思考一个Django model: 它是一个Python的嘞, 你该如何在浏览器中渲染一个Python的类到JSON 呢?
使用Django REST 序列器!
一个序列器 也能够反向工做: 它转换 JSON 到 对象
这种方式你能够:
简要归纳: DjangoREST 序列器 是操做模型到API的主宰。
建立一个新文件: ./leads/serializers.py. 这个LeadSerializer 接收咱们的Lead model 与一些字段
from rest_framework import serializers
from leads.models import Lead
class LeadSerializer(serializers.ModelSerializer):
class Meta:
model = Lead
fields = ('id', 'name', 'email', 'message')
复制代码
就像上面你能看到的代码里那样,咱们继承了ModelSerializer。
一个 ModelSerializer 在Django REST中就像一个 ModelForm
它很是适合于,任何你想接近 映射一个Model 到 一个Serializer 中时。
除了明确的定义须要映射的字段,你也能够映射model中的全部字段。
from rest_framework import serializers
from leads.models import Lead
class LeadSerializer(serializers.ModelSerializer):
class Meta:
model = Lead
fields = '__all__'
复制代码
保存并关闭文件,咱们离完成app更近了一步。
下面的章节里,咱们将看一下 views(视图) 和 urls。
注意: 开始下面以前,请确保你仍然在/YOUR_CODE_DIR/django-drf-react-quickstart/
目录。
若是你从其余框架转到Django,你可能感到惊奇的是: Django 没有控制器!
控制器用来封装处理 request 请求的逻辑并返回response。传统的MVC 体系 包含 Model(模型), View(视图), Controller(控制器)
这样的MVC框架有: Rails, Phoenix, Laravel。
Django 是一个 MVT framework,它有的三层是: Model(模型) - View (视图) - Template(模板)。其中View(视图) 关注着请求和响应的一整个生命周期。
Django中不少类型的views: function views 函数视图, class based views 基于类的视图, and generic views 通用视图.
虽然不少开发者相对于class based views(基于类的视图)更喜欢 function views (函数视图),但我是后者(基于类)的一个大粉丝
当我选择Django,由于个人核心价值要求是: 开发速度,DRY(dont repeat yourself),更少的代码。
当已经存在一组合理的默认值时,我认为继续手写Code是没有意义的。
这是个人经验法则:
仅当咱们想要自定义通用视图所花费的时间超过手动编写视图所花费的时间时,才使用函数视图。
与简单的Django同样,在Django REST 框架中,有不少方法能够编写视图:
在这个教程的范围内,我将使用 generic API view,目的是为了写更少的代码。
咱们的简单app应该有:
经过阅读generic API views documentation 咱们能够看到一件提供给咱们一个能够用于列出和建立models的view。
ListCreateAPIView 接收一个queryset 和 一个序列化类做为参数。
打开 ./leads/views.py
建立视图:
from leads.models import Lead
from leads.serializers import LeadSerializer
from rest_framework import generics
class LeadListCreate(generics.ListCreateAPIView):
queryset = Lead.objects.all()
serializer_class = LeadSerializer
复制代码
经过三行代码咱们建立了一个能够处理GET 和 POST请求的view。
如今还缺点啥呢? URL 映射! 换句话说,咱们须要映射URLs 到 视图
咋整? 敬请期待下一节
注意: 开始下面以前,请确保你仍然在/YOUR_CODE_DIR/django-drf-react-quickstart/
目录。
来自Rails, Phoenix, or Laravel 的朋友们,你可能又感到惊讶了,Django居然没有路由配置。
虽然DRF 提出了 resourceful router 资源化的路由,但最简单的映射URl到视图的方式仍是URL mapping。
咱们的目标是联通 LeadListCreate 到 api/lead/
换句话讲,咱们想要制做一个GET 和 POST请求到api/lead/ 来 列出和建立models。
在 ./drf_react/urls.py
配置URL mapping 包含app(leads)中的urls
from django.urls import path, include
urlpatterns = [
path('', include('leads.urls')),
]
复制代码
下一步是建立一个新的文件: ./leads/urls.py
:
from django.urls import path
from . import views
urlpatterns = [
path('api/lead/', views.LeadListCreate.as_view() ),
]
复制代码
最后: 咱们要让 rest_framework
注册进 INSTALLED_APPS。
打开 ./drf_react/settings.py
而后添加app 进入INSTALLED_APPS。
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'leads',
'rest_framework' # 加入 rest framework
]
复制代码
此时你应该能够经过健全性检查:
python manage.py runserver
复制代码
访问: http://127.0.0.1:8000/api/lead/ 你将会看到 browsable API 可浏览式api
此时你能够经过网页上内建的表单来建立一些数据
在下一节中,咱们将学习如何在Django 中喂养数据库(-v-)
注意: 开始下面以前,请确保你仍然在/YOUR_CODE_DIR/django-drf-react-quickstart/
目录。
你可使用 Django fixtures 来填充数据库。
当你想要给前端一些demo数据时,Fixtures时很是有用的。
建立一个新文件夹: ./leads/fixtures
而后建立一个新的文件: ./leads/fixtures/leads.json
内容为下面的JSON:
[
{
"model": "leads.lead",
"pk": 1,
"fields": {
"name": "mtianyan",
"email": "1147727180@qq.com",
"message": "I am a happy pythoner",
"created_at": "2019-01-07 00:00:00"
}
},
{
"model": "leads.lead",
"pk": 2,
"fields": {
"name": "Tom",
"email": "tomsomething@gmail.com",
"message": "I want to talk about a Python project",
"created_at": "2018-01-14 00:00:00"
}
}
]
复制代码
保存并关闭这个文件,而后使用下面命令加载fixture:
python manage.py loaddata leads
复制代码
这就是所有了,下面的部分,咱们将实现一个简单的React 前端!
pipenv install https://codeload.github.com/sshwsfc/xadmin/zip/django2
复制代码
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'leads', # 添加leads app
'rest_framework', # 添加rest framework
'xadmin', # 添加 xadmin
'crispy_forms', # 添加 xadmin
]
复制代码
from django.urls import path, include
import xadmin
urlpatterns = [
path('', include('leads.urls')),
path('xadmin/', xadmin.site.urls),
]
复制代码
添加了xadmin的import 和 xadmin path url mapping。
import xadmin
from xadmin import views
from .models import Lead
class BaseSetting(object):
"""xadmin的基础信息配置"""
enable_themes = True # 开启主题功能
use_bootswatch = True
class GlobalSettings(object):
"""xadmin通用信息配置"""
site_title = "Leads Xadmin"
site_footer = "mtianyan@qq.com"
# 注册设置信息到View
xadmin.site.register(views.BaseAdminView, BaseSetting)
xadmin.site.register(views.CommAdminView, GlobalSettings)
class LeadAdmin(object):
""" list_display: 后台展现哪些字段 search_fields: 后台可搜索哪些字段 list_filter: 后台过滤器可以使用哪些字段 """
list_display = ['name', 'email','message']
search_fields = ['name', 'email','message']
list_filter = ['name', 'email','message','created_at']
xadmin.site.register(Lead, LeadAdmin)
复制代码
python manage.py makemigrations
python manage.py migrate
复制代码
python manage.py createsuperuser
复制代码
运行
python manage.py runserver
复制代码
访问: http://127.0.0.1:8000/xadmin/
pipenv install coreapi
复制代码
from django.urls import path, include
import xadmin
from rest_framework.documentation import include_docs_urls # new
urlpatterns = [
path('', include('leads.urls')),
path('xadmin/', xadmin.site.urls),
path('api/docs/', include_docs_urls(title='Lead 在线API文档')), # new
]
复制代码
from django.db import models
# Create your models here.
class Lead(models.Model):
name = models.CharField(max_length=100,verbose_name="lead名字", help_text="lead名字")
email = models.EmailField(verbose_name="邮箱", help_text="邮箱")
message = models.CharField(max_length=300, verbose_name="信息", help_text="信息")
created_at = models.DateTimeField(auto_now_add=True,verbose_name="建立时间", help_text="建立时间")
复制代码
添加verbose_name用于xadmin,help_text用于drf
class LeadListCreate(generics.ListCreateAPIView):
""" get: 返回全部已存在的lead对象的列表 post: 建立一个新的lead实例 """
queryset = Lead.objects.all()
serializer_class = LeadSerializer
复制代码
python manage.py runserver
复制代码
访问: http://127.0.0.1:8000/api/docs/
大功告成: 咱们有了一个既有后台,又提供api,又有在线API文档的Lead服务啦。
敬请期待下次更新React篇! 敬请期待下次更新React篇! 敬请期待下次更新React篇!