目录
[1.1 pycharm创建项目](#1.1 pycharm创建项目)
[1.2 修改配置settings.py](#1.2 修改配置settings.py)
[1.3 新增 static与staticfiles文件夹](#1.3 新增 static与staticfiles文件夹)
[1.4 生成数据表](#1.4 生成数据表)
[1.5 创建超级用户](#1.5 创建超级用户)
[1.6 启动项目](#1.6 启动项目)
[2.1 安装](#2.1 安装)
[2.2 配置settings](#2.2 配置settings)
[2.3 重新执行生成数据库脚本](#2.3 重新执行生成数据库脚本)
[4.1 修改apps.py](#4.1 修改apps.py)
[4.2 创建models.py](#4.2 创建models.py)
[4.3 修改admin.py](#4.3 修改admin.py)
[4.4 生成数据表](#4.4 生成数据表)
[4.5 添加库表数据](#4.5 添加库表数据)
[五、使用ModelSerializer序列化 模型类](#五、使用ModelSerializer序列化 模型类)
[5.1 创建serializers文件](#5.1 创建serializers文件)
[5.2 序列化models表中的Course](#5.2 序列化models表中的Course)
[5.3 带URL的HyperlinkedModelSerializer(非必须)](#5.3 带URL的HyperlinkedModelSerializer(非必须))
[六、DRF视图开发RESful API接口](#六、DRF视图开发RESful API接口)
[6.1 使用django原生编写API接口(可跳过,不推荐)](#6.1 使用django原生编写API接口(可跳过,不推荐))
[6.1.1 django函数式编程Function Based View(不推荐)](#6.1.1 django函数式编程Function Based View(不推荐))
[6.1.2 django原生类视图Class Based View(不推荐)](#6.1.2 django原生类视图Class Based View(不推荐))
[6.2 DRF函数式编程Function Based View](#6.2 DRF函数式编程Function Based View)
[6.2.1 编码代码-----》(查询列表+新增)](#6.2.1 编码代码-----》(查询列表+新增))
[6.2.2 添加路由](#6.2.2 添加路由)
[6.2.3 访问验证](#6.2.3 访问验证)
[6.2.4 测试新增](#6.2.4 测试新增)
[6.2.5 查询列表](#6.2.5 查询列表)
[6.2.6 编写代码 ----》(修改、删除,查询单个)](#6.2.6 编写代码 ----》(修改、删除,查询单个))
[6.2.7 添加路由](#6.2.7 添加路由)
[6.2.8 查询单个](#6.2.8 查询单个)
[6.2.9 修改单个](#6.2.9 修改单个)
[6.2.10 删除单个](#6.2.10 删除单个)
[6.3 DRF类视图Class Based View](#6.3 DRF类视图Class Based View)
[6.3.1 代码](#6.3.1 代码)
[6.3.2 更新url](#6.3.2 更新url)
[6.3.3 测试](#6.3.3 测试)
[6.4 通用类视图Generic Classed Based View](#6.4 通用类视图Generic Classed Based View)
[6.4.1 代码](#6.4.1 代码)
[6.3.2 添加路由](#6.3.2 添加路由)
[6.3.3 测试](#6.3.3 测试)
[6.5 DRF的视图集viewsets](#6.5 DRF的视图集viewsets)
[6.5.1 代码](#6.5.1 代码)
[6.5.2 路由urls---》 这个写法与之前路由不一样](#6.5.2 路由urls---》 这个写法与之前路由不一样)
[6.5.3 测试](#6.5.3 测试)
[7.1 BasicAuthenrication用户名密码认证](#7.1 BasicAuthenrication用户名密码认证)
[7.2 SessionAuthenrication认证](#7.2 SessionAuthenrication认证)
[7.3 TokenAuthenrication认证](#7.3 TokenAuthenrication认证)
[7.3.1 使用django manage.py 生成token(测试使用)](#7.3.1 使用django manage.py 生成token(测试使用))
[7.3.2 通过django的信号机制生成token](#7.3.2 通过django的信号机制生成token)
[7.3.2.1 在视图写函数实现](#7.3.2.1 在视图写函数实现)
[7.3.2.2 项目urls配置路由](#7.3.2.2 项目urls配置路由)
[7.3.2.3 后台创建一个用户](#7.3.2.3 后台创建一个用户)
[7.3.2.4 调用接口生成token](#7.3.2.4 调用接口生成token)
[7.3.2.5 其他接口使用token](#7.3.2.5 其他接口使用token)
[7.3.2.6 每个方法设置不同认证](#7.3.2.6 每个方法设置不同认证)
[8.1 常用的权限类](#8.1 常用的权限类)
[8.2 设置权限策略](#8.2 设置权限策略)
[8.3 如何自定义对象级别权限](#8.3 如何自定义对象级别权限)
[8.3.1 新建permissons.py文件](#8.3.1 新建permissons.py文件)
[8.3.2 导入到视图views.py应用](#8.3.2 导入到视图views.py应用)
[8.3.3 测试](#8.3.3 测试)
[9.1 如何生成接口文档](#9.1 如何生成接口文档)
[9.1.1 安装库](#9.1.1 安装库)
[9.1.2 settings配置](#9.1.2 settings配置)
[9.1.3 urls配置](#9.1.3 urls配置)
[9.1.4 访问](#9.1.4 访问)
[9.2 接口文档的使用方法](#9.2 接口文档的使用方法)
[9.2.1 修改settings](#9.2.1 修改settings)
[9.2.2 修改urls](#9.2.2 修改urls)
[9.2.3 访问](#9.2.3 访问)
[9.2.4 使用](#9.2.4 使用)
前言:django RESTFramework基础学习整理
一、搭建项目开发环境
1.1 pycharm创建项目
1.2 修改配置settings.py
ALLOWED_HOSTS = ['*']
.
.
.
# LANGUAGE_CODE = 'en-us'
# TIME_ZONE = 'UTC'
# USE_TZ = True
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
USE_TZ = False
USE_I18N = True
.
.
.
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'staticfiles')]
1.3 新增 static与staticfiles文件夹
1.4 生成数据表
这里使用默认的数据库
python manage.py makemigrations
python manage.py migrate
1.5 创建超级用户
# 创建超级用户
python manage.py createsuperuser
1、输入邮箱,随便
2、输入密码
3、再次数据密码
4、 如果密码太简单会提示, 忽略就点Y
1.6 启动项目
python manage.py runserver
http://127.0.0.1:8000/admin/
输入刚才设置的用户 root 123456,能登录成功就说明用户创建成功
二、安装REST_Framework
2.1 安装
pip install djangorestframework
pip install coreapi # 第九章使用
pip install pyyaml # 第九章使用
2.2 配置settings
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'studyApp.apps.StudyappConfig',
'rest_framework', #rest-framework API
'rest_framework.authtoken' # DRF 自带的token认证
]
.
.
.
#DRF的全局配置
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 10,
'DATETIME_FORMAT': '%Y-%m-%d %H:%M:%S',
'DEFAULT_RENDER_CLASSES': [# 渲染response ,可以不写
'rest_framework.renderers.JSONRenderer',
'rest_framework.renders.BrowsableAPIRender',
],
'DEFAULT_PARSER_CLASSES': [ # 解析request.data
'rest_framework.parsers.JSONParser',
'rest_framework.parsers.FormParser',
'rest_framework.parsers.MultiPartParser',
],
'DEFAULT_PERMISSION_CLASSES': [ # 权限
'rest_framework.permissions.IsAuthenticatedOrReadOnly',
],
'DERAULT_AUTHENTICATION_CLASSES': [ # 认证
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication',
]
}
2.3 重新执行生成数据库脚本
python manage.py makemigrations
python manage.py migrate
三、修改路由
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
path('admin/', admin.site.urls),
path('studyApp/',include('studyApp.urls')),
path('api-auth/', include('rest_framework.urls')), # DRF登录退出接口,可点击进去看看
]
登录
http://127.0.0.1:8000/api-auth/login/
四、studyApp应用开发
4.1 修改apps.py
from django.apps import AppConfig
class StudyappConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'studyApp'
verbose_name = '学习APP'
4.2 创建models.py
from django.db import models
from django.conf import settings
class Course(models.Model):
name = models.CharField(max_length=255, unique=True, help_text='课程名称', verbose_name='课程名称')
introduction = models.TextField(help_text='课程介绍', verbose_name='课程介绍')
teacher = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE,
help_text='课程讲师', verbose_name='课程讲师')
price = models.DecimalField(max_digits=6,decimal_places=2, help_text='价格', verbose_name='价格')
created_at = models.DateTimeField(auto_now_add=True, help_text='创建时间', verbose_name='创建时间')
updated_at = models.DateTimeField(auto_now=True, help_text='更新时间', verbose_name='更新时间')
class Meta:
verbose_name = '课程信息',
verbose_name_plural = verbose_name
ordering = ['price',]
def __str__(self):
return self.name
4.3 修改admin.py
将model.py创建的Course字段添加到后台系统,方面后期添加数据
from django.contrib import admin
from .models import Course
# Register your models here.
@admin.register(Course)
class CourseAdmin(admin.ModelAdmin):
list_display = ('name', 'introduction','teacher','price')
serch_fields = list_display
list_filter = list_display
4.4 生成数据表
python manage.py makemigrations
python manage.py migrate
4.5 添加库表数据
五、使用ModelSerializer序列化 模型类
5.1 创建serializers文件
5.2 序列化models表中的Course
注意:teacher是外键,复用了django的用户表,外键序列化还可以使用遍历深度
在Meta当中设置depth=1 , 数字越大,深度越大,
# -*- coding: utf-8 -*-
# @Time : 2024/11/1 9:30
# @Author : super
# @File : serializers.py
# @Software: PyCharm
# @Describe:
from rest_framework import serializers
from .models import Course
from django.contrib.auth.models import User # 导入用户模型
"""
用户序列化器
"""
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = '__all__'
class CourseSerializer(serializers.ModelSerializer):
teacher = serializers.ReadOnlyField(source='teacher.username') # 外键显示名称
class Meta:
model = Course
fields = '__all__'
# fields = ('id', 'name', 'teacher', 'price', 'introduction', 'created_at', 'updated_at')
5.3 带URL的HyperlinkedModelSerializer(非必须)
这里是讲解,后面例子没有使用到,可注解掉
# -*- coding: utf-8 -*-
# @Time : 2024/11/1 9:30
# @Author : super
# @File : serializers.py
# @Software: PyCharm
# @Describe:
from rest_framework import serializers
from .models import Course
from django.contrib.auth.models import User # 导入用户模型
"""
用户序列化器
"""
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = '__all__'
class CourseSerializer(serializers.HyperlinkedModelSerializer):
teacher = serializers.ReadOnlyField(source='teacher.username') # 外键显示名称
class Meta:
model = Course
# url 是默认值,可在settings.py设置URL_FIELD_NAME使全局生效
fields = ('id', 'url', 'teacher', 'price', 'introduction', 'created_at', 'updated_at')
如果要更url,这样设置,(不建议)
六、DRF视图开发RESful API接口
6.1 使用django原生编写API接口(可跳过,不推荐)
6.1.1 django函数式编程Function Based View(不推荐)
使用django原生的函数式编写api接口
from django.shortcuts import render
import json
from django.http import JsonResponse, HttpResponse
from django.views.decorators.csrf import csrf_exempt # 用于免除csrf验证
# Create your views here.
coures_dict = {
"name": "python",
"introduction": "python基础入门",
"price": 100
}
@csrf_exempt
def course_list(request):
'''
django原生的fbv式编写API接口
:param request:
:return:
'''
if request.method == 'Get':
return JsonResponse(coures_dict)
# return HttpResponse(json.dumps(coures_dict), content_type='application/json') # 这个与上面JsonResponse作用一样
if request.method == 'POST':
course_data = json.loads(request.body.decode('utf-8'))
# return JsonResponse(course_data, safe=False) # 这个与下面的JsonResponse作用一样
return HttpResponse(json.dumps(course_data), content_type='application/json')
6.1.2 django原生类视图Class Based View(不推荐)
使用django原生的类编写api接口
import json
from django.http import JsonResponse, HttpResponse
from django.views.decorators.csrf import csrf_exempt # 用于免除csrf验证
from django.utils.decorators import method_decorator # 用于方法免除csrf验证
from django.views import View
@method_decorator(csrf_exempt, name='dispatch')
class CourseView(View):
'''
django原生的cbv式编写API接口
'''
def get(self, request):
return JsonResponse(coures_dict)
def post(self, request):
course_data = json.loads(request.body.decode('utf-8'))
return JsonResponse(course_data, safe=False)
6.2 DRF函数式编程Function Based View
6.2.1 编码代码-----》(查询列表+新增)
from django.shortcuts import render
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
from .models import Course
from .serializers import CourseSerializer
"""
一、 函数式编程 FBV
"""
@api_view(['GET', 'POST'])
def coures_list(request):
'''
获取课程列表或新增一个课程
:param request:
:return:
'''
if request.method == 'GET':
courses = CourseSerializer(instance=Course.objects.all(), many=True)
return Response(data=courses.data,status=status.HTTP_200_OK)
elif request.method == 'POST':
serializer = CourseSerializer(data=request.data) # partial=True 只验证部分字段,适用于非必填字段
if serializer.is_valid():
serializer.save(teacher=request.user) # teacher 字段为外键,获取登录用户id,因为复用了django的用户模型,有认证功能
return Response(data=serializer.data, status=status.HTTP_201_CREATED)
return Response(data=serializer.errors, status=status.HTTP_400_BAD_REQUEST)
6.2.2 添加路由
在应用新增urls文件,输入内容
# -*- coding: utf-8 -*-
# @Time : 2024/11/1 10:27
# @Author : super
# @File : urls.py
# @Software: PyCharm
# @Describe:
from django.urls import path,include
from studyApp import views
urlpatterns = [
path('fbv/list/', views.coures_list, name='fbv-list'), # 函数视图FBV
]
6.2.3 访问验证
http://127.0.0.1:8000/studyApp/fbv/list/
因为这里设置了全局的身份认证,需要登录
6.2.4 测试新增
json
{
"name": "python",
"introduction": "python基础入门",
"price": 100
}
6.2.5 查询列表
6.2.6 编写代码 ----》(修改、删除,查询单个)
from django.shortcuts import render
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
from .models import Course
from .serializers import CourseSerializer
"""
一、 函数式编程 FBV
"""
@api_view(['GET', 'POST'])
def coures_list(request):
'''
获取课程列表或新增一个课程
:param request:
:return:
'''
if request.method == 'GET':
courses = CourseSerializer(instance=Course.objects.all(), many=True)
return Response(data=courses.data,status=status.HTTP_200_OK)
elif request.method == 'POST':
serializer = CourseSerializer(data=request.data) # partial=True 只验证部分字段,适用于非必填字段
if serializer.is_valid():
serializer.save(teacher=request.user) # teacher 字段为外键,获取登录用户id,因为复用了django的用户模型,有认证功能
return Response(data=serializer.data, status=status.HTTP_201_CREATED)
return Response(data=serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@api_view(['GET', 'PUT', 'DELETE'])
def course_detail(request, pk):
'''
获取单个课程详情,更新或删除一个课程
:param request:
:param pk:
:return:
'''''
try:
course = Course.objects.get(pk=pk)
except Course.DoesNotExist:
return Response({'message': 'Course not found'}, status=status.HTTP_404_NOT_FOUND)
if request.method == 'GET':
serializer = CourseSerializer(course)
return Response(data=serializer.data, status=status.HTTP_200_OK)
elif request.method == 'PUT':
serializer = CourseSerializer(instance=course, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
elif request.method == 'DELETE':
course.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
else:
return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED)
6.2.7 添加路由
from django.urls import path,include
from studyApp import views
urlpatterns = [
path('fbv/list/', views.coures_list, name='fbv-list'), # 函数视图FBV
path('fbv/detail/<int:pk>/', views.course_detail, name='fbv-detail'),
]
6.2.8 查询单个
http://127.0.0.1:8000/studyApp/fbv/detail/2/
6.2.9 修改单个
请求体
{
"name": "菠菜的野蛮生长",
"introduction": "编码人生",
"price": 100
}
6.2.10 删除单个
知识点:使用postman测试的话注意这个地方
另外一种设置方式:
继承
6.3 DRF类视图Class Based View
6.3.1 代码
from django.shortcuts import render
from rest_framework.decorators import api_view # fbv
from rest_framework.views import APIView #cbv
from rest_framework.response import Response
from rest_framework import status
from .models import Course
from .serializers import CourseSerializer
"""
一、 函数式编程 FBV
"""
@api_view(['GET', 'POST'])
def coures_list(request):
'''
获取课程列表或新增一个课程
:param request:
:return:
'''
if request.method == 'GET':
courses = CourseSerializer(instance=Course.objects.all(), many=True)
return Response(data=courses.data,status=status.HTTP_200_OK)
elif request.method == 'POST':
serializer = CourseSerializer(data=request.data) # partial=True 只验证部分字段,适用于非必填字段
if serializer.is_valid():
serializer.save(teacher=request.user) # teacher 字段为外键,获取登录用户id,因为复用了django的用户模型,有认证功能
return Response(data=serializer.data, status=status.HTTP_201_CREATED)
return Response(data=serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@api_view(['GET', 'PUT', 'DELETE'])
def course_detail(request, pk):
'''
获取单个课程详情,更新或删除一个课程
:param request:
:param pk:
:return:
'''''
try:
course = Course.objects.get(pk=pk)
except Course.DoesNotExist:
return Response({'message': 'Course not found'}, status=status.HTTP_404_NOT_FOUND)
if request.method == 'GET':
serializer = CourseSerializer(course)
return Response(data=serializer.data, status=status.HTTP_200_OK)
elif request.method == 'PUT':
serializer = CourseSerializer(instance=course, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
elif request.method == 'DELETE':
course.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
else:
return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED)
"""
二、 函数式编程 CBV
"""
class CourseList(APIView):
"""
获取课程列表或新增一个课程
"""
def get(self, request):
queryset = Course.objects.all()
serializer = CourseSerializer(instance=queryset, many=True)
return Response(data=serializer.data, status=status.HTTP_200_OK)
def post(self, request):
serializer = CourseSerializer(data=request.data)
if serializer.is_valid():
serializer.save(teacher=self.request.user)
return Response(data=serializer.data, status=status.HTTP_201_CREATED)
return Response(data=serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class CourseDetail(APIView):
"""
获取单个课程详情,更新或删除一个课程
"""
@staticmethod
def get_object(pk):
'''
获取课程对象
:param self:
:param pk:
:return:
'''
try:
return Course.objects.get(pk=pk)
except Course.DoesNotExist:
return
def get(self, request, pk):
obj = self.get_object(pk=pk)
if obj is None:
return Response({'message': 'Course not found'}, status=status.HTTP_404_NOT_FOUND)
serializer = CourseSerializer(obj)
return Response(data=serializer.data, status=status.HTTP_200_OK)
def put(self, request, pk):
'''
更新课程
:param request:
:param pk:
:return:
'''
obj = self.get_object(pk=pk)
if obj is None:
return Response({'message': 'Course not found'}, status=status.HTTP_404_NOT_FOUND)
serializer = CourseSerializer(instance=obj, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, pk):
'''
删除课程
:param request:
:param pk:
:return:
'''
obj = self.get_object(pk=pk)
if obj is None:
return Response({'message': 'Course not found'}, status=status.HTTP_404_NOT_FOUND)
obj.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
6.3.2 更新url
# -*- coding: utf-8 -*-
# @Time : 2024/11/1 10:27
# @Author : super
# @File : urls.py
# @Software: PyCharm
# @Describe:
from django.urls import path,include
from studyApp import views
urlpatterns = [
path('fbv/list/', views.coures_list, name='fbv-list'), # 函数视图FBV
path('fbv/detail/<int:pk>/', views.course_detail, name='fbv-detail'), # 函数视图FBV
path('cbv/list/', views.CourseList.as_view(), name='cbv-list'), # 类视图CBV
path('cbv/detail/<int:pk>/', views.CourseDetail.as_view(), name='cbv-detail'), # 类视图CBV
]
6.3.3 测试
查询全部
新增
修改
删除
6.4 通用类视图Generic Classed Based View
6.4.1 代码
如果没有那个teacher ,那个方法重写可以不需要
from django.shortcuts import render
from rest_framework.decorators import api_view # fbv
from rest_framework.views import APIView #cbv
from rest_framework import generics # gcb通用视图类
from rest_framework.response import Response
from rest_framework import status
from .models import Course
from .serializers import CourseSerializer
"""
一、 函数式编程 FBV
"""
@api_view(['GET', 'POST'])
def coures_list(request):
'''
获取课程列表或新增一个课程
:param request:
:return:
'''
if request.method == 'GET':
courses = CourseSerializer(instance=Course.objects.all(), many=True)
return Response(data=courses.data,status=status.HTTP_200_OK)
elif request.method == 'POST':
serializer = CourseSerializer(data=request.data) # partial=True 只验证部分字段,适用于非必填字段
if serializer.is_valid():
serializer.save(teacher=request.user) # teacher 字段为外键,获取登录用户id,因为复用了django的用户模型,有认证功能
return Response(data=serializer.data, status=status.HTTP_201_CREATED)
return Response(data=serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@api_view(['GET', 'PUT', 'DELETE'])
def course_detail(request, pk):
'''
获取单个课程详情,更新或删除一个课程
:param request:
:param pk:
:return:
'''''
try:
course = Course.objects.get(pk=pk)
except Course.DoesNotExist:
return Response({'message': 'Course not found'}, status=status.HTTP_404_NOT_FOUND)
if request.method == 'GET':
serializer = CourseSerializer(course)
return Response(data=serializer.data, status=status.HTTP_200_OK)
elif request.method == 'PUT':
serializer = CourseSerializer(instance=course, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
elif request.method == 'DELETE':
course.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
else:
return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED)
"""
二、 函数式编程 CBV
"""
class CourseList(APIView):
"""
获取课程列表或新增一个课程
"""
def get(self, request):
queryset = Course.objects.all()
serializer = CourseSerializer(instance=queryset, many=True)
return Response(data=serializer.data, status=status.HTTP_200_OK)
def post(self, request):
serializer = CourseSerializer(data=request.data)
if serializer.is_valid():
serializer.save(teacher=self.request.user)
return Response(data=serializer.data, status=status.HTTP_201_CREATED)
return Response(data=serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class CourseDetail(APIView):
"""
获取单个课程详情,更新或删除一个课程
"""
@staticmethod
def get_object(pk):
'''
获取课程对象
:param self:
:param pk:
:return:
'''
try:
return Course.objects.get(pk=pk)
except Course.DoesNotExist:
return
def get(self, request, pk):
obj = self.get_object(pk=pk)
if obj is None:
return Response({'message': 'Course not found'}, status=status.HTTP_404_NOT_FOUND)
serializer = CourseSerializer(obj)
return Response(data=serializer.data, status=status.HTTP_200_OK)
def put(self, request, pk):
'''
更新课程
:param request:
:param pk:
:return:
'''
obj = self.get_object(pk=pk)
if obj is None:
return Response({'message': 'Course not found'}, status=status.HTTP_404_NOT_FOUND)
serializer = CourseSerializer(instance=obj, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, pk):
'''
删除课程
:param request:
:param pk:
:return:
'''
obj = self.get_object(pk=pk)
if obj is None:
return Response({'message': 'Course not found'}, status=status.HTTP_404_NOT_FOUND)
obj.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
'''
三、 通用视图类
'''
class CourseGenericAPIView(generics.ListCreateAPIView):
'''
获取课程列表或新增一个课程
'''
queryset = Course.objects.all()
serializer_class = CourseSerializer
def perform_create(self, serializer): # 重写perform_create方法,在保存之前添加teacher字段
serializer.save(teacher=self.request.user)
class CourseGenericDetailAPIView(generics.RetrieveUpdateDestroyAPIView):
'''
获取单个课程详情,更新或删除一个课程
'''
queryset = Course.objects.all()
serializer_class = CourseSerializer
6.3.2 添加路由
# -*- coding: utf-8 -*-
# @Time : 2024/11/1 10:27
# @Author : super
# @File : urls.py
# @Software: PyCharm
# @Describe:
from django.urls import path,include
from studyApp import views
urlpatterns = [
path('fbv/list/', views.coures_list, name='fbv-list'), # 函数视图FBV
path('fbv/detail/<int:pk>/', views.course_detail, name='fbv-detail'), # 函数视图FBV
path('cbv/list/', views.CourseList.as_view(), name='cbv-list'), # 类视图CBV
path('cbv/detail/<int:pk>/', views.CourseDetail.as_view(), name='cbv-detail'), # 类视图CBV
path('gcbv/list/', views.CourseGenericAPIView.as_view(),name='gcbv-list'), # 通用视图类gcbv
path('gcbv/detail/<int:pk>/', views.CourseGenericDetailAPIView.as_view(), name='gcbv-detail'),# 通用视图类gcbv
]
6.3.3 测试
查询列表
新增
查询单个
修改
删除
6.5 DRF的视图集viewsets
6.5.1 代码
from django.shortcuts import render
from rest_framework.decorators import api_view # fbv
from rest_framework.views import APIView #cbv
from rest_framework import generics # gcbv通用视图类
from rest_framework import viewsets # 视图集
from rest_framework.response import Response
from rest_framework import status
from .models import Course
from .serializers import CourseSerializer
"""
一、 函数式编程 FBV
"""
@api_view(['GET', 'POST'])
def coures_list(request):
'''
获取课程列表或新增一个课程
:param request:
:return:
'''
if request.method == 'GET':
courses = CourseSerializer(instance=Course.objects.all(), many=True)
return Response(data=courses.data,status=status.HTTP_200_OK)
elif request.method == 'POST':
serializer = CourseSerializer(data=request.data) # partial=True 只验证部分字段,适用于非必填字段
if serializer.is_valid():
serializer.save(teacher=request.user) # teacher 字段为外键,获取登录用户id,因为复用了django的用户模型,有认证功能
return Response(data=serializer.data, status=status.HTTP_201_CREATED)
return Response(data=serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@api_view(['GET', 'PUT', 'DELETE'])
def course_detail(request, pk):
'''
获取单个课程详情,更新或删除一个课程
:param request:
:param pk:
:return:
'''''
try:
course = Course.objects.get(pk=pk)
except Course.DoesNotExist:
return Response({'message': 'Course not found'}, status=status.HTTP_404_NOT_FOUND)
if request.method == 'GET':
serializer = CourseSerializer(course)
return Response(data=serializer.data, status=status.HTTP_200_OK)
elif request.method == 'PUT':
serializer = CourseSerializer(instance=course, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
elif request.method == 'DELETE':
course.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
else:
return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED)
"""
二、 函数式编程 CBV
"""
class CourseList(APIView):
"""
获取课程列表或新增一个课程
"""
def get(self, request):
queryset = Course.objects.all()
serializer = CourseSerializer(instance=queryset, many=True)
return Response(data=serializer.data, status=status.HTTP_200_OK)
def post(self, request):
serializer = CourseSerializer(data=request.data)
if serializer.is_valid():
serializer.save(teacher=self.request.user)
return Response(data=serializer.data, status=status.HTTP_201_CREATED)
return Response(data=serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class CourseDetail(APIView):
"""
获取单个课程详情,更新或删除一个课程
"""
@staticmethod
def get_object(pk):
'''
获取课程对象
:param self:
:param pk:
:return:
'''
try:
return Course.objects.get(pk=pk)
except Course.DoesNotExist:
return
def get(self, request, pk):
obj = self.get_object(pk=pk)
if obj is None:
return Response({'message': 'Course not found'}, status=status.HTTP_404_NOT_FOUND)
serializer = CourseSerializer(obj)
return Response(data=serializer.data, status=status.HTTP_200_OK)
def put(self, request, pk):
'''
更新课程
:param request:
:param pk:
:return:
'''
obj = self.get_object(pk=pk)
if obj is None:
return Response({'message': 'Course not found'}, status=status.HTTP_404_NOT_FOUND)
serializer = CourseSerializer(instance=obj, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, pk):
'''
删除课程
:param request:
:param pk:
:return:
'''
obj = self.get_object(pk=pk)
if obj is None:
return Response({'message': 'Course not found'}, status=status.HTTP_404_NOT_FOUND)
obj.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
'''
三、 通用视图类
'''
class CourseGenericAPIView(generics.ListCreateAPIView):
'''
获取课程列表或新增一个课程
'''
queryset = Course.objects.all()
serializer_class = CourseSerializer
def perform_create(self, serializer): # 重写perform_create方法,在保存之前添加teacher字段
serializer.save(teacher=self.request.user)
class CourseGenericDetailAPIView(generics.RetrieveUpdateDestroyAPIView):
'''
获取单个课程详情,更新或删除一个课程
'''
queryset = Course.objects.all()
serializer_class = CourseSerializer
'''
四、 视图集
'''
class CourseViewSet(viewsets.ModelViewSet):
queryset = Course.objects.all()
serializer_class = CourseSerializer
def perform_create(self, serializer): # 重写perform_create方法,在保存之前添加teacher字段
serializer.save(teacher=self.request.user)
6.5.2 路由urls---》 这个写法与之前路由不一样
# -*- coding: utf-8 -*-
# @Time : 2024/11/1 10:27
# @Author : super
# @File : urls.py
# @Software: PyCharm
# @Describe:
from django.urls import path,include
from studyApp import views
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(prefix='courseviewsets', viewset=views.CourseViewSet)
urlpatterns = [
# 函数视图FBV
path('fbv/list/', views.coures_list, name='fbv-list'), # 函数视图FBV
path('fbv/detail/<int:pk>/', views.course_detail, name='fbv-detail'), # 函数视图FBV
# 类视图CBV
path('cbv/list/', views.CourseList.as_view(), name='cbv-list'), # 类视图CBV
path('cbv/detail/<int:pk>/', views.CourseDetail.as_view(), name='cbv-detail'), # 类视图CBV
# 通用视图类gcbv
path('gcbv/list/', views.CourseGenericAPIView.as_view(),name='gcbv-list'), # 通用视图类gcbv
path('gcbv/detail/<int:pk>/', views.CourseGenericDetailAPIView.as_view(), name='gcbv-detail'),# 通用视图类gcbv
# 视图集写法不一样
path('', include(router.urls)),
]
6.5.3 测试
列表
新增
查询单个
修改单个
删除单个
七、DRF的认证(了解即可)
前面配置的三种认证,这里了解即可,一般使用jwt,博主其他博文有介绍
7.1 BasicAuthenrication用户名密码认证
这个认证一般用于测试,不要在生产环境使用
7.2 SessionAuthenrication认证
使用的是django默认的后端会话,
7.3 TokenAuthenrication认证
这个要配置,之前配置了
之前执行数据同步将对应库表更新到了数据库,双击这个默认数据库
7.3.1 使用django manage.py 生成token(测试使用)
python manage.py drf_create_token root
# root 是对应用户
在上面的库表可见
7.3.2 通过django的信号机制生成token
7.3.2.1 在视图写函数实现
'''
token 认证
'''
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.conf import settings
from rest_framework.authtoken.models import Token
@receiver(post_save, sender=settings.AUTH_USER_MODEL) # django 信号
def generate_token(sender, instance=None, created=False, **kwargs):
'''
创建用户生成token
:param sender:
:param instance:
:param created:
:param kwargs:
:return:
'''
if created:
Token.objects.create(user=instance)
7.3.2.2 项目urls配置路由
"""
URL configuration for djangoRESTFramework project.
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/4.2/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path,include
from rest_framework.authtoken import views
urlpatterns = [
path('api-token-auth/', views.obtain_auth_token), # token认证
path('admin/', admin.site.urls),
path('studyApp/',include('studyApp.urls')),
path('api-auth/', include('rest_framework.urls')), # DRF登录退出接口,可点击进去看看
]
7.3.2.3 后台创建一个用户
bocai
bocai@163.com
7.3.2.4 调用接口生成token
7.3.2.5 其他接口使用token
7.3.2.6 每个方法设置不同认证
方法认证优先级大于全局settings
函数视图添加方法
类视图\通用类、视图集添加方法相同
from django.shortcuts import render
from rest_framework.decorators import api_view, authentication_classes # fbv
from rest_framework.views import APIView #cbv
from rest_framework import generics # gcbv通用视图类
from rest_framework import viewsets # 视图集
from rest_framework.response import Response
from rest_framework import status
from .models import Course
from .serializers import CourseSerializer
from rest_framework.authentication import BasicAuthentication,SessionAuthentication,TokenAuthentication
'''
token 认证
'''
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.conf import settings
from rest_framework.authtoken.models import Token
@receiver(post_save, sender=settings.AUTH_USER_MODEL) # django 信号
def generate_token(sender, instance=None, created=False, **kwargs):
'''
创建用户生成token
:param sender:
:param instance:
:param created:
:param kwargs:
:return:
'''
if created:
Token.objects.create(user=instance)
"""
一、 函数式编程 FBV
"""
@api_view(['GET', 'POST'])
@authentication_classes((BasicAuthentication,TokenAuthentication))
def coures_list(request):
'''
获取课程列表或新增一个课程
:param request:
:return:
'''
if request.method == 'GET':
courses = CourseSerializer(instance=Course.objects.all(), many=True)
return Response(data=courses.data,status=status.HTTP_200_OK)
elif request.method == 'POST':
serializer = CourseSerializer(data=request.data) # partial=True 只验证部分字段,适用于非必填字段
if serializer.is_valid():
serializer.save(teacher=request.user) # teacher 字段为外键,获取登录用户id,因为复用了django的用户模型,有认证功能
return Response(data=serializer.data, status=status.HTTP_201_CREATED)
return Response(data=serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@api_view(['GET', 'PUT', 'DELETE'])
@authentication_classes((BasicAuthentication,TokenAuthentication))
def course_detail(request, pk):
'''
获取单个课程详情,更新或删除一个课程
:param request:
:param pk:
:return:
'''''
try:
course = Course.objects.get(pk=pk)
except Course.DoesNotExist:
return Response({'message': 'Course not found'}, status=status.HTTP_404_NOT_FOUND)
if request.method == 'GET':
serializer = CourseSerializer(course)
return Response(data=serializer.data, status=status.HTTP_200_OK)
elif request.method == 'PUT':
serializer = CourseSerializer(instance=course, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
elif request.method == 'DELETE':
course.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
else:
return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED)
"""
二、 函数式编程 CBV
"""
class CourseList(APIView):
"""
获取课程列表或新增一个课程
"""
authentication_classes = (BasicAuthentication,SessionAuthentication,TokenAuthentication)
def get(self, request):
queryset = Course.objects.all()
serializer = CourseSerializer(instance=queryset, many=True)
return Response(data=serializer.data, status=status.HTTP_200_OK)
def post(self, request):
serializer = CourseSerializer(data=request.data)
if serializer.is_valid():
serializer.save(teacher=self.request.user)
return Response(data=serializer.data, status=status.HTTP_201_CREATED)
return Response(data=serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class CourseDetail(APIView):
"""
获取单个课程详情,更新或删除一个课程
"""
authentication_classes = (BasicAuthentication, SessionAuthentication, TokenAuthentication)
@staticmethod
def get_object(pk):
'''
获取课程对象
:param self:
:param pk:
:return:
'''
try:
return Course.objects.get(pk=pk)
except Course.DoesNotExist:
return
def get(self, request, pk):
obj = self.get_object(pk=pk)
if obj is None:
return Response({'message': 'Course not found'}, status=status.HTTP_404_NOT_FOUND)
serializer = CourseSerializer(obj)
return Response(data=serializer.data, status=status.HTTP_200_OK)
def put(self, request, pk):
'''
更新课程
:param request:
:param pk:
:return:
'''
obj = self.get_object(pk=pk)
if obj is None:
return Response({'message': 'Course not found'}, status=status.HTTP_404_NOT_FOUND)
serializer = CourseSerializer(instance=obj, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, pk):
'''
删除课程
:param request:
:param pk:
:return:
'''
obj = self.get_object(pk=pk)
if obj is None:
return Response({'message': 'Course not found'}, status=status.HTTP_404_NOT_FOUND)
obj.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
'''
三、 通用视图类
'''
class CourseGenericAPIView(generics.ListCreateAPIView):
'''
获取课程列表或新增一个课程
'''
queryset = Course.objects.all()
serializer_class = CourseSerializer
def perform_create(self, serializer): # 重写perform_create方法,在保存之前添加teacher字段
serializer.save(teacher=self.request.user)
class CourseGenericDetailAPIView(generics.RetrieveUpdateDestroyAPIView):
'''
获取单个课程详情,更新或删除一个课程
'''
queryset = Course.objects.all()
serializer_class = CourseSerializer
'''
四、 视图集
'''
class CourseViewSet(viewsets.ModelViewSet):
queryset = Course.objects.all()
serializer_class = CourseSerializer
def perform_create(self, serializer): # 重写perform_create方法,在保存之前添加teacher字段
serializer.save(teacher=self.request.user)
八、DRF的权限
8.1 常用的权限类
8.2 设置权限策略
函数视图添加方法
类视图\通用类、视图集添加方法相同
8.3 如何自定义对象级别权限
8.3.1 新建permissons.py文件
# -*- coding: utf-8 -*-
# @Time : 2024/11/1 15:58
# @Author : super
# @File : permissions.py
# @Software: PyCharm
# @Describe:
from rest_framework import permissions
class IsOwnerReadOnly(permissions.BasePermission):
"""
自定义权限只允许对象的所有者编辑它。
"""
def has_object_permission(self, request, view, obj):
"""
判断用户是否有权限访问该对象。
:param request:
:param view:
:param obj:
:return: bool
"""
if request.method in permissions.SAFE_METHODS:
return True
# 判断当前用户是否是该对象的拥有者
return obj.teacher == request.user
8.3.2 导入到视图views.py应用
这里是修改
8.3.3 测试
这个id=9 是root创建的
那么bocai无法修改
九、如何使用drf的接口文档
9.1 如何生成接口文档
9.1.1 安装库
前面安装就可不安装
pip install coreapi
pip install pyyaml
9.1.2 settings配置
'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.AutoSchema',
9.1.3 urls配置
"""
URL configuration for djangoRESTFramework project.
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/4.2/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path,include
from rest_framework.authtoken import views
from rest_framework.schemas import get_schema_view
schema_view = get_schema_view(title='DRF API文档',description="API", version="0.1")
urlpatterns = [
path('api-token-auth/', views.obtain_auth_token), # token认证
path('admin/', admin.site.urls),
path('studyApp/',include('studyApp.urls')),
path('api-auth/', include('rest_framework.urls')), # DRF登录退出接口,可点击进去看看
path('schema/', schema_view),
]
9.1.4 访问
谷歌浏览器
9.2 接口文档的使用方法
9.2.1 修改settings
'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',
9.2.2 修改urls
"""
URL configuration for djangoRESTFramework project.
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/4.2/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path,include
from rest_framework.authtoken import views
from rest_framework.documentation import include_docs_urls
# from rest_framework.schemas import get_schema_view
# schema_view = get_schema_view(title='DRF API文档',description="API", version="0.1")
urlpatterns = [
path('api-token-auth/', views.obtain_auth_token), # token认证
path('admin/', admin.site.urls),
path('studyApp/',include('studyApp.urls')),
path('api-auth/', include('rest_framework.urls')), # DRF登录退出接口,可点击进去看看
# path('schema/', schema_view),
path('docs/',include_docs_urls(title='DRF API 文档',description='Django REST Framwork 快速入门')),
]
9.2.3 访问
9.2.4 使用
注意:配置认证页面不能刷新