Django Rest_Framework (2)


Quand un sérialiseur déclaré doit-il hériter de la classe de base du sérialiseur Serializer, et quand hérite-t-il de la classe du sérialiseur de modèle ModelSerializer ?

继承序列化器类Serializer
	字段声明
	验证
	添加/保存数据功能
继承模型序列化器类ModelSerializer
	字段声明[可选,看需要]
	Meta声明
	验证
	添加/保存数据功能[可选]

Vérifiez si les données sont obtenues à partir de la base de données MySQL. Si c'est le cas, utilisez ModelSerializer. Sinon, utilisez Serializer.

1. Réponse à la demande http

En plus d'abréger le code dans la partie sérialisation des données, drf fournit également des opérations d'abréviation dans les vues. Par conséquent, sur la base de la classe django.views.View originale de Django, drf encapsule plusieurs sous-classes de vues que nous pouvons utiliser.

Les principales fonctions des vues fournies par le framework Django REST :

  • Contrôler l'exécution du sérialiseur (vérifier, enregistrer, convertir les données)
  • Contrôler l'exécution des requêtes de base de données
  • Appelez la classe de requête et la classe de réponse [Ces deux classes sont également étendues par drf pour nous aider à étendre certaines classes fonctionnelles. ]

Afin de faciliter notre apprentissage, nous créons d'abord une sous-application req

python manage.py startapp req

Sous-référence du registre :

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'students',
    'sers',    # 序列化器
    "school",  # 序列化器嵌套
    'req',     # 请求与响应
]

Enregistrer un itinéraire

# 子应用路由
from django.urls import path
from . import views
urlpatterns = [

]


# 总路由
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('students/', include("students.urls")),
    path('sers/', include("sers.urls")),
    path('school/', include("school.urls")),
    path("req/", include("req.urls")),
]

1.1. Demande et réponse

Négociation de contenu : sur la base du Django d'origine, drf a ajouté un nouvel objet de requête et en a hérité de la classe de vue APIVIew, et a implémenté une sous-classe de réponse rest_framework.response.Response basée sur la classe de réponse HttpResponse d'origine de Django. Les deux classes effectuent la conversion du format de données sur la base de la négociation de contenu.

request->parser analysing class->identifier le Content-Type dans l'en-tête de la requête du client pour terminer la conversion des données en->dictionnaire de classe (QueryDict, une sous-classe du dictionnaire)

réponse->classe de rendu du moteur->Identifiez le "Accepter" de l'en-tête de la requête client pour extraire le format de données de retour attendu par le client, -> Convertissez-le dans les données au format attendu par le client

[Le transfert de l'image du lien externe a échoué. Le site source peut avoir un mécanisme anti-sangsue. Il est recommandé de sauvegarder l'image et de la télécharger directement (img-5kzAIkXK-1691197102532) (assets/image-20211020101829885.png)]

1.1.1 Demande

L'objet request passé dans la vue par le framework REST n'est plus l'objet HttpRequest par défaut de Django, mais un objet de la classe Request fournie par le framework REST qui étend la classe HttpRequest.

Le framework REST fournit un analyseur Parser.Après avoir reçu une requête, il analysera automatiquement les données de la requête en fonction du type de données de la requête (tel que JSON, formulaire, etc.) spécifié par Content-Type, et les analysera dans un dictionnaire de type [ QueryDict] et enregistrez-le dans l' objet Request .

Les données de l'objet Request sont automatiquement analysées en fonction du format des données envoyées par le front-end.

Quel que soit le format de données envoyé par le front-end, nous pouvons lire les données de manière uniforme.

1.1.1.1 Attributs communs

1).données

request.dataRenvoie les données du corps de la requête analysées . Similaire au standard request.POSTet request.FILESaux attributs de Django, mais offre les fonctionnalités suivantes :

  • Contient des données de fichiers et non-fichiers analysées
  • Contient les données analysées pour les méthodes de requête POST, PUT et PATCH
  • Utilisant l'analyseur syntaxique du framework REST, il prend non seulement en charge les données de type de formulaire, mais prend également en charge les données JSON.
2).query_params

query_params, paramètres de requête, également appelés chaîne de requête (chaîne de requête)

request.query_paramsIdentique au standard Django request.GET, juste changé pour un nom plus correct.

3)request._request

Récupère l'objet Request encapsulé par Django

Utilisation de base

Afficher le code :

from django.views import View
from django.http.response import HttpResponse
from django.http.request import HttpRequest
from django.core.handlers.wsgi import WSGIRequest
class ReqView(View):
    def get(self,request):
        print(request)
        return HttpResponse("ok")

"""
默认情况下, 编写视图类时,如果继承的是django内置的django.view.View视图基类,
则视图方法中得到的request对象,是django默认提供的django.core.handlers.wsgi.WSGIRequest
WSGIRequest这个请求处理对象,无法直接提供的关于json数据数据处理。
在编写api接口时很不方便,所以drf为了简写这块内容,在原来的HttpRequest的基础上面,新增了一个Request对象
这个Request对象是单独声明的和原来django的HttpRequest不是父子关系。
同时注意:
   要使用drf提供的Request请求处理对象,必须在编写视图类时继承drf提供的视图基类
   from rest_framework.views import APIView
   
   如果使用drf提供的视图基类APIView编写类视图,则必须使用来自drf提供的Request请求对象和Response响应对象
"""
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
class ReqAPIView(APIView):
    def get(self,request):
        # rest_framework.request.Request对象
        print(request) # <rest_framework.request.Request: GET '/req/req2?name=xiaoming&age=17&lve=swim&lve=code'>
        # 获取查询字符串
        print(request.query_params)
        # 没有参数情况下: <QueryDict: {}>
        # 有参数的情况下: <QueryDict: {'name': ['xiaoming'], 'age': ['17'], 'lve': ['swim', 'code']}>
        # 所以,request.query_params的返回值操作和原来在django里面是一模一样的
        print(request.query_params.get("name")) # xiaoming
        print(request.query_params.getlist("lve")) # ['swim', 'code']

        return Response("ok")

    def post(self, request):
        # 获取请求体
        print(request.data) # {'name': 'xiaoming', 'age': 16, 'lve': ['swim', 'code']}
        """直接从请求体中提取数据转
        # 客户端如果上传了json数据,直接返回字典
        {'name': '灰太狼', 'age': 20, 'sex': 1, 'classmate': '301', 'description': '我还会再回来的~'}
        # 客户端如果上传了表单数据,直接返回QueryDict
        <QueryDict: {'name': ['xiaohui'], 'age': ['18']}>
        """
        print(request.FILES) # 获取上传文件列表
        
        # 要获取django原生提供的HttpRequest对象,可以通过request._request来获取到
        print(request._request.META.get("Accept")) # 当值为None时,drf默认在响应数据时按json格式返回
        # response = Response(data="not ok", status=204, headers={"Company":"Oldboy"})
        response = Response(data="not ok", status=status.HTTP_400_BAD_REQUEST, headers={
    
    "Company":"Oldboy"})
        return response

1.1.2 Réponse

rest_framework.response.Response

Le framework REST fournit une classe de réponse.Lors Responsede l'utilisation de cette classe pour construire un objet de réponse, le contenu des données spécifiques de la réponse sera converti (rendu) en un type qui répond aux exigences frontales.

Le framework REST fournit Rendererun moteur de rendu pour Acceptconvertir automatiquement les données de réponse dans le format correspondant en fonction de la (déclaration de type de données reçue) dans l'en-tête de la demande. Si Accept n'est pas déclaré dans la requête front-end, les données de réponse seront traitées en mode Content-Type. Nous pouvons modifier le format de réponse par défaut via la configuration.

Vous pouvez trouver tous les éléments de configuration par défaut de drf dans rest_framework.settings

REST_FRAMEWORK = {
    
    
    'DEFAULT_RENDERER_CLASSES': (  # 默认响应渲染类
        'rest_framework.renderers.JSONRenderer',  # json渲染器,返回json数据
        'rest_framework.renderers.BrowsableAPIRenderer',  # 浏览器API渲染器,返回调试界面
    )
}

1.1.2.1 Méthode de construction

Response(data, status=None, template_name=None, headers=None, content_type=None)

La classe de traitement des réponses de drf est différente de la classe de traitement des requêtes. Response est une sous-classe de la classe de traitement des réponses HttpResponse de Django.

dataLes données n'ont pas besoin d'être les données après le traitement du rendu, il suffit de transmettre les données de type intégrées de Python et le framework REST utilisera le renderermoteur de rendu pour les traiter data.

dataIl ne peut pas s'agir de données avec une structure complexe, comme l'objet de classe modèle de Django. Pour de telles données, nous pouvons utiliser un Serializersérialiseur pour les sérialiser (les convertir en type de dictionnaire Python) puis les transmettre aux dataparamètres.

Description du paramètre :

  • data: Les données sérialisées préparées pour la réponse ;
  • status: code d'état, par défaut 200 ;
  • template_name: Nom du modèle, s'il est utilisé, HTMLRendereril doit être spécifié ;
  • headers: Dictionnaire utilisé pour stocker les informations d'en-tête de réponse ;
  • content_type: Le Content-Type des données de réponse, généralement ce paramètre n'a pas besoin d'être transmis, et le framework REST définira ce paramètre en fonction du type de données requis par le front-end.

1.1.2.2 Propriétés de l'objet de réponse

Utilisez moins de travail,

1).données

Données transmises à l'objet de réponse après la sérialisation mais pas encore rendues.

2).status_code

Numéro de code d'état

3).contenu

Données de réponse après le traitement du rendu

1.1.2.3 Code d'état

Afin de faciliter la configuration des codes d'état, le framework REST rest_framework.statusfournit des constantes des codes d'état http courants dans le module.

1) Notification d'informations - 1xx
HTTP_100_CONTINUE
HTTP_101_SWITCHING_PROTOCOLS
2) Succès - 2xx
HTTP_200_OK
HTTP_201_CREATED
HTTP_202_ACCEPTED
HTTP_203_NON_AUTHORITATIVE_INFORMATION
HTTP_204_NO_CONTENT
HTTP_205_RESET_CONTENT
HTTP_206_PARTIAL_CONTENT
HTTP_207_MULTI_STATUS
3) Redirection - 3xx
HTTP_300_MULTIPLE_CHOICES
HTTP_301_MOVED_PERMANENTLY
HTTP_302_FOUND
HTTP_303_SEE_OTHER
HTTP_304_NOT_MODIFIED
HTTP_305_USE_PROXY
HTTP_306_RESERVED
HTTP_307_TEMPORARY_REDIRECT
4) Erreur client - 4xx
HTTP_400_BAD_REQUEST
HTTP_401_UNAUTHORIZED
HTTP_402_PAYMENT_REQUIRED
HTTP_403_FORBIDDEN
HTTP_404_NOT_FOUND
HTTP_405_METHOD_NOT_ALLOWED
HTTP_406_NOT_ACCEPTABLE
HTTP_407_PROXY_AUTHENTICATION_REQUIRED
HTTP_408_REQUEST_TIMEOUT
HTTP_409_CONFLICT
HTTP_410_GONE
HTTP_411_LENGTH_REQUIRED
HTTP_412_PRECONDITION_FAILED
HTTP_413_REQUEST_ENTITY_TOO_LARGE
HTTP_414_REQUEST_URI_TOO_LONG
HTTP_415_UNSUPPORTED_MEDIA_TYPE
HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE
HTTP_417_EXPECTATION_FAILED
HTTP_422_UNPROCESSABLE_ENTITY
HTTP_423_LOCKED
HTTP_424_FAILED_DEPENDENCY
HTTP_428_PRECONDITION_REQUIRED
HTTP_429_TOO_MANY_REQUESTS
HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE
HTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS
5) Erreur de serveur - 5xx
HTTP_500_INTERNAL_SERVER_ERROR
HTTP_501_NOT_IMPLEMENTED
HTTP_502_BAD_GATEWAY
HTTP_503_SERVICE_UNAVAILABLE
HTTP_504_GATEWAY_TIMEOUT
HTTP_505_HTTP_VERSION_NOT_SUPPORTED
HTTP_507_INSUFFICIENT_STORAGE
HTTP_511_NETWORK_AUTHENTICATION_REQUIRED

Afin de faciliter la démonstration, nous créons une autre sous-application pour afficher les connaissances du contenu dans la vue fournie par drf.

python manage.py startapp demo

Enregistrer les sous-applications

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'students',
    'sers',    # 序列化器
    "school",  # 序列化器嵌套
    'req',     # 请求与响应
    'demo',    # 视图
]

Routage général, code :

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('students/', include("students.urls")),
    path('sers/', include("sers.urls")),
    path('school/', include("school.urls")),
    path("req/", include("req.urls")),
    path("demo/", include("demo.urls")),
]

Routage sous-application, code :

from django.urls import path
from . import views

urlpatterns = [

]

1. Voir

Les principales fonctions des vues fournies par le framework Django REST :

  • Contrôler l'exécution du sérialiseur (vérifier, enregistrer, convertir les données)
  • Contrôler le fonctionnement des modèles de bases de données

1.2 Vue normale

Le framework REST fournit de nombreuses classes de base de vues communes et classes d'extension pour simplifier l'écriture des vues.

1.2.1 2 vues des classes de base

1.2.1.1 Classe de vue de base APIView

rest_framework.views.APIView

APIViewIl s'agit de la classe de base de toutes les classes de vues fournies par le framework REST et hérite de la Viewclasse parent de Django.

APIViewViewLa différence avec c'est que :

  • Ce qui est transmis à la méthode view est l' Requestobjet du framework REST, pas l' HttpRequesetobjet Django ;

  • La méthode view peut renvoyer l'objet framework REST Response, et la vue définira (rendu) les données de réponse dans un format qui répond aux attentes du front-end ;

  • Toutes APIExceptionles exceptions seront détectées et traitées dans un message de réponse dans un format approprié et renvoyées au client ;

    Toutes les exceptions dans la vue de Django sont affichées au format HTML

    La sous-classe APIVIew ou APIView de drf convertira automatiquement le format du message d'erreur en fonction de l'acceptation du client.

  • Une nouvelle méthode as_view est redéclarée et avant que dispatch() ne soit utilisé pour la distribution de route, le client demandeur sera authentifié, autorisé vérifié et contrôlé de flux.

En plus d'hériter des méthodes d'attribut d'origine de View, APIView ajoute également de nouveaux attributs de classe :

  • liste ou tuple d'authentification_classes , classe d'authentification d'identité
  • permissoin_classes liste ou tuple, classe de vérification des autorisations
  • liste throttle_classes ou ancêtre, classe de contrôle de flux

Dans APIViewce document, les méthodes conventionnelles de définition de vue de classe sont toujours utilisées pour implémenter get(), post() ou d'autres méthodes de requête.

Sérialiseur, démo/serializers.py, code :

from rest_framework import serializers
from stuapi.models import Student


class StudentModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = Student
        fields = "__all__"
        extra_kwargs = {
    
    
            "age": {
    
    
                "max_value": 25,
                "error_messages": {
    
    
                    "max_value": "年龄不能超过25岁!",
                }
            }
        }

Afficher le code :

from rest_framework import status
from rest_framework.views import APIView
from rest_framework.response import Response
from stuapi.models import Student
from .serializers import StudentModelSerializer
"""
GET  /demo/students/   获取所有学生信息    
POST /demo/students/   添加一个学生信息    

GET  /demo/students/<pk>   获取一个学生信息    
PUT  /demo/students/<pk>   更新一个学生信息    
DELETE  /demo/students/<pk>   删除一个学生信息    
"""


# Create your views here.
class StudentAPIView(APIView):
    def get(self,request):
        """获取所有学生信息"""
        # 1. 从数据库中读取学生列表信息
        student_list = Student.objects.all()
        # 2. 实例化序列化器,获取序列化对象
        serializer = StudentModelSerializer(instance=student_list, many=True)

        # 3. 转换数据并返回给客户端
        return Response(serializer.data)

    def post(self,request):
        """添加一条数据"""
        # 1. 获取客户端提交的数据,实例化序列化器,获取序列化对象
        serializer = StudentModelSerializer(data=request.data)

        # 2. 反序列化[验证数据、保存数据到数据库]
        serializer.is_valid(raise_exception=True)
        serializer.save()

        # 3. 返回新增的模型数据给客户单
        return Response(serializer.data, status=status.HTTP_201_CREATED)


class StudentInfoAPIView(APIView):
    def get(self,request, pk):
        """获取一条数据"""
        # 1. 使用pk作为条件获取模型对象
        try:
            student = Student.objects.get(pk=pk)
        except Student.DoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)

        # 2. 序列化
        serializer = StudentModelSerializer(instance=student)

        # 3. 返回结果
        return Response(serializer.data)

    def put(self,request,pk):
        """更新数据"""
        # 1. 使用pk作为条件获取模型对象
        try:
            student = Student.objects.get(pk=pk)
        except Student.DoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)

        # 2. 获取客户端提交的数据
        serializer = StudentModelSerializer(instance=student, data=request.data)

        # 3. 反序列化[验证数据和数据保存]
        serializer.is_valid(raise_exception=True)
        serializer.save()

        # 4. 返回结果
        return Response(serializer.data, status=status.HTTP_201_CREATED)

    def delete(self,request,pk):
        """删除数据"""
        # 1. 根据PK值获取要删除的数据并删除
        try:
            Student.objects.get(pk=pk).delete()
        except Student.DoesNotExist:
            pass

        # 2. 返回结果
        return Response(status=status.HTTP_204_NO_CONTENT)

Code de routage :

from django.urls import path, re_path
from . import views

urlpatterns = [
    path("students/", views.StudentAPIView.as_view()),
    re_path("^students/(?P<pk>\d+)/$", views.StudentInfoAPIView.as_view()),
]

1.2.1.2 GenericAPIView [classe de vue générique]

La fonction principale de la classe general view est d' extraire le code unique dans la view , ce qui rend le code de la méthode view plus général et abrège commodément le code général.

rest_framework.generics.GenericAPIView

Hérité de APIView, il ajoute principalement des méthodes pour faire fonctionner les sérialiseurs et les requêtes de base de données. Sa fonction est de fournir un support de méthode pour l'exécution de la classe d'extension Mixin ci-dessous. Habituellement, lorsqu'il est utilisé, il peut être associé à une ou plusieurs classes d'extension Mixin.

Propriétés et méthodes fournies par le sérialiseur

  • Les attributs:

    • serializer_class spécifie la classe de sérialiseur utilisée par la vue
  • méthode:

    • get_serializer_class(soi)

      Lorsque plusieurs sérialiseurs sont appelés dans une classe de vue, la méthode de vue peut exécuter différents objets de sérialiseur en renvoyant différents noms de classe de sérialiseur dans la méthode get_serializer_class via un jugement conditionnel.

      Renvoie la classe du sérialiseur, qui est renvoyée par défaut serializer_classet peut être remplacée, par exemple :

      class Student2GenericAPIView(GenericAPIView):
          # 整个视图类只使用一个序列化器的情况
          # serializer_class = StudentModelSerializert
          # 整个视图类中使用多个序列化器的情况
          def get_serializer_class(self):
            if self.request.method.lower() == "put":
                  return StudentModelSerializer
            else:
                  return Student2ModelSerializer
      
          queryset = Student.objects
      
          def get(self, request, pk):
              """获取一个模型信息"""
              serializer = self.get_serializer(instance=self.get_object())
              return Response(serializer.data)
      
          def put(self, request, pk):
              """更新一个模型信息"""
              serializer = self.get_serializer(instance=self.get_object(), data=request.data)
              serializer.is_valid(raise_exception=True)
              serializer.save()
              return Response(serializer.data)
      
    • get_serializer(soi, *args, **kwargs)

      Renvoie l'objet sérialiseur,qui est principalement utilisé par les classes d'extension Mixin.Si nous voulons obtenir l'objet sérialiseur dans la vue,nous pouvons également appeler cette méthode directement.

      Notez que lorsque cette méthode fournit l'objet sérialiseur,elle ajoutera trois données à l'attribut de contexte de l'objet sérialiseur :requête,format et vue.Ces trois objets de données peuvent être utilisés lors de la définition du sérialiseur.

      • demander l'objet de requête de la vue actuelle
      • viewL'objet de type vue actuellement demandé
      • format Le format de données qui devrait être renvoyé par la requête actuelle

Propriétés et méthodes fournies pour les requêtes de base de données

  • Les attributs:

    • queryset spécifie l'ensemble de requêtes de données utilisé
  • méthode:

    • get_queryset(soi)

      L'ensemble de requêtes utilisé par la vue de retour est principalement utilisé par la classe d'extension Mixin et constitue la base pour obtenir des données pour la vue de liste et la vue détaillée. L' querysetattribut de retour par défaut peut être remplacé, par exemple :

      def get_queryset(self):
          user = self.request.user
          return user.accounts.all()
      
    • get_object (soi)

      Renvoie l'objet de données de classe de modèle requis pour la vue détaillée, qui est principalement utilisé par les classes d'extension Mixin.

      Cette méthode peut être appelée dans la vue pour obtenir l'objet de classe modèle avec des informations détaillées.

      Si l'objet de classe de modèle auquel les détails ont accès n'existe pas, 404 sera renvoyé.

      Cette méthode utilisera la méthode check_object_permissions fournie par APIView par défaut pour vérifier si l'objet actuel est autorisé à y accéder.

      Exemple:

      # url(r'^books/(?P<pk>\d+)/$', views.BookDetailView.as_view()),
      class BookDetailView(GenericAPIView):
          queryset = BookInfo.objects.all()
          serializer_class = BookInfoSerializer
      
          def get(self, request, pk):
              book = self.get_object() # get_object()方法根据pk参数查找queryset中的数据对象
              serializer = self.get_serializer(book)
              return Response(serializer.data)
      

Autres propriétés pouvant être définies

  • pagination_class spécifie la classe de contrôle de pagination
  • filter_backends spécifie le backend de contrôle de filtrage des données

Vue, code :

"""
APIView中的api接口代码,除了部分涉及到调用模型和序列化器的代码以外,其他代码几乎都是固定写法。
所以,当我们将来针对增删查改的通用api接口编写时,完全可以基于原有的代码进行复用,
那么,drf也考虑到了这个问题,所以提供了一个GenericAPIView(通用视图类),让我们可以把接口中独特的代码单独提取出来作为属性存在。
rest_framework.generics.GenericAPIView是APIView的子类,在APIView的基础上进行属性扩展提供了2个属性,4个方法,方便我们针对通用接口进行编写。
"""
"""GenericAPIView 通用视图类"""
from rest_framework.generics import GenericAPIView


class StudentGenericAPIView(GenericAPIView):
    queryset = Student.objects.all()
    serializer_class = StudentModelSerializer
    def get(self,request):
        """获取所有数据"""
        # 1. 从数据库中读取模型列表信息
        queryset = self.get_queryset()  # GenericAPIView提供的get_queryset
        # 2. 序列化
        serializer = self.get_serializer(instance=queryset, many=True)

        # 3. 转换数据并返回给客户端
        return Response(serializer.data)

    def post(self,request):
        """添加一个数据"""
        # 1. 获取客户端提交的数据,实例化序列化器,获取序列化对象
        serializer = self.get_serializer(data=request.data)

        # 2. 反序列化[验证数据、保存数据到数据库]
        serializer.is_valid(raise_exception=True)
        serializer.save()

        # 3. 返回新增的模型数据给客户单
        return Response(serializer.data, status=status.HTTP_201_CREATED)


class StudentInfoGenericAPIView(GenericAPIView):
    queryset = Student.objects.all()
    serializer_class = StudentModelSerializer
    def get(self,request,pk):
        """获取一个数据"""
        # 1. 使用pk作为条件获取模型对象
        instance = self.get_object()

        # 2.序列化
        serializer = self.get_serializer(instance=instance)

        # 3. 返回结果
        return Response(serializer.data)

    def put(self, request, pk):
        """更新一个数据"""
        # 1. 使用pk作为条件获取模型对象
        instance = self.get_object()

        # 2. 获取客户端提交的数据
        serializer = self.get_serializer(instance=instance, data=request.data)

        # 3. 反序列化[验证数据和数据保存]
        serializer.is_valid(raise_exception=True)
        serializer.save()

        # 4. 返回结果
        return Response(serializer.data, status=status.HTTP_201_CREATED)

    def delete(self,request,pk):
        """删除一个数据"""
        # 1. 根据PK值获取要删除的数据并删除
        self.get_object().delete()

        # 2. 返回结果
        return Response(status=status.HTTP_204_NO_CONTENT)

Classe de sérialiseur :

from rest_framework import serializers
from stuapi.models import Student


class StudentModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = Student
        fields = "__all__"
        extra_kwargs = {
    
    
            "age": {
    
    
                "max_value": 25,
                "error_messages": {
    
    
                    "max_value": "年龄不能超过25岁!",
                }
            }
        }

Code de routage :

from django.urls import path, re_path
from . import views

urlpatterns = [
    # APIView
    path("students/", views.StudentAPIView.as_view()),
    re_path("^students/(?P<pk>\d+)/$", views.StudentInfoAPIView.as_view()),

    # GenericAPIView
    path("students2/", views.StudentGenericAPIView.as_view()),
    re_path("^students2/(?P<pk>\d+)/$", views.StudentInfoGenericAPIView.as_view()),
]

1.2.2 Classes d'extension à 5 vues

Également appelé mix-ins.

effet:

Fournit la mise en œuvre de plusieurs processus de traitement de vues back-end (ajout, suppression, modification et requête de ressources de données). Si la vue à écrire appartient à ces cinq types, la vue peut réutiliser le code en héritant de la classe d'extension correspondante, réduisant ainsi la code écrit par soi-même.quantité.

Ces cinq classes d'extension doivent être associées à la classe de base de vue universelle GenericAPIView, car l'implémentation des cinq classes d'extension doit appeler les méthodes de sérialisation et de requête de base de données fournies par GenericAPIView.

1)ListModelMixin

La classe d'extension de vue de liste fournit list(request, *args, **kwargs)des méthodes pour implémenter rapidement la vue de liste et renvoie un code d'état 200.

La méthode de liste de Mixin filtrera et pagine les données.

Code source:

class ListModelMixin(object):
    """
    List a queryset.
    """
    def list(self, request, *args, **kwargs):
        # 过滤
        queryset = self.filter_queryset(self.get_queryset())
        # 分页
        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)
        # 序列化
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

Exemple:

from rest_framework.mixins import ListModelMixin,CreateModelMixin
class StudentMixinAPIView(GenericAPIView,ListModelMixin,CreateModelMixin):
    serializer_class = StudentModelSerializer
    queryset = Student.objects
    def get(self,request,*args,**kwargs):
        """获取所有模型信息"""
        return self.list(request,*args,**kwargs)

2)CréerModelMixin

Créez une classe d'extension de vue, fournissez create(request, *args, **kwargs)une méthode pour créer rapidement une vue de ressources et renvoyez un code d'état 201 en cas de succès.

Si le sérialiseur ne parvient pas à vérifier les données envoyées par le frontal, une erreur 400 est renvoyée.

Code source:

class CreateModelMixin(object):
    """
    Create a model instance.
    """
    def create(self, request, *args, **kwargs):
        # 获取序列化器
        serializer = self.get_serializer(data=request.data)
        # 验证
        serializer.is_valid(raise_exception=True)
        # 保存
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

    def perform_create(self, serializer):
        serializer.save()

    def get_success_headers(self, data):
        try:
            return {
    
    'Location': str(data[api_settings.URL_FIELD_NAME])}
        except (TypeError, KeyError):
            return {
    
    }

Afficher le code :

from rest_framework.mixins import ListModelMixin,CreateModelMixin
class StudentMixinAPIView(GenericAPIView,ListModelMixin,CreateModelMixin):
    serializer_class = StudentModelSerializer
    queryset = Student.objects
    def get(self,request,*args,**kwargs):
        """获取所有模型信息"""
        return self.list(request,*args,**kwargs)

    def post(self,request):
        """添加一个模型信息"""
        return self.create(request)

3)RécupérerModelMixin

La vue détaillée étend la classe et fournit retrieve(request, *args, **kwargs)des méthodes pour renvoyer rapidement un objet de données existant.

S'il existe, renvoyez 200, sinon renvoyez 404.

Code source:

class RetrieveModelMixin(object):
    """
    Retrieve a model instance.
    """
    def retrieve(self, request, *args, **kwargs):
        # 获取对象,会检查对象的权限
        instance = self.get_object()
        # 序列化
        serializer = self.get_serializer(instance)
        return Response(serializer.data)

Afficher le code :

from rest_framework.mixins import RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin
class Student1MixinAPIView(GenericAPIView,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin):
    serializer_class = StudentModelSerializer
    queryset = Student.objects
    def get(self,request,pk):
        """获取一个模型信息"""
        return self.retrieve(request,pk)

4)Mise à jourModelMixin

La classe d'extension de vue de mise à jour fournit update(request, *args, **kwargs)des méthodes pour mettre à jour rapidement un objet de données existant.

Il fournit également partial_update(request, *args, **kwargs)des méthodes pour implémenter des mises à jour locales.

200 est renvoyé avec succès. Lorsque le sérialiseur ne parvient pas à vérifier les données, une erreur 400 est renvoyée.

Code source:

class UpdateModelMixin(object):
    """
    Update a model instance.
    """
    def update(self, request, *args, **kwargs):
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data, partial=partial)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)

        if getattr(instance, '_prefetched_objects_cache', None):
            # If 'prefetch_related' has been applied to a queryset, we need to
            # forcibly invalidate the prefetch cache on the instance.
            instance._prefetched_objects_cache = {
    
    }

        return Response(serializer.data)

    def perform_update(self, serializer):
        serializer.save()

    def partial_update(self, request, *args, **kwargs):
        kwargs['partial'] = True
        return self.update(request, *args, **kwargs)

Afficher le code :

from rest_framework.mixins import RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin
class Student1MixinAPIView(GenericAPIView,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin):
    serializer_class = StudentModelSerializer
    queryset = Student.objects
    def get(self,request,pk):
        """获取一个模型信息"""
        return self.retrieve(request,pk)

    def put(self,request,pk):
        """更新一个模型信息"""
        return self.update(request,pk)

5)DestroyModelMixin

La classe d'extension de vue Supprimer fournit destroy(request, *args, **kwargs)des méthodes pour supprimer rapidement un objet de données existant.

Renvoie 204 en cas de succès, 404 s'il n'est pas présent.

Code source:

class DestroyModelMixin(object):
    """
    Destroy a model instance.
    """
    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        self.perform_destroy(instance)
        return Response(status=status.HTTP_204_NO_CONTENT)

    def perform_destroy(self, instance):
        instance.delete()

Afficher le code :

from rest_framework.mixins import RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin
class Student1MixinAPIView(GenericAPIView,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin):
    serializer_class = StudentModelSerializer
    queryset = Student.objects
    def get(self,request,pk):
        """获取一个模型信息"""
        return self.retrieve(request,pk)

    def put(self,request,pk):
        """更新一个模型信息"""
        return self.update(request,pk)

    def delete(self,request,pk):
        """删除一个模型信息"""
        return self.destroy(request,pk)

Le code global utilise GenericAPIView combiné à la classe d'extension de vue pour implémenter 5 interfaces API de base.

"""
使用drf内置的模型扩展类[混入类]结合GenericAPIView实现通用视图方法的简写操作
from rest_framework.mixins import ListModelMixin   获取多条数据,返回响应结果    list
from rest_framework.mixins import CreateModelMixin 添加一条数据,返回响应结果    create
from rest_framework.mixins import RetrieveModelMixin 获取一条数据,返回响应结果  retrieve
from rest_framework.mixins import UpdateModelMixin 更新一条数据,返回响应结果    update(更新全部字段)和partial_update(更新单个或部分字段,例如修改密码,修改头像)
from rest_framework.mixins import DestroyModelMixin 删除一条数据,返回响应结果   destroy
"""
from rest_framework.mixins import ListModelMixin, CreateModelMixin


class StudentMixinView(GenericAPIView, ListModelMixin, CreateModelMixin):
    queryset = Student.objects.all()
    serializer_class = StudentModelSerializer
    def get(self,request):
        """获取所有数据"""
        return self.list(request)

    def post(self,request):
        """添加一条数据"""
        return self.create(request)


from rest_framework.mixins import RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin

class StudentInfoMixinView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
    queryset = Student.objects.all()
    serializer_class = StudentModelSerializer

    def get(self,request,pk):
        return self.retrieve(request, pk=pk)

    def put(self,request, pk):
        return self.update(request, pk=pk)

    def delete(self,request, pk):
        return self.destroy(request, pk=pk)

Sérialiseur, code :

from rest_framework import serializers
from stuapi.models import Student


class StudentModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = Student
        fields = "__all__"
        extra_kwargs = {
    
    
            "age": {
    
    
                "max_value": 25,
                "error_messages": {
    
    
                    "max_value": "年龄不能超过25岁!",
                }
            }
        }

Code de routage :

from django.urls import path, re_path
from . import views

urlpatterns = [
    # APIView
    path("students/", views.StudentAPIView.as_view()),
    re_path("^students/(?P<pk>\d+)/$", views.StudentInfoAPIView.as_view()),

    # GenericAPIView
    path("students2/", views.StudentGenericAPIView.as_view()),
    re_path("^students2/(?P<pk>\d+)/$", views.StudentInfoGenericAPIView.as_view()),

    # GenericAPIView + mixins
    path("students3/", views.StudentMixinView.as_view()),
    re_path("^students3/(?P<pk>\d+)/$", views.StudentInfoMixinView.as_view()),
]

1.2.3 9 vues des sous-classes

1)CréerAPIView

La méthode post est fournie et la méthode create est appelée en interne.

Hérité de : GenericAPIView, CreateModelMixin

2)ListeAPIView

La méthode get est fournie et la méthode list est appelée en interne

Hérité de : GenericAPIView, ListModelMixin

3)RécupérerAPIView

La méthode get est fournie et la méthode retrieve est appelée en interne

Hérité de : GenericAPIView, RetrieveModelMixin

4)DestoryAPIView

La méthode delete est fournie et la méthode destroy est appelée en interne.

Hérité de : GenericAPIView, DestoryModelMixin

5)Mise à jourAPIView

Fournit les méthodes put et patch, et appelle les méthodes update et partial_update en interne

Hérité de : GenericAPIView, UpdateModelMixin

6)ListCreateAPIView

Fournit des méthodes get et post, ainsi qu'une liste d'appels et des méthodes de création en interne

Hérité de : GenericAPIView, ListModelMixin, CreateModelMixin

7)RécupérerUpdateAPIView

Fournit des méthodes get, put et patch

Hérité de : GenericAPIView, RetrieveModelMixin, UpdateModelMixin

8)RécupérerDestoryAPIView

Fournir des méthodes d'obtention et de suppression

Hérité de : GenericAPIView, RetrieveModelMixin, DestoryModelMixin

9)RécupérerUpdateDestoryAPIView

Fournit des méthodes get, put, patch, delete

Description : GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestoryModelMixin

Afficher le code :


"""
上面的接口代码还可以继续更加的精简,drf在使用GenericAPIView和Mixins进行组合以后,还提供了视图子类。
视图子类,提供了各种的视图方法调用mixins操作

    ListAPIView = GenericAPIView + ListModelMixin         获取多条数据的视图方法
    CreateAPIView = GenericAPIView + CreateModelMixin     添加一条数据的视图方法
    RetrieveAPIView = GenericAPIView + RetrieveModelMixin 获取一条数据的视图方法
    UpdateAPIView = GenericAPIView + UpdateModelMixin     更新一条数据的视图方法
    DestroyAPIView = GenericAPIView + DestroyModelMixin   删除一条数据的视图方法
组合视图子类
    ListCreateAPIView = ListAPIView + CreateAPIView
    RetrieveUpdateAPIView = RetrieveAPIView + UpdateAPIView
    RetrieveDestroyAPIView = RetrieveAPIView + DestroyAPIView
    RetrieveUpdateDestroyAPIView = RetrieveAPIView + UpdateAPIView + DestroyAPIView
"""
# from rest_framework.generics import ListAPIView, CreateAPIView
from rest_framework.generics import ListCreateAPIView
class StudentListAPIView(ListCreateAPIView):
    queryset = Student.objects.all()
    serializer_class = StudentModelSerializer


# from rest_framework.generics import RetrieveAPIView, UpdateAPIView, DestroyAPIView
# from rest_framework.generics import RetrieveUpdateAPIView, DestroyAPIView
# from rest_framework.generics import RetrieveDestroyAPIView, UpdateAPIView
from rest_framework.generics import RetrieveUpdateDestroyAPIView # 四行代码一样意思
class StudentInfoAPIView(RetrieveUpdateDestroyAPIView):
    queryset = Student.objects.all()
    serializer_class = StudentModelSerializer

Sérialiseur, code :

from rest_framework import serializers
from school.models import Student
class  StudentModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = Student
        fields = "__all__"

Routage, code :

from django.urls import path
from . import views

urlpatterns = [
    path("s1/", views.StudentList1APIView.as_view()),
    path("s1/<int:pk>/", views.StudentInfo1APIView.as_view()),
    path("s2/", views.StudentList2GenericAPIView.as_view()),
    path("s2/<int:pk>/", views.StudentInfo2GenericAPIView.as_view()),
    path("s3/", views.StudentList3GenericAPIView.as_view()),
    path("s3/<int:pk>/", views.StudentInfo3GenericAPIView.as_view()),
    path("s4/", views.StudentListAPIView.as_view()),
    path("s4/<int:pk>/", views.StudentInfoAPIView.as_view()),
]

1.3 Ensemble de vues

À l'aide de ViewSet, une série de logiques de code liées à la vue et d'actions de requête http associées peuvent être encapsulées dans une classe :

  • list() fournit un ensemble de données
  • retrieve() fournit une seule donnée
  • create() crée des données
  • update() enregistre les données
  • destroy() supprimer des données

La classe d'ensemble de vues ViewSet ne limite plus les noms de méthodes d'affichage à autoriser uniquement get(), post(), etc., mais permet aux développeurs de définir des noms de méthodes personnalisés en fonction de leurs propres besoins, tels que list(), create(), etc. . , puis utilisez http et ces noms de méthodes d'affichage dans le routage pour effectuer des appels de liaison.

L'ensemble de vues fera uniquement correspondre l'action à la méthode de requête spécifique lors de l'utilisation de la méthode as_view() . comme:

"""
针对视图子类这种写法写法虽然已经省略了http请求,但是在开发通用5个api接口时,还是会出现需要2个类来实现5个接口的情况。
这主要的原因是2点:
1. 获取多条数据与获取一条数据的http请求重复了。在django中依赖于请求方法来响应不同的http请求
2. 部分接口需要pk值作为url地址。

drf为了解决上面的2个问题,提供了视图集和路由集。
视图集就可以帮我们实现一个视图类响应多种重复的http请求
路由集就可以帮我们实现自动根据不同的视图方法来生成不同参数的路由地址。
from rest_framework.viewsets import ViewSet  # ViewSet是APIView的子类,是所有drf中的视图集的父类
"""
from rest_framework.viewsets import ViewSet
class StudentViewSet(ViewSet):
    # ViewSet不再需要我们使用http请求作为视图方法了。当然,如果你还希望使用http作为视图方法也可以。
    def get_all(self,request):
        queryset = Student.objects.all()
        # 实例化序列化器对象
        serializer = StudentModelSerializer(instance=queryset, many=True)
        # 返回序列化后的数据列表
        return Response(serializer.data)

    def create(self,request):
        """添加一条数据"""
        # 接收客户端提交的数据
        # 1. 实例化序列化器对象,获取来自客户端的请求数据作为参数
        serializer = StudentModelSerializer(data=request.data)
        # 2. 反序列化, 调用is_valid进行数据校验
        serializer.is_valid(raise_exception=True)
        # 3. 反序列化, 调用save保存数据
        serializer.save()
        # 4. 序列化,把新增后的模型对象返回给客户端
        return Response(serializer.data, status=status.HTTP_201_CREATED)

    def get_one(self,request,pk):
        try:
            # 模型操作,根据pk值获取指定数据
            instance = Student.objects.get(pk=pk)
            # 实例化序列化器对象
            serializer = StudentModelSerializer(instance=instance)
            # 返回序列化后的数据
            return Response(serializer.data)
        except Student.DoesNotExist:
            return Response({
    
    "msg":"当前学生不存在!"}, status=status.HTTP_404_NOT_FOUND)


    def put(self,request,pk):
        """更新一条数据"""
        try:
            # 获取要更新的模型对象
            instance = Student.objects.get(pk=pk)
            # 实例化序列化器对象,参数分别是本次更新的模型对象以及接受来自客户端提交的更新数据
            serializer = StudentModelSerializer(instance=instance, data=request.data)
            # 反序列化,验证数据
            serializer.is_valid(raise_exception=True)
            # 反序列化器,保存数据
            serializer.save()
            # 序列化,返回更新后的数据
            return Response(serializer.data)

        except Student.DoesNotExist:
            return Response({
    
    "msg": "当前学生不存在!"}, status=status.HTTP_404_NOT_FOUND)


    def delete(self,request,pk):
        """删除一条数据"""
        try:
            # 获取要更新的模型对象
            student = Student.objects.get(pk=pk)
            student.delete()
            return Response(status=status.HTTP_204_NO_CONTENT)
        except Student.DoesNotExist:
            return Response({
    
    "msg": "当前学生不存在!"}, status=status.HTTP_404_NOT_FOUND)

Lors de la configuration du routage, nous pouvons effectuer les opérations suivantes

from django.urls import path
from . import views

urlpatterns = [
    path("s1/", views.StudentList1APIView.as_view()),
    path("s1/<int:pk>/", views.StudentInfo1APIView.as_view()),
    path("s2/", views.StudentList2GenericAPIView.as_view()),
    path("s2/<int:pk>/", views.StudentInfo2GenericAPIView.as_view()),
    path("s3/", views.StudentList3GenericAPIView.as_view()),
    path("s3/<int:pk>/", views.StudentInfo3GenericAPIView.as_view()),
    path("s4/", views.StudentListAPIView.as_view()),
    path("s4/<int:pk>/", views.StudentInfoAPIView.as_view()),
    path("s5/", views.StudentViewSet.as_view(actions={
    
    "get":"get_all","post":"create"})),
    path("s5/<int:pk>/", views.StudentViewSet.as_view({
    
    "get":"get_one","put":"put","delete":"delete"})),
]

1.3.1 Classes parents d'ensembles de vues couramment utilisées

1)ViewSet

Hérité de APIViewet ViewSetMixin, sa fonction est fondamentalement similaire à APIView, fournissant l'authentification d'identité, la vérification des autorisations, la gestion du trafic, etc.

ViewSet implémente principalement le traitement de mappage du dictionnaire {"http request": "view method"} transmis lors de l'appel de as_view(), tel que {'get':'list'}, en héritant de ViewSetMixin.

Dans ViewSet, aucune méthode d'action n'est fournie et nous devons implémenter la méthode d'action nous-mêmes.

2)GenericViewSet

Hérité de GenericAPIView et ViewSetMixin, il rend le code de vue de l'ensemble de vues plus général et extrait le code unique en tant qu'attribut de la classe de vue.

Il n'est généralement pas pratique d'utiliser ViewSet, car les méthodes list, retrieve, create, update, destroy et autres doivent être écrites par vous-même, et ces méthodes ont les mêmes noms que les méthodes fournies par la classe d'extension Mixin mentionnée précédemment, nous peut les dupliquer en héritant de la classe d'extension Mixin. Utilisez ces méthodes sans écrire les vôtres. Mais la classe d'extension Mixin dépend de and GenericAPIView, elle doit donc toujours être héritée GenericAPIView.

GenericViewSet nous aide à réaliser ce travail d'héritage. Il hérite GenericAPIViewet ViewSetMixintout en implémentant le traitement de mappage du dictionnaire (tel que) transmis lors de l'appel de as_view() {'get':'list'}, il fournit également GenericAPIViewdes méthodes de base qui peuvent être directement utilisées avec les classes d'extension Mixin.

Afficher le code :


from rest_framework.viewsets import GenericViewSet

class StudentGenericViewSet(GenericViewSet):
    queryset = Student.objects.all()
    serializer_class = StudentModelSerializer
    def list(self,request):
        """获取多条数据"""
        # 获取模型对象列表,实例化序列化器对象
        serializer = self.get_serializer(instance=self.get_queryset(), many=True)
        # 返回序列化后的数据列表
        return Response(serializer.data)

    def post(self,request):
        """添加一条数据"""
        serializer = self.get_serializer(data=request.data)
        # 2. 反序列化, 调用is_valid进行数据校验
        serializer.is_valid(raise_exception=True)
        # 3. 反序列化, 调用save保存数据
        serializer.save()
        # 4. 序列化,把新增后的模型对象返回给客户端
        return Response(serializer.data, status=status.HTTP_201_CREATED)

    def retrieve(self, request, pk):
        """获取一条数据"""
        # 模型操作,根据pk值获取指定数据
        instance = self.get_object() # 上面代码的简写,而且对错误进行格式处理
        # 实例化序列化器对象
        serializer = self.get_serializer(instance=instance)
        # 返回序列化后的数据列表
        return Response(serializer.data)

    def update(self, request, pk):
        """更新一条数据"""
        instance = self.get_object() # 不要漏了pk参数
        serializer = self.get_serializer(instance=instance, data=request.data)
        # 反序列化,验证数据
        serializer.is_valid(raise_exception=True)
        # 反序列化器,保存数据
        serializer.save()
        # 序列化,返回更新后的数据
        return Response(serializer.data)

    def delete(self, request, pk):
        instance = self.get_object()
        instance.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

Code de routage :

from django.urls import path
from . import views

urlpatterns = [
    path("s1/", views.StudentList1APIView.as_view()),
    path("s1/<int:pk>/", views.StudentInfo1APIView.as_view()),
    path("s2/", views.StudentList2GenericAPIView.as_view()),
    path("s2/<int:pk>/", views.StudentInfo2GenericAPIView.as_view()),
    path("s3/", views.StudentList3GenericAPIView.as_view()),
    path("s3/<int:pk>/", views.StudentInfo3GenericAPIView.as_view()),
    path("s4/", views.StudentListAPIView.as_view()),
    path("s4/<int:pk>/", views.StudentInfoAPIView.as_view()),
    # path("url地址/", views.StudentViewSet.as_view({"http请求方法名":"视图方法名","http请求方法名":"视图方法名",....})),
    path("s5/", views.StudentViewSet.as_view({
    
    "get":"get_all","post":"create"})),
    path("s5/<int:pk>/", views.StudentViewSet.as_view({
    
    "get":"get_one","put":"put","delete":"delete"})),
    path("s6/", views.StudentGenericViewSet.as_view({
    
    "get":"list","post":"post"})),
    path("s6/<int:pk>/", views.StudentGenericViewSet.as_view({
    
    "get":"retrieve","put":"update","delete":"delete"})),
]

Rassemblez les classes d'extension de modèle que nous avons apprises ci-dessus pour implémenter des opérations, des vues et du code abrégés :

"""
GenericViewSet结合Mixins的混入类,直接视图接口,这次连视图子类都不需要了。
ViewSet
GenericViewSet
ModelViewSet = GenericViewSet + ListModelMixin + CreateModelMixin + UpdateModelMixin + RetrieveModelMixin + DestroyModelMixin
ReadOnlyModelViewSet = GenericViewSet + ListModelMixin + RetrieveModelMixin
"""
from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import ListModelMixin, CreateModelMixin, UpdateModelMixin, RetrieveModelMixin, DestroyModelMixin
class StudentMixinViewSet(GenericViewSet, ListModelMixin, CreateModelMixin, UpdateModelMixin, RetrieveModelMixin, DestroyModelMixin):
    queryset = Student.objects.all()
    serializer_class = StudentModelSerializer

Routage, code :

from django.urls import path
from . import views

urlpatterns = [
    path("s1/", views.StudentList1APIView.as_view()),
    path("s1/<int:pk>/", views.StudentInfo1APIView.as_view()),
    path("s2/", views.StudentList2GenericAPIView.as_view()),
    path("s2/<int:pk>/", views.StudentInfo2GenericAPIView.as_view()),
    path("s3/", views.StudentList3GenericAPIView.as_view()),
    path("s3/<int:pk>/", views.StudentInfo3GenericAPIView.as_view()),
    path("s4/", views.StudentListAPIView.as_view()),
    path("s4/<int:pk>/", views.StudentInfoAPIView.as_view()),
    # path("url地址/", views.StudentViewSet.as_view({"http请求方法名":"视图方法名","http请求方法名":"视图方法名",....})),
    path("s5/", views.StudentViewSet.as_view({
    
    "get":"get_all","post":"create"})),
    path("s5/<int:pk>/", views.StudentViewSet.as_view({
    
    "get":"get_one","put":"put","delete":"delete"})),
    path("s6/", views.StudentGenericViewSet.as_view({
    
    "get":"list","post":"post"})),
    path("s6/<int:pk>/", views.StudentGenericViewSet.as_view({
    
    "get":"retrieve","put":"update","delete":"delete"})),
    path("s7/", views.StudentMixinViewSet.as_view({
    
    "get":"list","post":"create"})),
    path("s7/<int:pk>/", views.StudentMixinViewSet.as_view({
    
    "get":"retrieve","put":"update","delete":"destroy"})),
]

3)ModelViewSet

Hérité de GenericViewSet, inclut également ListModelMixin, RetrieveModelMixin, CreateModelMixin, UpdateModelMixin, DestoryModelMixin.

4)ReadOnlyModelViewSet

Hérité de GenericViewSet, notamment ListModelMixin et RetrieveModelMixin.

Afficher le code :

"""
GenericViewSet结合Mixins的混入类,直接视图接口,这次连视图子类都不需要了。
ViewSet
GenericViewSet
ModelViewSet = GenericViewSet + ListModelMixin + CreateModelMixin + UpdateModelMixin + RetrieveModelMixin + DestroyModelMixin
ReadOnlyModelViewSet = GenericViewSet + ListModelMixin + RetrieveModelMixin
"""
from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import ListModelMixin, CreateModelMixin, UpdateModelMixin, RetrieveModelMixin, DestroyModelMixin
from rest_framework.viewsets import ModelViewSet # 万能视图集,5个接口的简写
from rest_framework.viewsets import ReadOnlyModelViewSet # 只读视图集,2个接口的简写
class StudentMixinViewSet(ModelViewSet):
    queryset = Student.objects.all()
    serializer_class = StudentModelSerializer

Code de routage :

from django.urls import path
from . import views

urlpatterns = [
    path("s1/", views.StudentList1APIView.as_view()),
    path("s1/<int:pk>/", views.StudentInfo1APIView.as_view()),
    path("s2/", views.StudentList2GenericAPIView.as_view()),
    path("s2/<int:pk>/", views.StudentInfo2GenericAPIView.as_view()),
    path("s3/", views.StudentList3GenericAPIView.as_view()),
    path("s3/<int:pk>/", views.StudentInfo3GenericAPIView.as_view()),
    path("s4/", views.StudentListAPIView.as_view()),
    path("s4/<int:pk>/", views.StudentInfoAPIView.as_view()),
    # path("url地址/", views.StudentViewSet.as_view({"http请求方法名":"视图方法名","http请求方法名":"视图方法名",....})),
    path("s5/", views.StudentViewSet.as_view({
    
    "get":"get_all","post":"create"})),
    path("s5/<int:pk>/", views.StudentViewSet.as_view({
    
    "get":"get_one","put":"put","delete":"delete"})),
    path("s6/", views.StudentGenericViewSet.as_view({
    
    "get":"list","post":"post"})),
    path("s6/<int:pk>/", views.StudentGenericViewSet.as_view({
    
    "get":"retrieve","put":"update","delete":"delete"})),
    path("s7/", views.StudentMixinViewSet.as_view({
    
    "get":"list","post":"create"})),
    path("s7/<int:pk>/", views.StudentMixinViewSet.as_view({
    
    "get":"retrieve","put":"update","delete":"destroy"})),
]

2. Routeurs

Pour ViewSet, en plus de spécifier manuellement la correspondance entre la méthode de requête et l'action, nous pouvons également utiliser des routeurs pour nous aider à implémenter rapidement les informations de routage. S'il s'agit d'un ensemble sans vue, il n'est pas nécessaire d'utiliser des routeurs d'ensemble de routage.

Le framework REST fournit deux routeurs, qui sont utilisés de la même manière. Le résultat est simplement un problème d'une adresse URL du répertoire racine en plus ou en moins.

  • Routeur simple
  • Routeur par défaut

2.1 Comment utiliser

1) Créez un objet routeur et enregistrez l'ensemble de vues, par exemple

from django.urls import path
from . import views

urlpatterns = [
    # 省略....
    # path("s7/", views.StudentMixinViewSet.as_view({"get":"list","post":"create"})),
    # path("s7/<int:pk>/", views.StudentMixinViewSet.as_view({"get":"retrieve","put":"update","delete":"destroy"})),
]

# 路由集的操作
from rest_framework.routers import DefaultRouter,SimpleRouter
router = DefaultRouter()
# 注册视图(访问前缀,视图集类,调用别名)
router.register("s7", views.StudentMixinViewSet, "s7")
# 把路由对象生成的视图集路由列表合并追加路由列表中
print(router.urls)
urlpatterns += router.urls

registre (préfixe, ensemble de vues, nom de base)

  • prefix Le préfixe de routage pour cet ensemble de vues
  • ensemble de vues
  • préfixe de nom de base de l'alias de routage

L'itinéraire formé par le code ci-dessus est le suivant :

url: ^s7/$                  basename: s7-list
url: ^s7/(?P<pk>[^/.]+)/$   basename: s7-detail

2) Il existe deux manières d'ajouter la liste de routage de l'ensemble de vues généré par l'objet de routage au routage de Django :

urlpatterns = [
    ...
]

urlpatterns += router.urls

ou

from django.urls import include,re_path
urlpatterns = [
    ...
    re_path('^', include(router.urls))
]

2.2 Déclaration d'actions supplémentaires dans l'ensemble de vues

Dans l'ensemble de vues, si vous souhaitez que Router nous aide automatiquement à générer des informations de routage pour les actions personnalisées, vous devez utiliser un rest_framework.decorators.actiondécorateur.

Le nom de la méthode décoré avec le décorateur d'action sera utilisé comme nom d'action, ce qui équivaut à lister et récupérer.

Le décorateur d'action peut recevoir deux paramètres :

  • méthodes : déclare la méthode de requête correspondant à l'action, passée dans une liste

  • détail : déclare si le chemin de l'action correspond à une seule ressource

    路由前缀/<pk>/action方法名/
    
    • True signifie que le format du chemin estxxx/<pk>/action方法名/
    • False signifie que le format du chemin estxxx/action方法名/
  • url_path : déclare le suffixe de routage de l'action.

Exemple:

from rest_framework.viewsets import ModelViewSet # 万能视图集,5个接口的简写
from rest_framework.viewsets import ReadOnlyModelViewSet # 只读视图集,2个接口的简写
from rest_framework.decorators import action
class StudentMixinViewSet(ModelViewSet):
    queryset = Student.objects.all()
    serializer_class = StudentModelSerializer

    # 路由对象给视图集生成路由信息时,只会生成5个基本api接口,这主要是router只识别5个混入类的原因,
    # 而针对我们开发者自定义的视图方法,路由对象不会自动生成路由信息,
    # 所以下面这个login,如果希望被外界访问到,则必须通过action装饰器告诉路由对象要给它生成一个路由信息。
    @action(methods=["get","post"], detail=False, url_path="login")
    # action的参数
    # methods, 列表,指定允许哪些http请求方法可以访问当前视图方法
    # detail, 布尔值,告诉路由对象在生成路由信息时,是否要自动生成pk值,True表示需要,False表示不需要。
    # url_path,字符串,访问视图的url地址,如果不设置,则默认采用视图方法名作为访问后缀
    # http://127.0.0.1:8000/demo/s7/login/
    def login(self, request):
        """登录视图"""
        return Response({
    
    "msg":"登录成功"})

    @action(methods=["get"], detail=True, url_path="login/log")
    # http://127.0.0.1:8000/demo/s7/23/login/log/
    def login_log(self,request,pk):
        """用户登录历史记录"""
        # 视图集类中
        # 可以通过self.method获取本次客户端的http请求
        # 可以通过self.action获取本次客户端请求的视图方法名[ViewSet提供的]
        print(self.action) # login_log
        return Response({
    
    "msg": "用户登录历史记录"})

L'itinéraire formé par le routeur personnalisant automatiquement la méthode d'action pour cet ensemble de vues sera le suivant :

url: ^s7/login/$                      basename: s7-login
url: ^s7/(?P<pk>[^/.]+)/login/log/$   basename: s7-login-log

2.3 La façon dont le routeur forme l'URL

1) SimpleRouter (prefix="préfixe de routage", vuesset=classe viewset, basename="alias de routage")

[Le transfert de l'image du lien externe a échoué. Le site source peut avoir un mécanisme anti-sangsue. Il est recommandé de sauvegarder l'image et de la télécharger directement (img-gbax9nAn-1691197102533) (assets/SimpleRouter.png)]

2)Routeur par défaut

[Le transfert de l'image du lien externe a échoué. Le site source peut avoir un mécanisme anti-sangsue. Il est recommandé de sauvegarder l'image et de la télécharger directement (img-tRdBSVn1-1691197102534) (assets/DefaultRouter.png)]

La différence entre DefaultRouter et SimpleRouter est que DefaultRouter sera livré avec une vue racine d'API par défaut et renverra des données de réponse de lien hypertexte contenant toutes les vues de liste.

Je suppose que tu aimes

Origine blog.csdn.net/weixin_53909748/article/details/132115507
conseillé
Classement