3 horas para obtener el marco DRF | Práctica del marco de separación frontal del marco Django REST
Prefacio (basado en el asistente de IA de INSCODE)
DRF (nombre completo Django REST framework) es un poderoso conjunto de herramientas para construir Web API. Es un Python Web framework basado en Django. Proporciona a los desarrolladores un conjunto de herramientas para el desarrollo rápido de RESTful API. Puede automatizar la visualización y documentación de API. Realiza pruebas automatizadas de interfaces y enrutamiento API automatizado, serialización, vistas, verificación, paginación, administración de versiones, autenticación y otras funciones. DRF simplifica el desarrollo de API y proporciona una serie de herramientas para crear API de alta calidad.
1.1: Introducción al curso
Objetivo de aprendizaje: usar DRF para desarrollar una interfaz RESTful API
Contenido de aprendizaje: serialización, conjunto de vistas, enrutamiento, autenticación, autoridad
Efecto del curso: varias vistas de DRF realizan la adición, eliminación, modificación y consulta de información del curso
2.1: Comprender la separación de front-end y back-end desde cuatro aspectos
- formulario interactivo
RESTful API es una especificación de interfaz acordada entre los extremos frontal y posterior de i
- Modo de organización del código
Los extremos delantero y trasero no están separados: sintaxis de plantilla de django
Los extremos delantero y trasero están semiseparados
Los extremos delantero y trasero están separados - Modo de desarrollo
Los extremos delantero y trasero no están separados Proceso de desarrollo del proyecto:
los extremos delantero y trasero están separados Proceso de desarrollo del proyecto:
- Proceso de especificación de la interfaz de datos
2.2 Comprensión profunda de qué es RESTful API
Puede aprender de las especificaciones de interfaz de otras personas.
Por ejemplo:
github-API
Comprensión profunda de lo que es RESTful API
2.3 Pycharm crea un entorno de desarrollo de proyectos
- Configuración.py
# 因为RESTframework是有前端文件的,后面使用时会全部放到这个目录
STATIC_ROOT = os.pardir.join(BASE_DIR, "static")
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "staticfiles")
]
- gestionar.py
makemigrations
migrate
createsuperuser
2.4 Introducción e instalación del marco
Sitio web oficial de Django Rest Framework: https://www.django-rest-framework.org/
Realice los siguientes pasos de acuerdo con la documentación:
- 1. Instalar el paquete correspondiente
pip install djangorestframework
pip install markdown # Markdown support for the browsable API.
pip install django-filter # Filtering support
- Modificar la configuración en settings.py
# Add 'rest_framework' to your INSTALLED_APPS setting.
INSTALLED_APPS = [
...
"rest_framework", # 用于开发RESTful API
'rest_framework.authtoken', # DRF自带的Token认证
]
Todas las configuraciones relevantes para el marco de descanso se colocan en un diccionario de configuraciones
# DRF的全局配置
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', # 自带分页类
'PAGE_SIZE': 50, # 每页数据量
'DATETIME_FORMAT': '%Y-%m-%d %H:%M:%S', # 时间显示格式
'DEFAULT_RENDER_CLASSES': [
'rest_framework.renders.JSONRenderer',
'rest_framework.renders.BrowsableAPIRenderer',
], # 返回response对象所用的类
'DEFAULT_PARSER_CLASSES': [
'rest_framework.parsers.JSONParser',
'rest_framework.parsers.FormParser',
'rest_framework.parsers.MultiPartParser',
], # 解析器,如何解析request请求中的request.data
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
], # 权限相关配置
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication',
], # 认证相关配置
"URL_FIELD_NAME": 'link',
}
- Modificar la configuración en urls.py
urlpatterns = [
...
path('api-auth/', include('rest_framework.urls')) # DRF的登录退出
]
- Serialización de 20 módulos de DRF
, vista, enrutamiento, autenticación, permisos, limitación de corriente, filtrado, analizador, renderizador, paginación, versión, prueba, resumen, manejo de excepciones, configuración, verificación, código de estado, negociación de contenido, almacenamiento en caché, metadatos
3.1 Desarrollar la clase modelo de información del curso
modelos.py
from django.db import models
# Create your models here.
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='课程价格')
created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_at = models.DateTimeField(auto_now=True, verbose_name='更新时间')
class Meta:
verbose_name = "课程信息"
verbose_name_plural = verbose_name
ordering = ('price',)
def __str__(self):
return self.name
Registre el campo en el backend para facilitar la adición de datos desde el backend de administración
admin.py
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')
search_fields = list_display
list_filter = list_display
3.2 ¿Qué es la serialización?
La serialización también se denomina serializador, que se refiere a convertir el tipo de datos django del conjunto de consultas QuerySet o instancia de instancia de clase de modelo en json o xml, convertir
queryset o instancia en json/xml/yaml que puede ser fácilmente representado por el front-end,
por lo que serialización y deserialización es
analizar profundamente el serializador de Django para la interacción de datos de front-end y back-end
-
Inicie el proyecto, ingrese el fondo de administrador e inserte datos
-
Prueba el serializador de django en la consola de python
from course.models import Course
from django.core import serializers
serializers.serialize('json', Course.objects.all())
# '[{"model": "course.course", "pk": 1, "fields": {"name": "Django REST framework快速入门", "introduction": "快速入门Django REST framework,学会开发一套自己的Restful API服务,并且自动生成API文档", "teacher": 1, "price": "9.99", "created_at": "2023-07-28T10:11:46.882", "update_at": "2023-07-28T10:11:46.882"}}]'
# 如果只需要序列化一部分字段
serializers.serialize('json', Course.objects.all(), fields=("name"))
# '[{"model": "course.course", "pk": 1, "fields": {"name": "Django REST framework快速入门"}}]'
Pero el serializador de django todavía tiene mucho que mejorar
1. Procesamiento de validación: en el proceso de deserialización, cuando los datos pasados por el front-end se colocan en request.data, deben convertirse en una instancia de clase modelo y luego guardarse. En este momento, es necesario verificar los datos enviados por el front-end.
2. Parámetros del validador
3. Serializar varios objetos al mismo tiempo
4. Agregar contexto durante la serialización
5. Sin manejo de excepciones para datos no válidos
6. El campo de clave externa del campo relacional solo devuelve la identificación, que debe ser manejada por nosotros mismos
El serializador de drf puede ayudarnos a resolver bien estos problemas.
3.3 Cómo heredar ModelSerializer para serializar clases modelo
Aprendizaje de Python———serializador (revisión) El método de serialización para
construir una clase de modelo serializes.py bajo la aplicación es muy similar al método de escritura de formulario durante el desarrollo de django . Primero revise la clase de formulario para la clase de modelo
from django import forms
from rest_framework import serializers # 导入序列化器
from .models import Course
class CourseForm(forms.ModelForm):
class Meta:
model = Course
fields = ('name', 'introduction', 'teacher', 'price')
La serialización de la clase modelo es casi la misma, excepto que hereda de los serializadores. ModelSerializer
teacher es una clave externa, por lo que si desea obtener el nombre correspondiente al disertante, debe serializar el nombre del usuario.
La tabla de usuarios asociada con el profesor no es un usuario nuevo cuando se crea un nuevo curso, por lo que este campo se puede configurar como de solo lectura ReadOnlyField
class CourseSerializer(serializers.ModelSerializer):
teacher = serializers.ReadOnlyField(source='teacher.username') # 外键字段、只读
class Meta:
model = Course # 写法和上面的CourseForm类似
# exclude = ('id', ) # 注意元组中只有1个元素时不能写成("id")
# fields = ('name', 'introduction', 'teacher', 'price')
fields = "__all__"
El mismo método serializa la clase de modelo de usuario.
ModelSerializer es un nivel más alto de encapsulación. Hereda de Serializer. Para lograr una personalización más flexible, puede heredar de Serializer.
Aquí solo serializamos clases de modelo, que es relativamente simple, por lo que puede ser utilizado directamente
from django.contrib.auth.models import User
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = "__all__"
Para la serialización de campos de clave externa, puede especificar la profundidad de recorrido.
Si la estructura de la tabla tiene tablas secundarias asociadas con la tabla principal y la tabla principal está asociada con otra tabla principal, puede establecer la profundidad
class CourseSerializer(serializers.ModelSerializer):
teacher = serializers.ReadOnlyField(source='teacher.username') # 外键字段、只读
class Meta:
model = Course # 写法和上面的CourseForm类似
# exclude = ('id', ) # 注意元组中只有1个元素时不能写成("id")
# fields = ('name', 'introduction', 'teacher', 'price')
fields = "__all__"
depth = 2 # 深度
3.4 Serializador de modelo hipervinculado con URL
Suponiendo que al solicitar información del curso, se espera que cada registro de información del curso pueda saltar a la página de detalles
Todas las configuraciones relacionadas con DRF están escritas en el diccionario REST_FRAMEWORK en settings.py
Heredado de
los campos HyperlinkedModelSerializer Add url
url es el valor predeterminado, si desea cambiarlo a otro nombre, como "enlace", puede establecer URL_FIELD_NAME en la configuración. py para usar Take effect globalmente
configuración.py
# DRF的全局配置
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', # 自带分页类
'PAGE_SIZE': 50, # 每页数据量
'DATETIME_FORMAT': '%Y-%m-%d %H:%M:%S', # 时间显示格式
'DEFAULT_RENDER_CLASSES': [
'restframework.renders.JSONRenderer',
'restframework.renders.BrowsableAPIRenderer',
], # 返回response对象所用的类
'DEFAULT_PARSER_CLASSES': [
'rest_framework.parsers.JSONparser',
'rest_framework.parsers.Formparser',
'rest_framework.parsers.MultiPartparser',
], # 解析器,如何解析request请求中的request.data
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
], # 权限相关配置
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication',
], # 认证相关配置
"URL_FIELD_NAME": 'link',
}
serializadores.py
class CourseSerializer(serializers.HyperlinkedModelSerializer):
teacher = serializers.ReadOnlyField(source='teacher.username') # 外键字段、只读
class Meta:
model = Course # 写法和上面的CourseForm类似
# url是默认值,可在settings.py中设置URL_FIELD_NAME使全局生效
# fields = ('id', 'url', 'name', 'introduction', 'teacher', 'price', 'created_at', 'update_at')
fields = ('id', 'link', 'name', 'introduction', 'teacher', 'price', 'created_at', 'update_at')
4.1 Las vistas de Django desarrollan una interfaz API RESTful
Use cuatro formas diferentes de interactuar con Restful API a través de DRF
- programación funcional
- vista de clase
- Vista de clase genérica
- Conjuntos de vistas para DRF
en el archivo vistas.py
4.1.1 Interfaz API de programación funcional vista nativa de Django
La idea es juzgar qué método es este y luego tratarlo.
@csrf_exempt
def course_list(request):
course_dict = {
'name': '课程名称',
'introduction': '课程介绍',
'price': 0.11
}
if request.method == "GET":
# return HttpResponse(json.dumps(course_dict), content_type='application/json')
return JsonResponse(course_dict) # 这两种写法是等价的
if request.method == "POST":
course = json.loads(request.body.decode('utf-8'))
return JsonResponse(course, safe=False) # 如果解析的数据不是字典类型,是字符串的话,需要使用safe=false
Necesidad de prestar atención: solicitud de publicación, necesidad de usar el decorador para eliminar la restricción csrf
4.1.2 Interfaz API de programación de vista de clase de vista nativa de Django
La idea de escribir CBV es usar funciones correspondientes para procesar diferentes métodos de solicitud
import json
from django.http import JsonResponse, HttpResponse
from django.views import View
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator
# Django CBV 编写API接口
@method_decorator(csrf_exempt, name='dispatch')
class CourseList(View):
def get(self, request):
return JsonResponse(course_dict)
@csrf_exempt
def post(self, request):
course = json.loads(request.body.decode('utf-8'))
return JsonResponse(course, safe=False) # 如果解析的数据不是字典类型,是字符串的话,需要使用safe=false
El decorador de métodos se puede importar, y el método de decoración es envío, porque de acuerdo con el principio de respuesta de solicitud de django, cuando llega la solicitud, primero llega al método de envío y, después de ser procesada por el método de envío, encuentra el método de publicación.
Los dos métodos anteriores son para usar directamente Django nativo para escribir la interfaz, y hay muchas cosas que deben implementarse desde cero.
Tales como paginación, clasificación, autenticación, permisos, limitación actual, etc.
Luego hay una vista de DRF, que integra las funciones comunes de este desarrollo de interfaz.
4.2 DRF decorador api_view - programación funcional
4.2.1 Implementar la interfaz de "obtener toda la información del curso o agregar un nuevo curso"
- Nueva vista fbv de drf
from rest_framework.decorators import api_view
from rest_framework.response import Response # django使用的是JsonResponse或HttpResponse,而drf直接封装好了,就是Response
from rest_framework import status
from .models import Course
from .serializers import CourseSerializer
"""一、函数式编程 Function Based View"""
@api_view(["GET", "POST"])
def course_list(request):
"""
获取所有课程信息或新增一个课程
:param request:
:return:
"""
if request.method == "GET":
s = CourseSerializer(instance=Course.objects.all(), many=True) # 序列化多个对象,所以需要many=True
# 序列化后的数据可以通过s.data获得
return Response(data=s.data, status=status.HTTP_200_OK)
elif request.method == "POST":
s = CourseSerializer(data=request.data, partial=True) # 反序列化, partial=True表示部分更新
if s.is_valid():
s.save(teacher=request.user) # 讲师是只读属性
return Response(data=s.data, status=status.HTTP_201_CREATED)
return Response(s.erros, status=status.HTTP_400_BAD_REQUEST)
La programación funcional usará el decorador
Partial=True para indicar actualizaciones parciales.
- nueva ruta
Para facilitar la gestión de rutas en la aplicación del curso, cree un archivo urls.py en la aplicación del curso y luego inclúyalo en las direcciones URL del proyecto mediante include
django urls include use
curso/urls.py
from django.urls import path
from course import views
urlpatterns = [
# Function Based View
path("fbv/list/", views.course_list, name="fbv-list")
]
drf_tutorial/urls.py
urlpatterns = [
path('api-auth/', include('rest_framework.urls')), # DRF的登录退出
path("admin/", admin.site.urls),
path('course/', include('course.urls'))
]
La API de HyperlinkedModelSerializer no se usa primero, porque HyperlinkedModelSerializer es una clase de serialización altamente integrada, que se puede usar para programar con la vista drf configurada más adelante. Entonces, la clase serializadora usa en su lugar:
class CourseSerializer(serializers.ModelSerializer):
teacher = serializers.ReadOnlyField(source='teacher.username') # 外键字段、只读
class Meta:
model = Course # 写法和上面的CourseForm类似
# exclude = ('id', ) # 注意元组中只有1个元素时不能写成("id")
# fields = ('name', 'introduction', 'teacher', 'price')
fields = "__all__"
depth = 2 # 深度
- resultado devuelto
- solicitud de puesto de prueba
4.2.2 Implementar la interfaz de "obtener información de un curso o actualizar y eliminar información de un curso"
- Darse cuenta de la vista
@api_view(["GET", "PUT", "DELETE"])
def course_detail(request, pk): # 通过url传递pk
"""
获取、更新、删除一个课程
:param request:
:param pk:
:return:
"""
try:
course = Course.objects.get(pk=pk)
except Course.DoesNotExist:
return Response(data={
"msg": "没有此课程信息"}, status=status.HTTP_404_NOT_FOUND)
else:
if request.method == "GET":
s = CourseSerializer(instance=course) # 序列化一个对象不需要many=True
return Response(data=s.data, status=status.HTTP_200_OK)
elif request.method == "PUT": # PUT方法表示更新,部分写法和POST方法类似
s = CourseSerializer(instance=course, data=request.data) #instance是指要序列化哪个实例,data表示数据哪里来的
# 表示把data的数据,反序列化之后,保存或者更新到cuorse对象里
if s.is_valid():
s.save() # 不需要teacher字段
return Response(s.data, status=status.HTTP_200_OK)
elif request.method == "DELETE":
course.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
- implementar enrutamiento
urlpatterns = [
# Function Based View
path("fbv/list/", views.course_list, name="fbv-list")
path("fbv/detail/<int:pk>", views.course_detail, name="fbv-detail")
]
4.3 Cómo usar Postman para probar la interfaz API (Soy apipost aquí)
Aquí tomo apipost como ejemplo
método de verificación:
-
autenticación de autenticación básica: nombre de cuenta, autenticación de contraseña
-
autenticación de clave api: autenticación de token
-
OAuth 2.0, etc
Para agregar algunas claves y valores al encabezado de la solicitud, puede hacer clic en la
consulta del encabezado, que es un parámetro en la URL
. Los datos de la solicitud analizados en el código de back-end generalmente se colocan en bruto
- Publicar solicitud
- Obtener solicitud
4.4 Ver APIView en DRF - programación de vista de clase
4.4.1 Implementar la interfaz de "obtener toda la información del curso o agregar un nuevo curso"
- importar APIView
from rest_framework.views import APIView
- Implementar vista de clase
"""二、类视图 Class Based View"""
class CourseList(APIView):
def get(self, request):
"""
:param request:
:return:
"""
queryset = Course.objects.all()
s = CourseSerializer(instance=queryset, many=True)
return Response(s.data, status=status.HTTP_200_OK)
def post(self, request):
"""
:param request:
:return:
"""
s = CourseSerializer(data=request.data)
if s.is_valid():
s.save(teacher=self.request.user)
print(type(request.data), type(s.data))
# type(request.data): <class 'dict'>
# type(s.data): <class 'rest_framework.utils.serializer_helpers.ReturnDict'>
return Response(data=s.data, status=status.HTTP_201_CREATED)
return Response(s.errors, status=status.HTTP_400_BAD_REQUEST)
- nueva ruta
urlpatterns = [
# Function Based View
path("fbv/list/", views.course_list, name="fbv-list"),
path("fbv/detail/<int:pk>/", views.course_detail, name="fbv-detail"),
# Class Based View
path("cbv/list/", views.CourseList.as_view(), name='cbv-list')
]
- solicitud de prueba
4.4.2 Implementar la interfaz de "página de detalles"
Método estático: ya sea que se llame directamente a través de un objeto de clase o un objeto de instancia, es posible llamarlo. Cabe señalar que los atributos y métodos de instancia no se pueden usar en métodos estáticos. Métodos estáticos, métodos de instancia y métodos de clase de
Python
- implementar la interfaz
class CourseDetail(APIView):
@staticmethod # 静态方法
def get_object(pk):
"""
:param pk:
:return:
"""
try:
return Course.objects.get(pk=pk)
except Course.DoesNotExist:
return
def get(self, request, pk):
"""
:param request:
:param pk:
:return:
"""
obj = self.get_object(pk=pk)
if not obj:
return Response(data={
"msg": "没有此课程信息"}, status=status.HTTP_404_NOT_FOUND)
s = CourseSerializer(instance=obj)
return Response(s.data, status=status.HTTP_200_OK)
def put(self, request, pk):
obj = self.get_object(pk=pk)
if not obj:
return Response(data={
"msg": "没有此课程信息"}, status=status.HTTP_404_NOT_FOUND)
s = CourseSerializer(instance=obj, data=request.data)
if s.is_valid():
s.save()
return Response(data=s.data, status=status.HTTP_200_OK)
return Response(s.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, pk):
"""
:param request:
:param pk:
:return:
"""
obj = self.get_object(pk=pk)
if not obj:
return Response(data={
"msg": "没有此课程信息"}, status=status.HTTP_404_NOT_FOUND)
obj.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
- implementar enrutamiento
urlpatterns = [
# Function Based View
path("fbv/list/", views.course_list, name="fbv-list"),
path("fbv/detail/<int:pk>/", views.course_detail, name="fbv-detail"),
# Class Based View
path("cbv/list/", views.CourseList.as_view(), name='cbv-list'),
path("cbv/detail/<int:pk>/", views.CourseDetail.as_view(), name='cbv-detail'),
]
- solicitud de prueba
El método de programación de vista de clases es casi el mismo que el método de programación funcional, y el código es casi el mismo. La siguiente sección explica una forma más concisa de escribir.
4.5 La vista de clase genérica GenericAPIView en DRF
importar genéricos
from rest_framework import generics
4.5.1 Realizar visualización y solicitud de nuevas interfaces
La vista general de clases en realidad mezcla las clases correspondientes a algunas operaciones comunes de adición, eliminación, modificación y consulta a través de mixin.
El nombre del atributo aquí está fijo.
Aquí debe sobrecargar el método perform_create.
4.5.2 Implementar la interfaz de detalles del curso
- Implementar una vista de clase genérica
La siguiente escritura es equivalente a
class GCourseDetail(generics.RetrieveUpdateDestroyAPIView):
pero para el siguiente método, el método de solicitud ya no es GET, PUT, PATCH, DELETE, sino recuperar, actualizar, destruir, etc., por lo que se recomienda utilizarclass GCourseDetail(generics.RetrieveUpdateDestroyAPIView):
from rest_framework import mixins
from rest_framework.generics import GenericAPIView
class GCourseDetail(generics.mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
GenericAPIView):
queryset = Course.objects.all()
serializer_class = CourseSerializer
- nueva ruta
urlpatterns = [
# Function Based View
path("fbv/list/", views.course_list, name="fbv-list"),
path("fbv/detail/<int:pk>/", views.course_detail, name="fbv-detail"),
# Class Based View
path("cbv/list/", views.CourseList.as_view(), name='cbv-list'),
path("cbv/detail/<int:pk>/", views.CourseDetail.as_view(), name='cbv-detail'),
# Generic Class Based View
path("gcbv/list/", views.GCourseList.as_view(), name='gcbv-list'),
path("gcbv/detail/<int:pk>/", views.GCourseDetail.as_view(), name='gcbv-detail'),
]
- solicitud de prueba
Otras cosas se hacen en la vista de clase general: número total (recuento), página siguiente (siguiente), página anterior (anterior), datos (resultados)
4.6 Interfaz de desarrollo de viewsets de DRF para agregar, eliminar, modificar y consultar información del curso - Viewset
- importar conjuntos de vistas
from rest_framework import viewsets
- crear conjunto de vistas
"""四、DRF的视图集"""
class CourseViewSet(viewsets.ModelViewSet):
queryset = Course.objects.all()
serializer_class = CourseSerializer
def perform_create(self, serializer):
serializer.save(teacher=self.request.user)
Solo se requieren cuatro líneas de código sin autorización de autenticación
4.7 URL de Django y enrutadores DRF
- nueva ruta
La forma de escribir es diferente a la
forma anterior de escribir las rutas de los dos conjuntos de vistas.
-
- 1 escritura tradicional
# DRF viewsets
path("viewsets/", views.CourseViewSet.as_view(
{
"get": "list", "post": "create"}
), name="viewsets-list"),
path("viewsets/<int:pk>/", views.CourseViewSet.as_view(
{
"get": "retrieve", "put": "update", "patch": "partial_update", "delete": "destory"}
), name="viewsets-detail")
-
- 2. Enrutadores de enrutamiento DRF
- importar
from rest_framework.routers import DefaultRouter
router = DefaultRouter() # 把类实例化
router.register(prefix="viewsets", viewset=views.CourseViewSet) # 把视图集注册到这个路由实例里面
urlpatterns = [
path("", include(router.urls))
]
- interfaz de prueba
5.1 Introducción a los métodos de autenticación DRF
Tres métodos de autenticación comúnmente utilizados en DRF:
1.BasicAuthentication: autenticación de nombre de usuario y contraseña
2.SessionAuthentication: autenticación de sesión
3.TokenAuthentication: autenticación de token
También puede implementar un esquema de autenticación personalizado, o usar un paquete de terceros, como json webtoken (sobre la autenticación jwt, que se explicará en el próximo curso práctico avanzado de drf).La diferencia entre autenticación y autoridad: la autenticación es la identidad del inicio de sesión
del usuario
Realizar verificación
El permiso se refiere a qué interfaces puede acceder un usuario que ha pasado la verificación de inicio de sesión; o para una interfaz determinada, qué nivel de datos puede obtener
De acuerdo con el proceso de respuesta de Django restframework a la solicitud http, la autenticación de identidad ocurre antes verificación de permisos y verificación de límite actual
Autenticación y permisos, el núcleo depende de dos datos: request.user, request.auth
El mecanismo de autenticación en realidad se basa en las múltiples clases de autenticación
en el marco de autenticación de Django
'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework.authentication.BasicAuthentication', 'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.TokenAuthentication', ],
, y DRF autenticará cada clase en orden de arriba a abajo. Y use la primera clase de autenticación aprobada con éxito para devolver el valor para establecer request.user y request.auth
5.1.1 Autenticación básica
Si se establece la autenticación básica, los encabezados tendrán una autorización adicional, que es el texto cifrado calculado por la biblioteca base64 del nombre de usuario y la contraseña, que el cartero completa automáticamente. La biblioteca base64 no es confidencial y se puede descifrar. Por lo tanto, la autenticación básica generalmente se usa para el trabajo de prueba, no para el entorno de producción.
- Pruebe, después de pasar la autenticación de autenticación básica, qué devuelven request.user y request.auth
print(self.request.user, self.request.auth)
print(type(self.request.user), type(self.request.auth))
# admin None
# <class 'django.contrib.auth.models.User'> <class 'NoneType'>
- Compruebe qué información hay en el encabezado de respuesta.
La contraseña es correcta.
La contraseña es incorrecta.
Si la autenticación falla, habrá un campo WWW_Authenticate adicional en el encabezado de respuesta.
5.1.2 Autenticación de sesión
Se usa el backend de sesión predeterminado de Django. Por lo general, la autenticación de sesión se puede usar cuando se usan solicitudes HTTP y ajax en el front-end js. Al usar esto, se debe proporcionar un token csrf al backend.
5.1.3 Autenticación de Token
Es un método de autenticación http simple basado en token
- Agregue INSTALLED_APPS en settings.py
'rest_framework.authtoken'
generará una tabla de datos
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"rest_framework", # 用于开发RESTful API
'rest_framework.authtoken', # DRF自带的Token认证
'course.apps.CourseConfig',
]
- La forma de generar token
5.1.3.1 Usar Django manag.py para generar Token
Solo lo pueden usar los administradores para probar
Generar tokens manualmente
python manage.py drf_create_token admin #给admin建一个token
5.1.3.2 Usando el mecanismo de señal de Django para generar Token
Propósito:
para generar tokens automáticamente,
los usuarios pueden solicitar tokens a través de la interfaz
ver.py
from django.db.models.signals import post_save # 保存之后,即用户已经建好之后的信号
from django.conf import settings
from django.dispatch import receiver # 接收信号
from rest_framework.authtoken.models import Token
@receiver(post_save, sender=settings.AUTH_USER_MODEL)
def generate_token():
También puede importar directamente la clase de modelo de usuario de django como clase de modelo de autenticación:
from django.contrib.auth.models import User
Principio: cuando una clase de modelo de usuario crea una nueva instancia y la guarda, es decir, cuando se crea un nuevo usuario, porque se llama al método save para guardar, el La señal post_save
se transmitirá al receptor, después de que el receptor acepte, ejecutará la función generar_token
Al ejecutar la función, la instancia se refiere a la instancia de usuario recién creada, created=True, por lo que se genera un registro en la tabla authtoken_token
¿Cómo puede el usuario obtener el token generado para el usuario?
rest_framework ha sido escrito para nosotros, podemos llamarlo directamente
En ruta total urls.py
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('api-auth/', include('rest_framework.urls')), # DRF的登录退出
path("admin/", admin.site.urls),
path('course/', include('course.urls'))
]
- Prueba: cree un nuevo usuario
user01 - mima123456
, puede ver que hay nuevos registros en la tabla de tokens
- Pruebe, obtenga token a través de la interfaz a través del cartero
Encabezado de solicitud de autenticación exitosa
print(self.request.user, self.request.auth)
print(type(self.request.user), type(self.request.auth))
# user01 e1e4eb90e389feb76c8bb71ad73e3b3c63e8090c
# <class 'django.contrib.auth.models.User'> <class 'rest_framework.authtoken.models.Token'>
Si la autenticación es exitosa, request.user sigue siendo una instancia de la clase de usuario de Django
request.auth es una instancia de la clase Token
y no hay información relacionada con la autenticación en el encabezado de respuesta.
- Autenticación fallida
- Para usar un método de autenticación diferente para una determinada interfaz
No importa qué método de programación de vistas se utilice, existen métodos de configuración correspondientes. Los siguientes son cuatro métodos de programación de vista diferentes, que se explican por separado.
-
- 1. Para la programación funcional
, importe la clase de decoración para la autenticación:
- 1. Para la programación funcional
from rest_framework.decorators import api_view, authentication_classes
from rest_framework.authentication import BasicAuthentication, SessionAuthentication, TokenAuthentication
Se ordenan decoradores
Un decorador de clase que solo agrega autenticación de contraseña al objeto
@api_view(["GET", "POST"])
@authentication_classes((BasicAuthentication, )) # 对象级别的认证设置,优先于全局设置
def course_list(request):
"""
获取所有课程信息或新增一个课程
:param request:
:return:
"""
if request.method == "GET":
s = CourseSerializer(instance=Course.objects.all(), many=True) # 序列化多个对象,所以需要many=True
# 序列化后的数据可以通过s.data获得
return Response(data=s.data, status=status.HTTP_200_OK)
elif request.method == "POST":
s = CourseSerializer(data=request.data, partial=True) # 反序列化, partial=True表示部分更新
if s.is_valid():
s.save(teacher=request.user) # 讲师是只读属性
return Response(data=s.data, status=status.HTTP_201_CREATED)
return Response(s.erros, status=status.HTTP_400_BAD_REQUEST)
- prueba
Presta atención a la redacción, debe ser
Token xxx
-
2. Agregue atributos de clase directamente a la programación de vista de claseauthentication_classes
class CourseList(APIView):
authentication_classes = (BasicAuthentication, SessionAuthentication, TokenAuthentication)
Lo mismo es cierto para las vistas de clases generales y los conjuntos de vistas, y también tienen atributos de clase.
5.3 Control de permisos DRF
¿Cuáles son las clases de permiso de uso común? ¿Cómo deben establecerse las políticas de permisos? ¿Cómo personalizar los permisos de nivel de objeto?
Los permisos de DRF están todos en el módulo de permisos. El proceso de verificación de permisos es el mismo que el de autenticación de identidad explicado anteriormente, y la información de autenticación de identidad en los atributos request.user y request.auth también se usa para determinar si la solicitud es aprobada en. ,
5.3.1 Las clases de permisos globales se pueden configurar en settings.py
- Las clases de permisos comunes son:
IsAuthenticatedOrReadOnly: los usuarios registrados pueden agregar, eliminar, modificar y consultar, y los usuarios no registrados pueden consultar
IsAuthenticated: solo los usuarios registrados pueden realizar todas las operaciones, los usuarios no registrados no pueden realizar todas las operaciones y obtener no funciona. IsAdminUser
: los usuarios administradores tienen permiso para acceder a la interfaz, ¿verdad? El administrador mira el campo is_staff de la tabla auth_user, verdadero significa que es un usuario de nivel administrador
AllowAny: Permitir todas las solicitudes
5.3.2 Cómo establecer permisos a nivel de interfaz/objeto
- decorador de importación
from rest_framework.decorators import api_view, authentication_classes, permission_classes
- Clase de permiso de importación
在这里插入代码片
5.3.2.1 Establecer permiso para la vista de funciones
- Agregar un decorador a la vista de funciones
@api_view(["GET", "POST"])
@authentication_classes((BasicAuthentication, )) # 对象级别的认证设置,优先于全局设置
@permission_classes((IsAuthenticated, )) # 自定义的权限类
def course_list(request):
5.3.2.2 Configuración de permisos para vistas de clase/vistas de clase generales/conjuntos de vistas
- directamente en el atributo de clase
authentication_classes
permission_classes = (IsAuthenticated, )
5.3.3 ¿Cómo personalizar los permisos a nivel de objeto?
La implementación solo puede modificar su propia información, y la información de otras personas solo se puede ver, no modificar.
- Cree permiso.py en la aplicación y cree una clase de permiso personalizada
permiso.py
class IsOwnerReadOnly(permissions.BasePermission):
"""
自定义权限:只有对象的所有者可以增删改查
"""
def has_object_permission(self, request, view, obj): # 重写BasePermission的方法
"""
所有的request请求都有读权限,因此一律允许GET/HEAD/OPTIONS方法
如果用户是自己,可以修改
:param request:
:param view:
:param obj:
:return: bool
"""
if request.method in permissions.SAFE_METHODS:
return True
# 对象的所有者才有写权限
return obj.teacher == request.user
has_object_permission
Métodos anulados
Los métodos seguros("GET", "HEAD", "OPTIONS")
se puedenpermissions.SAFE_METHODS
reemplazar con
- Importe la clase de permiso personalizada creada en la vista
from .permission import IsOwnerReadOnly
class GCourseList(generics.ListCreateAPIView):
queryset = Course.objects.all()
serializer_class = CourseSerializer
permission_classes = (IsAuthenticated, )
def perform_create(self, serializer):
serializer.save(teacher=self.request.user)
class GCourseDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Course.objects.all()
serializer_class = CourseSerializer
permission_classes = (IsAuthenticated, IsOwnerReadOnly)
- interfaz de prueba
6.1 Cómo generar documentos de interfaz API
6.1.1 Cómo generar documentos de interfaz API
Puede ver el formato y otra información de una sola interfaz solicitando la url. Pero, ¿hay alguna manera de mostrar toda la información de la interfaz, es decir, la documentación en línea de la API,
para que el front-end pueda verla fácilmente y quede claro de un vistazo?
Las siguientes operaciones primero debenpip install coreapi
- 1. Agregar a REST_FRAMEWORK de settings.py
REST_FRAMEWORK = {
'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.AutoSchema',
...
}
- 2. Agregue el enrutamiento en el total de urls.py,
primero importe get_schema_view
y luego cree la instancia get_schema_view
y luego cree el enrutamiento
from rest_framework.schemas import get_schema_view
schema_view = get_schema_view(title="DRF API文档", description="xxx")
urlpatterns = [
path("api-token-auth/", views.obtain_auth_token), # 获取token的接口
path('api-auth/', include('rest_framework.urls')), # DRF的登录退出
path("admin/", admin.site.urls),
path('course/', include('course.urls')),
path('schema/', schema_view),
]
- prueba
Se recomienda descargar el complemento jsonView en Chrome App Store
Haga clic en GET-corejson
Pero el documento aún no es lo suficientemente hermoso, la siguiente sección presenta la función general de usar coreapi
6.2 Introducción al uso general de DRF
Cómo se debe configurar coreapi y cómo utilizar el documento.
- Modifique la propiedad 'DEFAULT_SCHEMA_CLASS' de REST_FRAMEWORK
- en urls.py
-
- 1. Importar el módulo y agregar una nueva ruta
from rest_framework.documentation import include_docs_urls
urlpatterns = [
path("api-token-auth/", views.obtain_auth_token), # 获取token的接口
path('api-auth/', include('rest_framework.urls')), # DRF的登录退出
path("admin/", admin.site.urls),
path('docs/', include_docs_urls(title='DRF API文档', description='Django REST framework快速入门')),
path('course/', include('course.urls')),
]
- prueba
En este documento de API, después de configurar la autenticación, debe volver a configurarse después de actualizar
7.1 Resumen del curso
-
¿Qué desarrollo de vista se debe usar?
Use la vista funcional para escribir de manera flexible, pero esta es una forma orientada al proceso y la tasa de repetición es alta.
Usando la vista de clase, puede usar las características de las clases en python, encapsulación, herencia, polimorfismo y reducir la repetición de código. Clase general La vista es más
flexible Bajo
El conjunto de vistas es altamente personalizado y la flexibilidad es mínima
En general, la programación de vista de clases es el método principal. -
¿Cómo funciona DRF? Código fuente APIView? ¿prueba? ¿cache? limitando . . no hablé de eso