简介
DRF 框架,全程: django-rest framework , rest是插件名字,django插件的名字叫rest,framework是框架的意思。DRF是以Django扩展应用的方式提供的,所以我们可以直接利用已有的Django环境而无需从新创建。(若没有Django环境,需要先创建环境安装Django)
安装django相关依赖
- 三方库
# 创建django骨架
django-admin startproject djangoy
- 启动django服务
python manage.py runserver
这是报错:You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run ‘python manage.py migrate’ to apply them.
执行提示命令。python manage.py migrate
,作用是在修改model后在不影响现有数据的前提下重建表结构
再次启动,发现无报错
settings.py文件解析
使用django-admin命令创建项目时会自动生成settings文件,我们可以更有应用的实际需要进行修改。
1、BASE_DIR 项目路径
BASE_DIR = Path(__file__).resolve().parent.parent
2、SECRET_KEY 加密串
这个变量本质上是一个加密盐,用于对各种需要加密的数据做Hash处理,例如密码重置、表单提交、session数据等,通常的做法是将它存储到系统环境变量中,通过os.getenv(key,default=None)的方式去获取
SECRET_KEY = 'django-insecure-&wzry=5&m94moji)iuu+hz%0yhw_m%e@xpdu&)w8pms)mp6un&'
3、DEBUG开关
DEBUG = True
4、ALLOWED_HOSTS
用于配置可以访问当前站点的域名,当DEBUG配置为False时,它是一个必填项,设置ALLOWED_HOSTS=[‘*’]允许所有的域名访问
ALLOWED_HOSTS = ['*']
5、INSTALLED_APPS
这个参数配置的是当前项目需要加载的App包路径列表。Django默认会把admin(管理后台)、auth(权限系统)、sessions(会话系统)加入进去,可以根据项目的需要对其增加或删除配置
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
6、MIDDLEWARE
当前项目中需要加载的中间件列表配置。与INSTALLED_APPS变量类似,Django也会默认加入一些中间件,例如用于处理会话的SessionMiddleware、用于处理授权验证的AuthenticationMiddleware等。同样,可以根据项目的需要对其增加或删除配置
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
7、ROOT_URLCONF
这个变量标记的是当前项目的根URL配置,是Django路由系统的入口点
8、TEMPLATES
这是一个列表变量,用于项目的模板配置,列表中的每一个元素都是一个字典,每个字典代表一个模板引擎
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
9、WSGI_APPLICATION
Django的内置服务器将使用的WSGI应用程序对象的完整Python路径
10、DATABASES
这是一个字典变量,标识项目的数据库配置
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
Django自带的sqlite3不适合做应用项目的数据库,所以,这里用MySQL替代项目的默认数据库
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', # 配置使用的数据库引擎
'NAME': 'django_test', # 数据库的名称
'USER': 'root', # 数据库用户名
'PASSWORD': 'root', # 数据库密码
'HOST': '127.0.0.1', # 数据库服务器地址,这里使用本地开发环境
'PORT': '3306', # 数据库服务器端口号,MySQL默认为3306
'OPTIONS': {
'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
'charset': 'utf8mb4'
}# 指定mysql语法
}
}
django引入mysql数据库的时候出现报错:
django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module.
Did you install mysqlclient?
修改mysqlclient为pymysql
# 在项目同级APP目录下__init__.py中添加
import pymysql
pymysql.install_as_MySQLdb() # 使用pymysql代替mysqldb连接数据库
# 命令行输入 迁移重置数据库结构
python3 manage.py makemigrations
python3 manage.py migrate
11、AUTH_PASSWORD_VALIDATORS
Django默认提供了一些支持插拔的密码验证器,且可以一次性配置多个。其主要目的是避免直接通过用户的弱密码配置申请
12、LANGUAGE_CODE和TIME_ZONE
这两个变量分别代表项目的语言环境和时区
# 修改中文和时区
LANGUAGE_CODE = 'zh-Hans'
TIME_ZONE = 'Asia/Shanghai'
13、USE_I18N和USE_L10N
Web服务搭建完成之后,可以面向不同国家的用户提供服务,这就要求应用支持国际化和本地化。这两个布尔类型的变量标识当前的项目是否需要开启国际化和本地化功能
14、USE_TZ
标识对于时区的处理,如果设置为True,不论TIME_ZONE设置的是什么,存储到数据库中的时间都是UTC时间,如果使用服务器本地时间,注释掉即可
15、STATIC_URL
用于标记当前项目中静态资源的存放位置
16、DEFAULT_AUTO_FIELD
主键的默认类型
17、REST_FRAMEWORK
DRF框架配置修改
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': [
"rest_framework.filters.SearchFilter",
"rest_framework.filters.OrderingFilter"
],
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication',
],
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', # 指定了url参数为page
'PAGE_SIZE': 20
}
初始化
INSTALLED_APPS中应用的数据库迁移
manage.py的migrate命令用于将应用的模型定义或修改同步到数据库中。migrate命令会检查INSTALLED_APPS里配置的应用列表,依次迭代为每个应用创建所需要的数据表
Django对于数据库的迁移命令:
python manage.py makemigrations
python manage.py migrate
对于将来应用的每一次表结构定义修改,都需要再次执行makemigrations命令,Django会重新生成一个新的数据库迁移文件,记录表结构之间的差异,命令规则是对上一个迁移文件的序列号加1,如0002_xxxx、0003_xxxx。之后,再次执行migrate命令让新的迁移文件生效,完成表结构定义的修改
创建管理员账号登陆django后台
manage.py提供了createsuperuser命令用于创建超级用户
python manage.py createsuperuser --username=admin --email=youremail@xx.com
当前命令执行后,需要重复输入两次密码(根据自己的需要设置),最终返回“Superuser created successfully”代表成功创建了超级用户
访问:http://127.0.0.1:8000/admin进入后台管理页面
创建应用
利用manage.py提供的startapp命令创建一个video应用的命令
python manage.py startapp video
# video是项目名称
DRF
- 安装依赖
- settings文件配置APP
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework', # DRF
'SkrAuto.apps.SkrautoConfig' # 应用
]
DRF框架封装风格
# DEMO
from rest_framework.views import APIView # 完成视图
# from rest_framework.generics import GenericAPIView # 二次封装依赖 等同于APIView
from rest_framework.response import Response # 响应数据
from rest_framework.request import Request # 请求数据
from rest_framework.serializers import Serializer # 序列化类
from rest_framework.settings import APISettings
from rest_framework.filters import SearchFilter # 查询过滤器
from rest_framework.pagination import PageNumberPagination # 分页器
from rest_framework.authentication import TokenAuthentication # auth认证
from rest_framework.permissions import IsAuthenticated # 权限认证
from rest_framework.throttling import SimpleRateThrottle # 频率
class Test(APIView):
def get(self, request, *args, **kwargs):
return Response('drf get ok')
# project urls
# django and DRF
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
# path('admin/', admin.site.urls),
path('', include("SkrAuto.urls")),
]
# 应用级视图 views
# django DEMO
class SkrAutoView(GenericAPIView):
def get(self, request):
queryset = UserInfo.objexts.all()
user_list = []
for user in queryset:
user_list.append({
"id": user.id,
"name": user.name,
"sex": user.sex,
"age": user.age,
"phone": user.phone
})
return JsonResponse(user_list, safe=False, json_dumps_params={"ensure_ascii": False})
# return Response({'code': 200, 'msg': '请求成功'})
def post(self, request):
json_bytes = request.body
json_str = json_bytes.decode()
user_dict = json.loads(json_str)
print(user_dict["name"])
# ORM
user = UserInfo.objects.creat(
name=user_dict.get('name'),
sex=user_dict.get('sex'),
age=user_dict.get('age'),
phone=user_dict.get('phone')
)
return JsonResponse({
"id": user.id,
"name": user.name,
"sex": user.sex,
"age": user.age,
"phone": user.phone
})
def put(self, request, pk):
try:
user = UserInfo.objects.get(pk=pk)
except UserInfo.DoesNotExist:
return Response({'code': 103, 'msg': '用户不存在'})
# 处理传参
json_bytes = request.body
json_str = json_bytes.decode()
user_dict = json.loads(json_str)
print(user_dict.get("name"))
user.name = user_dict.get("name")
user.save()
return JsonResponse({
"id": user.id,
"name": user.name,
"sex": user.sex,
"age": user.age,
"phone": user.phone
})
def delete(self, request, pk):
try:
user = UserInfo.objects.get(pk=pk)
except UserInfo.DoesNotExist:
return Response({'code': 103, 'msg': '用户不存在'})
user.delete()
return Response({'code': 200, 'msg': 'ok'})
# django demo2
# class SkrPostView(GenericAPIView):
#
# def __init__(self):
# super(SkrPostView, self).__init__()
# self.data = {}
#
# def post(self, request):
# c = request.data.get('a') + request.data.get('b')
# self.data['a'] = request.data.get('a')
# self.data['b'] = request.data.get('b')
# self.data['c'] = c
# return Response({'code': 200, 'data': self.data, 'msg': 'ok'})
#
#
# class SkrPutView(GenericAPIView):
#
# def __init__(self):
# super(SkrPutView, self).__init__()
# self.data = {}
#
# def put(self, request, pk):
# # c = request.data.get('a') + request.data.get('b')
# # self.data['a'] = request.data.get('a')
# # self.data['b'] = request.data.get('b')
# # self.data['c'] = c
# try:
# user = UserInfo.objects.get(pk=pk)
# except UserInfo.DoesNotExist:
# return Response({'code': 103, 'msg': '用户不存在'})
# # 参数解析
# json_bytes = request.body
# json_str = json_bytes.decode()
# user_dict = json.loads(json_str)
#
# return Response({'code': 200, 'data': self.data, 'msg': 'ok'})
# DRF DEMO
class SkrViewSet(ModelViewSet):
queryset = UserInfo.objects.all()
serializer_class = SkrSerializers
# 应用级 urls
# django demo
urlpatterns = [
# demo
# path('get/demo/', SkrAutoView.as_view()),
# path('post/demo/', SkrPostView.as_view()),
# re_path(r'get/demo/', views.SkrAutoView.as_view()),
# path('put/demo/'), SkrPutView.as_view(),
# re_path(r'^skr/$', views.SkrAutoView.as_view()), demo
# re_path(r'^skr/(?P<pk>\d+)/$', views.SkrAutoView.as_view()), demo
]
# DRF DEMO
from rest_framework.routers import DefaultRouter, SimpleRouter
from SkrAuto import views
urlpatterns = [ ]
# router = DefaultRouter()
router = SimpleRouter()
router.register(r"skr", views.SkrViewSet)
urlpatterns += router.urls
# models
# ORM模型
# serializers 序列化器 需要新建 serializers.py 文件
from rest_framework import serializers
from django.db import models
from SkrAuto.models import UserInfo
class SkrSerializers(serializers.ModelSerializer):
class Meta:
model = UserInfo
fields = "__all__"
DRF请求生命周期
1、请求走的是APIView的as_view函数
2、 在APIView的as_view调用父类(django原生)的as_view,还禁用了 csrf 认证
3、 在父类的as_view中dispatch方法请求走的又是APIView的dispatch
4、完成任务方法交给视图类的请求函数处理,得到请求的响应结果,返回给前台
服务启动
# debug
python manage.py runserver
# linux 后台挂载
nohup python manage.py runserver
请求示例