djiango DRF的使用

djiango DRF的使用

  • 一 、初始 DRF序列化
      • 环境安装
      • 环境配置
      • 数据模型定义
      • 定义DRF序列化模型对象
  • 二 、DRF请求和响应
    • 请求对象(Request objects)
    • 响应对象(Response objects)
    • 状态码(Status codes)
    • 包装(wrapping)API视图
    • 组合在一起(灵活的FBV视图)
        • 路由设置
        • 测试
    • 给我们的网址添加可选的格式后缀(json、api)
  • 三 、DRF类视图使用进化史
    • 基于APIView
    • GenericAPIView
      • 视图配置:
      • 路由配置:
    • 基于mixins类
      • 视图配置:
      • 路由配置
    • mixins + GenericAPIView组合封装
      • 视图配置
      • 路由配置
      • 修改序列化器字段属性
    • ModelViewSet类视图
      • 路由配置
      • 视图配置
    • ReadOnlyModelViewSet
      • 导入和继承
      • 提供的默认操作方法
      • 序列化器(Serializer)的使用
      • URL配置
  • 四、DRF认证与权限
    • 一、Django REST Framework (DRF) 认证配置
      • 1. 基本认证(Basic Authentication)
      • 2.Session 认证(Session Authentication)
        • 获取 Session Cookie(模拟登录过程,因为基于 Session 认证需要有效的 Session)
      • 3.Token 认证(Token Authentication)
      • 4.JWT 认证(JSON Web Token Authentication)
        • 生成 JWT 令牌
        • 利用token进行访问book书籍信息
    • 二、DRF 权限配置
      • 基于用户认证的权限(IsAuthenticated)
      • 基于用户角色的权限(如 IsAdminUser 等)
      • 自定义权限类

一 、初始 DRF序列化

环境安装

pip install djangorestframework

环境配置

INSTALLED_APPS = ['rest_framework',
]

数据模型定义

from django.db import modelsclass Book(models.Model):title = models.CharField(max_length=200)author = models.CharField(max_length=100)publication_year = models.IntegerField()

定义DRF序列化模型对象

在books app应用下创建一个serializers序列化对象文件

from rest_framework import serializers
from .models import Bookclass BookSerializer(serializers.ModelSerializer):class Meta:model = Bookfields = ['title', 'author', 'publication_year']

二 、DRF请求和响应

从现在开始,我们将真正开始接触REST框架的核心。 我们来介绍几个基本的构建模块。

请求对象(Request objects)

REST框架引入了一个扩展了常规HttpRequest的Request对象,并提供了更灵活的请求解析。Request对象的核心功能是request.data属性,它与request.POST类似,但对于使用Web API更为有用

request.POST  # 只处理表单数据  只适用于'POST'方法
request.data  # 处理任意数据  适用于'POST','PUT'和'PATCH'方法

响应对象(Response objects)

REST框架还引入了一个Response对象,这是一种获取未渲染(unrendered)内容的TemplateResponse类型,并使用内容协商来确定返回给客户端的正确内容类型。

return Response(data)  # 渲染成客户端请求的内容类型。

状态码(Status codes)

在你的视图(views)中使用纯数字的HTTP 状态码并不总是那么容易被理解。而且如果错误代码出错,很容易被忽略。REST框架为status模块中的每个状态代码(如HTTP_400_BAD_REQUEST)提供更明确的标识符。使用它们来代替纯数字的HTTP状态码是个很好的方法。

from rest_framework import status

包装(wrapping)API视图

REST框架提供了两个可用于编写API视图的包装器(wrappers)。

  1. 用于基于函数视图的@api_view装饰器。
  2. 用于基于类视图的APIView类。

这些包装器提供了一些功能,例如确保你在视图中接收到Request实例,并将上下文添加到Response,以便可以执行内容协商。

包装器还提供了诸如在适当时候返回405 Method Not Allowed响应,并处理在使用格式错误的输入来访问request.data时发生的任何ParseError异常。

组合在一起(灵活的FBV视图)

好的,我们开始使用这些新的组件来写几个视图。

创建一个DrfApiView.py新视图文件,开始重构我们的视图。

from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .models import Book
from .serializers import BookSerializer@api_view(['GET', 'POST'])
def BookList(request):"""列出所有的book信息,或者创建一个新的book信息。"""if request.method == 'GET':# 声明查询对象book = Book.objects.all()# 声明序列化器 # 设置many=True,这样序列化器就知道要将查询集中的每一个Book对象分别进行序列化,并将它们组合成一个列表返回serializer = BookSerializer(book, many=True)return Response(serializer.data)elif request.method == 'POST':serializer = BookSerializer(data=request.data)# 创建对象前先检查# is_valid()方法首先会检查request.data中的数据是否符合BookSerializer定义的规则if serializer.is_valid():# 保存创建对象的数据到数据库中serializer.save()return Response(serializer.data, status=status.HTTP_201_CREATED)# 不符合定义规则返回报错信息return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
路由设置
from django.urls import path
from .DrfApiView import BookListurlpatterns = [path('books/', BookList, name='book_list'),
]
测试

get

post

改进一下DrfApiView.py,增加一个BooksDetail视图方法,实现get, put,delete 请求

@api_view(['GET', 'PUT', 'DELETE'])
def BooksDetail(request, pk):"""获取,更新或删除一个book实例。"""try:book = Book.objects.get(pk=pk)except book.DoesNotExist:return Response(status=status.HTTP_404_NOT_FOUND)if request.method == 'GET':# 注意这里根据pk返回单个book实例就不用加many=True了serializer = BookSerializer(book)return Response(serializer.data)# 更新book为pk的实例elif request.method == 'PUT':serializer = BookSerializer(book, data=request.data)if serializer.is_valid():serializer.save()return Response(serializer.data)return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)elif request.method == 'DELETE':book.delete()return Response(status=status.HTTP_204_NO_CONTENT)

路由配置:

from django.urls import path
from .DrfApiView import BookList, BooksDetailurlpatterns = [path('books/', BookList, name='book_list'),path('books_detail/<int:pk>/', BooksDetail, name='BooksDetail'),
]

测试:

给我们的网址添加可选的格式后缀(json、api)

为了充分利用我们的响应不再与单一内容类型连接,我们可以为API路径添加对格式后缀的支持。使用格式后缀给我们明确指定了给定格式的URL,这意味着我们的API将能够处理诸如http://example.com/api/items/4.json之类的URL。

像下面这样在这两个视图中添加一个format关键字参数。

from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .models import Book
from .serializers import BookSerializer@api_view(['GET', 'POST'])
def book_list(request, format=None):"""列出所有的book信息,或者创建一个新的book信息。"""if request.method == 'GET':book = Book.objects.all()serializer = BookSerializer(book, many=True)return Response(serializer.data)elif request.method == 'POST':serializer = BookSerializer(data=request.data)if serializer.is_valid():serializer.save()return Response(serializer.data, status=status.HTTP_201_CREATED)return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)@api_view(['GET', 'PUT', 'DELETE'])        
def book_detail(request, pk, format=None):pass

现在更新urls.py文件,给现有的URL后面添加一组format_suffix_patterns。

from django.urls import path, re_path
from rest_framework.urlpatterns import format_suffix_patterns
from .DrfApiView import book_list, book_detail
'''
re_path则用于需要使用正则表达式来定义复杂路由的场景,
'''
urlpatterns = [re_path(r'^books/$', book_list),re_path(r'^books/(?P<pk>[0-9]+)$', book_detail),
]urlpatterns = format_suffix_patterns(urlpatterns)

测试:

三 、DRF类视图使用进化史

Django drf 基于类的视图(CBV)

我们也可以使用基于类的视图编写我们的API视图,而不是基于函数的视图

基于APIView

books下新建一个DrfCbvView.py视图文件(基于APIView)

from rest_framework import status
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import Book
from .serializers import BookSerializer
from django.http import Http404
class BookList(APIView):"""列出所有的book或者创建一个新的book。"""def get(self, request, format=None):book = Book.objects.all()serializer = BookSerializer(book, many=True)return Response(serializer.data)def post(self, request, format=None):serializer = BookSerializer(data=request.data)if serializer.is_valid():serializer.save()return Response(serializer.data, status=status.HTTP_201_CREATED)return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)class BookDetail(APIView):"""检索,更新或删除一个Book。"""def get_object(self, pk):try:return Book.objects.get(pk=pk)except Book.DoesNotExist:raise Http404def get(self, request, pk, format=None):book = self.get_object(pk)serializer = BookSerializer(book)return Response(serializer.data)def put(self, request, pk, format=None):book = self.get_object(pk)serializer = BookSerializer(book, data=request.data)if serializer.is_valid():serializer.save()return Response(serializer.data)return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)def delete(self, request, pk, format=None):book = self.get_object(pk)book.delete()return Response(status=status.HTTP_204_NO_CONTENT)

urls.py

from django.urls import path, re_path
from .DrfCbvView import BookList, BookDetail
from rest_framework.urlpatterns import format_suffix_patterns
'''
re_path则用于需要使用正则表达式来定义复杂路由的场景,
'''
urlpatterns = [path('book/', BookList.as_view(), name='book-list'),re_path(r'book_detail/(?P<pk>\d+)/$', BookDetail.as_view(), name='book-detail')
]urlpatterns = format_suffix_patterns(urlpatterns)

GenericAPIView

GenericAPIView 继承自 APIView,它在 APIView 的基础上进一步抽象和封装了一些与数据库模型操作、序列化等相关的通用行为。

可以在子类中重写这个方法来动态返回查询集。这在需要根据不同条件(如用户权限、请求参数等)返回不同查询集时非常有用。默认情况下,它返回在类属性中定义的 queryset

get_serializer_class() 获取序列化的类

get_serializer() 获取序列化器对象

get_queryset() 获取查询集结果

get_object() 获取视图单一资源对象

视图配置:

from rest_framework import status
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from .models import Book
from .serializers import BookSerializer
class BookList(GenericAPIView):"""列出所有的book或者创建一个新的book。"""# 先定义查询对象集数据和序列化器queryset = Book.objects.all()serializer_class = BookSerializerdef get(self, request, *args, **kwargs):serializer = self.get_serializer(self.get_queryset(), many=True)return Response(serializer.data)def post(self, request, *args, **kwargs):serializer = self.get_serializer(data=request.data)if serializer.is_valid():serializer.save()return Response(serializer.data, status=status.HTTP_201_CREATED)return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)class BookDetail(GenericAPIView):"""检索,更新或删除一个Book示例。"""# 先定义查询对象集数据和序列化器queryset = Book.objects.all()serializer_class = BookSerializerdef get(self, request, pk, *args, **kwargs):book = self.get_object()serializer = self.get_serializer(book)return Response(serializer.data)def put(self, request, pk, *args, **kwargs):book = self.get_object()serializer = self.get_serializer(book, data=request.data)if serializer.is_valid():serializer.save()return Response(serializer.data)return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)def delete(self, request, pk, *args, **kwargs):book = self.get_object()book.delete()return Response(status=status.HTTP_204_NO_CONTENT)

路由配置:

from django.urls import path
from .DrfCbvView import BookList, BookDetail
'''
re_path则用于需要使用正则表达式来定义复杂路由的场景,
'''
urlpatterns = [path('book/', BookList.as_view(), name='book-list'),path('book_detail/<int:pk>/', BookDetail.as_view(), name='book-detail')
]

基于mixins类

(GenericAPIView进一步封装)

视图配置:

from rest_framework.generics import GenericAPIView
from .models import Book
from rest_framework import mixins
from .serializers import BookSerializerclass SnippetList(mixins.ListModelMixin,mixins.CreateModelMixin,GenericAPIView):queryset = Book.objects.all()serializer_class = BookSerializerdef get(self, request, *args, **kwargs):return self.list(request, *args, **kwargs)def post(self, request, *args, **kwargs):return self.create(request, *args, **kwargs)class SnippetDetail(mixins.RetrieveModelMixin,mixins.UpdateModelMixin,mixins.DestroyModelMixin,GenericAPIView):queryset = Book.objects.all()serializer_class = BookSerializerdef get(self, request, *args, **kwargs):return self.retrieve(request, *args, **kwargs)def put(self, request, *args, **kwargs):return self.update(request, *args, **kwargs)def delete(self, request, *args, **kwargs):return self.destroy(request, *args, **kwargs)

路由配置

from django.urls import path
from .DrfCbvView import BookList, BookDetail
'''
re_path则用于需要使用正则表达式来定义复杂路由的场景,
'''
urlpatterns = [path('book/', BookList.as_view(), name='book-list'),path('book_detail/<int:pk>/', BookDetail.as_view(), name='book-detail')
]

mixins + GenericAPIView组合封装

使用:在自定义类视图方法中,导入相应类方法参数后,只需要2步,定义查询对象和序列化器就行了。

from rest_framework.generics import …

ListCreateAPIView类(查看所有、创建对象的方法)

RetrieveUpdateAPIView类(全更新、部分更新对象的方法)

RetrieveDestroyAPIView类(删除、搜索单条数据的对象方法)

RetrieveUpdateDestroyAPIView类(全更新、部分更新、删除、搜索单条数据对象方法)

UpdateAPIView(更新对象方法)

DestroyAPIView(删除对象方法)

RetrieveAPIView (搜索查看单条数据对象方法)

ListAPIView(查看对象数据方法)

CreateAPIView(创建对象数据方法)

视图配置

from rest_framework import generics
from .models import Book
from .serializers import BookSerializerclass BookView(generics.ListCreateAPIView):queryset = Book.objects.all()serializer_class = BookSerializerclass BookDetailView(generics.RetrieveUpdateDestroyAPIView):queryset = Book.objects.all()serializer_class = BookSerializer

路由配置

from django.urls import path
from .DrfCbvView import BookView, BookDetailView
'''
re_path则用于需要使用正则表达式来定义复杂路由的场景,
'''
urlpatterns = [path('BookView/', BookView.as_view(), name='book-list'),path('BookDetailView/<int:pk>/', BookDetailView.as_view(), name='book-detail')
]

修改序列化器字段属性

修改下实现能部分更新字段信息, 实际项目中前端也会判断

from rest_framework import serializers
from .models import Bookclass BookSerializer(serializers.ModelSerializer):title = serializers.CharField(max_length=200)author = serializers.CharField(max_length=100)# 将允许为空的字段设置为required=False(如果业务逻辑允许这些字段为空)publication_year = serializers.IntegerField(required=False)class Meta:model = Bookfields = ['title', 'author', 'publication_year']

ModelViewSet类视图

GenericViewSet + mixins 的结合

作用: 它把所有方法(增删改查查)全部放在了一个类下

使用: 1. 在自定义类视图方法中,导入ModelViewSet类方法参数后,只需要2步,定义查询对象和序列化器就行了。

  1. url路由改为注册添加方式

from rest_framework.viewsets import ModelViewSet

路由配置

from django.urls import path,include
from rest_framework.routers import DefaultRouter
from .DrfCbvView import BookViewrouter = DefaultRouter()
'''
这里的books是 URL 前缀,BookView是视图集类。
DefaultRouter会根据视图集类中定义的方法(如list、retrieve、create、update、destroy)自动生成对应的 URL 模式。
这样,Router会自动为BookModelViewSet生成以下 URL 模式:books/:get获取Book所有对象的列表。books/<pk>/:get方法,用于获取单个Book对象(其中<pk>是Book对象的主键)。books/:用于创建新的Book对象(实际上是通过POST请求发送数据到books/这个 URL 来实现创建功能)。books/<pk>/:用于更新指定的Book对象(通过PUT或PATCH请求)。books/<pk>/:用于删除指定的Book对象(通过DELETE请求)。
'''
router.register('books', BookView)
urlpatterns = [# path('', include(router.urls)),
]
# 这里单独+配置方便上面添加其它路由
urlpatterns += router.urls

视图配置

from rest_framework.viewsets import ModelViewSet
from .models import Book
from .serializers import BookSerializerclass BookView(ModelViewSet):queryset = Book.objects.all()serializer_class = BookSerializer

测试:

ReadOnlyModelViewSet

它仅支持list和retrive这两个可读的操作

以下是关于它的详细使用方法:

导入和继承

首先,在你的视图文件(通常是views.py)中需要导入ReadOnlyModelViewSet,并且让你的视图类继承自它。假设你有一个Book模型,示例如下:

from rest_framework.viewsets import ReadOnlyModelViewSet
from.models import Book
from.serializers import BookSerializerclass BookReadOnlyViewSet(ReadOnlyModelViewSet):queryset = Book.objects.all()serializer_class = BookSerializer

在这个示例中,BookReadOnlyViewSet继承了ReadOnlyModelViewSet

通过设置queryset属性指定了视图集操作的数据集(这里是所有的Book对象),serializer_class属性则指定了用于序列化和反序列化数据的序列化器类。

提供的默认操作方法

ReadOnlyModelViewSet提供了两种默认的只读操作方法:

  • list方法:用于获取模型对象的列表。
    • 当客户端发送一个GET请求到视图集对应的列表URL(例如/books/)时,list方法会被调用。
    • 它会从queryset中获取所有的对象,通过serializer_class将这些对象序列化为合适的数据格式(如JSON),然后将序列化后的数据作为响应返回给客户端。
  • retrieve方法:用于获取单个模型对象的详细信息。
    • 当客户端发送一个GET请求到视图集对应的详情URL(例如/books/1/,其中1Book对象的主键)时,retrieve方法会被调用。
    • 它会根据请求中的主键从queryset中获取对应的单个对象,再使用serializer_class进行序列化,并将结果返回给客户端。

序列化器(Serializer)的使用

  • 定义序列化器
from rest_framework import serializersclass BookSerializer(serializers.ModelSerializer):class Meta:model = Bookfields = '__all__'
- 序列化器用于将模型实例转换为可以在网络上传输的数据格式(如JSON),以及将接收到的格式数据转换为模型实例(在可写视图集中使用)。在上述示例中,`BookSerializer`可能是一个简单的基于模型的序列化器,例如:
- 这个序列化器定义了它基于`Book`模型,并且通过`fields = '__all__'`表示要序列化模型的所有字段。你也可以根据需要指定具体的字段列表,如`fields = ['title', 'author', 'publication_date']`。
  • 在视图集中使用序列化器
    • BookReadOnlyViewSet中,通过serializer_class = BookSerializer指定了使用这个序列化器。当执行listretrieve操作时,视图集会自动调用这个序列化器的相应方法进行数据的序列化。

URL配置

  • 自动配置(推荐)
from rest_framework.routers import DefaultRouter
from .views import BookReadOnlyViewSetrouter = DefaultRouter()
router.register('books', BookReadOnlyViewSet)urlpatterns = [# path('', include(router.urls)),
]
# 这里单独+配置方便上面添加其它路由
urlpatterns += router.urls
- 可以使用Django REST framework中的`Router`来自动配置`BookReadOnlyViewSet`的URL。
- 在`urls.py`文件中,示例如下:
- 这样,`Router`会自动为`BookReadOnlyViewSet`生成以下URL模式:* `books/`:对应`list`方法,用于获取`Book`对象的列表。* `books/<pk>/`:对应`retrieve`方法,用于获取单个`Book`对象(其中`<pk>`是`Book`对象的主键)。
  • 手动配置
from django.urls import path
from.views import BookReadOnlyViewSeturlpatterns = [path('books/', BookReadOnlyViewSet.as_view({'get': 'list'}), name='book - list'),path('books/<int:pk>/', BookReadOnlyViewSet.as_view({'get':'retrieve'}), name='book - retrieve'),
]
- 如果不想使用`Router`自动配置,也可以手动配置URL。在`urls.py`中,示例如下:
- 这里的`as_view`方法的参数是一个字典,键是`GET`请求方法,值是视图集类中的方法名(`list`或`retrieve`)。

四、DRF认证与权限

认证与权限一定要配合使用才行(2个都要配置)
认证与权限都分全局配置(settins.py中)与某个视图中局部配置两种配置方案
一个是drf框架视图全局生效,一个是drf框架局部视图生效

注意: 在每个视图或视图集单独指定认证与权限方式,会覆盖全局配置。

一、Django REST Framework (DRF) 认证配置

1. 基本认证(Basic Authentication)

  • 配置步骤
    • 全局配置,在 settings.py 文件中,将 rest_frameworkDEFAULT_AUTHENTICATION_CLASSES 配置项添加基本认证类。
    • 例如:
REST_FRAMEWORK = {'DEFAULT_AUTHENTICATION_CLASSES': ['rest_framework.authentication.BasicAuthentication',]
}
  • 或者局部配置在视图类或视图集中,可以通过设置 authentication_classes 属性来指定使用的认证方式。
  • 例如:
from rest_framework.viewsets import ModelViewSet
from .models import Book
from .serializers import BookSerializer
# 认证
from rest_framework.authentication import BasicAuthentication
# 权限
from rest_framework.permissions import IsAuthenticatedclass BookView(ModelViewSet):authentication_classes = [BasicAuthentication]permission_classes = [IsAuthenticated]queryset = Book.objects.all()serializer_class = BookSerializer
  • 原理:基本认证是通过在请求头中发送 Authorization 字段,格式为 Basic <base64编码的用户名:密码> 来进行认证, 基本认证通常只适用于测试。
  • DRF 的基本认证类会解析这个请求头,验证用户的用户名和密码。
  • 测试访问 : http://127.0.0.1:8000/books/ 会弹出用户密码登录验证框

2.Session 认证(Session Authentication)

https://www.cnblogs.com/zhangqigao/p/12800935.html

  • 安装必要的应用
    • 确保django.contrib.sessionsINSTALLED_APPS中已经添加。
    • 这是 Django 内置的用于处理会话(Session)的应用,默认情况下在新建的 Django 项目中已经添加。
  • 配置中间件
    • 确认django.contrib.sessions.middleware.SessionMiddlewareMIDDLEWARE列表中。这个中间件用于处理会话相关的操作,如创建、读取和更新会话。它的位置很重要,通常应该放在合适的位置,以确保在请求处理过程中能够正确地处理会话。例如,它应该放在AuthenticationMiddleware之前,这样在进行用户认证时可以利用会话信息。
  • REST_FRAMEWORK **全局配置**配置项中,可以设置DEFAULT_AUTHENTICATION_CLASSES来指定使用 Session 认证作为默认的认证方式。例如:
 REST_FRAMEWORK = {'DEFAULT_AUTHENTICATION_CLASSES': ['rest_framework.authentication.SessionAuthentication',]}
  1. 视图级别配置
    • 对于基于函数的视图
      • 可以使用@authentication_classes装饰器来指定认证方式。例如:
from rest_framework.decorators import authentication_classes
from rest_framework.authentication import SessionAuthentication
from rest_framework.views import APIView
from rest_framework.response import Response@authentication_classes([SessionAuthentication])
def my_view(request):# 这里可以访问通过Session认证后的用户信息user = request.userreturn Response({"message": "Hello, {}".format(user.username)})
  • 对于基于类的视图和视图集
    • 在视图类或视图集中设置authentication_classes属性。例如:
from rest_framework.views import APIView
from rest_framework.authentication import SessionAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Responseclass MyView(APIView):authentication_classes = [SessionAuthentication]permission_classes = [IsAuthenticated]def get(self, request):user = request.userreturn Response({"message": "Hello, {}".format(user.username)})

. url配置:

urlpatterns = [path('booksession/', MyView.as_view()),
]
获取 Session Cookie(模拟登录过程,因为基于 Session 认证需要有效的 Session)
  • 方式一:通过浏览器登录获取(如果有对应的登录页面)
    • 首先,在浏览器中访问你的 Django 项目的登录页面(假设存在),输入合法的用户名和密码进行登录。登录成功后,浏览器会自动存储后端返回的包含 Session ID 的 Cookie。
    • 然后,你可以通过浏览器的开发者工具(通常是按 F12 键调出),在 “Application”(不同浏览器可能名称稍有不同)选项卡中,找到 “Cookies” 部分,查看当前域名下存储的 Cookie,找到对应的 Session ID 相关的 Cookie 及其值(例如 sessionid=xxxxxxxxxxxx)。
    • 我们在访问 admin 后台登录,输入用户名密码的时候,后台会自动生成 session
    • 登录后,就可以直接访问视图相关信息了:
    • postman测试:
  • 方式二:使用curl模拟登录请求(如果有对应的 API 登录端点)
    • 假设你的项目有一个登录的 API 端点,比如 /api/login/,并且接受 usernamepassword 作为表单数据来进行登录验证,那么可以使用以下 curl 命令模拟登录(以下命令中的用户名和密码需要替换为实际有效的值):
curl -X POST -d "username=your_username" -d "password=your_password" http://127.0.0.1:8000/api/login/
  • 执行这个命令后,如果登录成功,服务器会在响应中设置包含 Session ID 的 Cookie。不过要注意,curl 默认情况下不会自动存储和发送 Cookie,所以还需要进一步配置 curl 来处理 Cookie.

CSRF Token 与 Session 的关系

- 在 Django 中,`CSRFToken`(跨站请求伪造令牌)和`Session`是相关但不同的概念。`CSRFToken`主要用于防止跨站请求伪造攻击。当一个用户通过浏览器访问一个网站并成功建立会话(`Session`)后,Django 会为每个表单或需要进行状态改变的请求(如 POST、PUT、DELETE 等)生成一个`CSRFToken`,并将其存储在用户的`Session`中(服务器端),同时在页面的表单或通过其他方式(如在 HTML 的`meta`标签中)发送给客户端。
- 当客户端发送一个需要进行状态改变的请求时,需要在请求中包含这个`CSRFToken`,服务器会验证请求中的`CSRFToken`是否与存储在`Session`中的一致,以此来防止恶意网站发起的跨站请求伪造攻击。

3.Token 认证(Token Authentication)

  • 配置步骤
    • 首先,需要在项目中使用 rest_framework.authtoken 应用。
    • INSTALLED_APPS 中添加 'rest_framework.authtoken'
INSTALLED_APPS = [# add drf authentication'rest_framework.authtoken',
]
- 运行 `python manage.py migrate` 来创建 `Token` 模型对应的数据库表。
- 然后在 `settings.py` 中配置 `DEFAULT_AUTHENTICATION_CLASSES`
- 与 DEFAULT_AUTHENTICATION_CLASSES
# 全局配置
REST_FRAMEWORK = {# 认证'DEFAULT_AUTHENTICATION_CLASSES': ('rest_framework.authentication.TokenAuthentication',),# 权限'DEFAULT_PERMISSION_CLASSES': ['rest_framework.permissions.IsAuthenticated',]
}

局部视图生效的配置方式:

from rest_framework.viewsets import ModelViewSet
from .models import Book
from .serializers import BookSerializer
# 认证
from rest_framework.authentication import TokenAuthentication
# 权限
from rest_framework.permissions import IsAdminUserclass BookView(ModelViewSet):authentication_classes = [TokenAuthentication]permission_classes = [IsAdminUser]queryset = Book.objects.all()serializer_class = BookSerializer
  • 为用户创建 Token,可以通过代码创建(例如在用户注册或登录成功后):
  • python manage.py shell
from rest_framework.authtoken.models import Token
from django.contrib.auth.models import Useruser = User.objects.get(username='admin')
token, created = Token.objects.get_or_create(user=user)

或者直接在管理后台页面中为用户创建 Token

  • 客户端在请求时,需要在请求头中添加 Authorization: Token <token_value>
  • 原理:用户登录后会获得一个唯一的 Token,之后每次请求都带上这个 Token,DRF 的 TokenAuthentication 类会验证 Token 的有效性来确定用户身份。

命令行工具curl 可用于测试基于Token认证的API,例如:

curl -X GET http://127.0.0.1:8000/books/ -H 'Authorization: Token 6aec32eaee0e11c9d708e703fb3f1cbf7a5b20c9'

postman测试:

注意: 如果你在生产环境下使用TokenAuthentication认证,你必须确保你的API仅在https可用。

4.JWT 认证(JSON Web Token Authentication)

  • 配置步骤(使用第三方库如djangorestframework-simplejwt):
    • 安装 djangorestframework - simplejwt,例如通过 pip install djangorestframework - simplejwt
  • 详细参考配置文档:

https://django-rest-framework-simplejwt.readthedocs.io/en/latest/settings.html

  • settings.py 中配置全局视图的认证与权限:
# 必配置的jwt模块
INSTALLED_APPS = ['rest_framework','rest_framework_simplejwt',
]
# 全局方式配置认证与权限
REST_FRAMEWORK = {'DEFAULT_AUTHENTICATION_CLASSES': [# jwt认证方式'rest_framework_simplejwt.authentication.JWTAuthentication',]# 权限'DEFAULT_PERMISSION_CLASSES': ['rest_framework.permissions.IsAuthenticated',]
}
  • 配置局部认证与权限的方式:
from rest_framework.authentication import JWTAuthentication
from rest_framework.viewsets import ModelViewSet
from .models import Book
from .serializers import BookSerializer
from rest_framework.permissions import IsAuthenticatedclass BookView(ModelViewSet):# 局部视图中单独配置认证与权限的验证方式authentication_classes = [JWTAuthentication]permission_classes = [IsAuthenticated]queryset = Book.objects.all()serializer_class = BookSerializer

注意:最终局部视图中认证与权限还是会覆盖全局的配置

生成 JWT 令牌

可以通过登录视图例如:

from rest_framework_simplejwt.views import (TokenObtainPairView,TokenRefreshView,
)urlpatterns = [path('token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),path('token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
]

获取token:

刷新访问token:

  • 或者使用库提供的方法来实现。例如:
from rest_framework_simplejwt.tokens import RefreshTokendef get_tokens_for_user(user):refresh = RefreshToken.for_user(user)return {'refresh': str(refresh),'access': str(refresh.access_token),}
利用token进行访问book书籍信息

二、DRF 权限配置

. AllowAny 允许所有用户

. IsAuthenticated 仅通过认证的用户

. IsAuthenticatedOrReadOnly 认证的用户可以完全操作,否则只能get读取

. IsAdminUser 仅管理员用户

基于用户认证的权限(IsAuthenticated)

  • 配置步骤
    • 全局配置:
    • 通过DEFAULT_PERMISSION_CLASSES配置全局权限类
REST_FRAMEWORK = {# 认证'DEFAULT_AUTHENTICATION_CLASSES': (# 'rest_framework.authentication.TokenAuthentication','rest_framework.authentication.BasicAuthentication',# 'rest_framework.authentication.SessionAuthentication',# 'rest_framework.permissions.IsAuthenticated',),# 权限'DEFAULT_PERMISSION_CLASSES': ['rest_framework.permissions.IsAuthenticated',]
}
- 或者局部视图类或视图集中设置 `permission_classes` 属性。
- 例如:
from rest_framework.viewsets import ModelViewSet
from .models import Book
from .serializers import BookSerializer
# 认证
from rest_framework.authentication import BasicAuthentication
# 权限
from rest_framework.permissions import IsAuthenticatedclass BookView(ModelViewSet):authentication_classes = [BasicAuthentication]permission_classes = [IsAuthenticated]queryset = Book.objects.all()serializer_class = BookSerializer
  • 原理:只有通过认证的用户(即认证成功的用户)才能访问该视图。
  • 继承自django原生的后台管理用户
  • 当未认证用户尝试访问时,会收到 401 Unauthorized403 Forbidden 错误(取决于具体的认证和权限配置细节)。

基于用户角色的权限(如 IsAdminUser 等)

- **配置步骤**:* DRF 提供了一些基于用户角色的权限类,例如 `IsAdminUser`。* 在视图中配置如下:
from rest_framework.viewsets import ModelViewSet
from .models import Book
from .serializers import BookSerializer
# 认证
from rest_framework.authentication import BasicAuthentication
# 权限
from rest_framework.permissions import IsAdminUserclass BookView(ModelViewSet):authentication_classes = [BasicAuthentication]permission_classes = [IsAdminUser]queryset = Book.objects.all()serializer_class = BookSerializer
  • 原理IsAdminUser 权限类会检查用户是否是管理员(通常是通过检查 user.is_staff 属性),只有管理员用户才能访问配置了该权限类的视图。

自定义权限类

  • 配置步骤
    • 首先,创建自定义权限类。例如,创建一个只允许特定 IP 地址访问的权限类:
from rest_framework.permissions import BasePermissionclass IPWhitelistPermission(BasePermission):def has_permission(self, request, view):ip_whitelist = ['127.0.0.1', '192.168.0.1']return request.META.get('REMOTE_ADDR') in ip_whitelist
  • 然后在视图中使用这个自定义权限类:
from rest_framework.views import APIViewclass MyIPRestrictedView(APIView):permission_classes = [IPWhitelistPermission]def get(self, request):return Response({"message": "Only whitelisted IPs can access"})
  • 原理:自定义权限类需要继承自 BasePermission,并实现 has_permission 方法(用于判断是否有权限访问视图)或 has_object_permission 方法(用于判断是否有权限访问对象)。在上述例子中,通过检查请求的 IP 地址是否在白名单中来决定用户是否有访问权限。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/64473.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机网络-HTTP协议

HTTP HTTP是一种不保存状态&#xff0c;即无状态的协议。HTTP协议自身不对请求和响应之间的通信进行保存。为了保存状态因此后面也有一些技术产生比如Cookies技术。 HTTP是通过URI定位网上的资源&#xff0c;理论上将URI可以访问互联网上的任意资源。 如果不是访问特定的资源…

CTFHub 命令注入-综合练习(学习记录)

综合过滤练习 命令分隔符的绕过姿势 ; %0a %0d & 那我们使用%0a试试&#xff0c;发现ls命令被成功执行 /?ip127.0.0.1%0als 发现一个名为flag_is_here的文件夹和index.php的文件&#xff0c;那么我们还是使用cd命令进入到文件夹下 http://challenge-438c1c1fb670566b.sa…

【AI知识】逻辑回归介绍+ 做二分类任务的实例(代码可视化)

1. 分类的基本概念 在机器学习的有监督学习中&#xff0c;分类一种常见任务&#xff0c;它的目标是将输入数据分类到预定的类别中。具体来说&#xff1a; 分类任务的常见应用&#xff1a; 垃圾邮件分类&#xff1a;判断一封电子邮件是否是垃圾邮件 。 医学诊断&#xff1a;…

为SSH2协议服务器的用户设置密钥

目录 私钥的创建1. 在服务器上直接生成2. 如果需要配置免密登录3. 查看生成的密钥 导出私钥至SSH用户获取sudo权限 新的一台服务器类型是SSH2&#xff1a;这表示服务器支持SSH&#xff08;Secure Shell&#xff09;协议的第二个版本。SSH是一个网络协议&#xff0c;用于加密方式…

level2逐笔委托查询接口

沪深逐笔委托队列查询 前置步骤 分配数据库服务器 查询模板 以下是沪深委托队列查询的请求模板&#xff1a; http://<数据库服务器>/sql?modeorder_book&code<股票代码>&offset<offset>&token<token>查询参数说明 参数名类型说明mo…

文献研读|基于像素语义层面图像重建的AI生成图像检测

前言&#xff1a;本篇文章主要对基于重建的AI生成图像检测的四篇相关工作进行介绍&#xff0c;分别为基于像素层面重建的检测方法 DIRE 和 Aeroblade&#xff0c;以及基于语义层面重建的检测方法 SimGIR 和 Zerofake&#xff1b;并对相应方法进行比较。 相关文章&#xff1a;论…

VScode MAC按任意键关闭终端 想要访问桌面文件

说明 最近配置MAC上CPP的运行环境&#xff0c;在安装必要的CPP插件后&#xff0c;配置launch和task等json文件后&#xff0c;点击运行三角形&#xff0c;每次都会跳出main想要访问桌面上的文件。并且输出也是在调试控制台&#xff0c;非常逆天。 尝试 尝试1:尽管我尝试将ta…

Linux Shell 脚本编程基础知识篇

ℹ️大家好&#xff0c;我是练小杰&#xff0c;从本文是Linux shell脚本编程的基础知识内容&#xff0c;后续我会不断补充~~ 更多Linux 相关内容请点击&#x1f449;“Linux专栏”~ 假面驾驭&#xff0c;时王&#xff0c;假面骑士时王~~ 文章目录 什么是 Linux Shell主要功能…

QT绘制同心扇形

void ChartForm::paintEvent(QPaintEvent *) {QPainter painter(this);painter.setRenderHint(QPainter::Antialiasing);// 设置抗锯齿painter.save();// 设置无边框&#xff08;不需要设置QPen&#xff0c;因为默认是不绘制边框的&#xff09;QPen pen(Qt::NoPen);// QPen pen…

TL3568/TL3562更改主机名,在Kernel用menuconfig失效

前言 最近在玩RK3562开发板&#xff0c;想改串口调试时看到的主机名&#xff0c;开发板的主机名默认是RK3562-Tronlong&#xff0c;如图&#xff1a; 按照之前玩T113开发版&#xff0c;在Kernel通过make menuconfig&#xff0c;可以改。但是在这个RK3562&#xff0c;改了后&…

【PLL】ISSCC 2024 Tutorial: Calibration Techniques in PLLs

1. 数字辅助模拟电路 为什么要辅助&#xff0c;或替换模拟电路&#xff1f; 利用CMOS管子尺寸缩小&#xff0c;降低功耗 和 减小面积校正模拟电路的 非线性行为 和 失配 数字辅助的好处&#xff1a; 简化模拟电路设计提高能源效率&#xff0c;提高准确度 2. 锁相环基础 2.1 概…

STM32-笔记5-按键点灯(中断方法)

1、复制03-流水灯项目&#xff0c;重命名06-按键点灯&#xff08;中断法&#xff09; 在\Drivers\BSP目录下创建一个文件夹exti&#xff0c;在该文件夹下&#xff0c;创建两个文件exti.c和exti.h文件&#xff0c;并且把这两个文件加载到项目中&#xff0c;打开项目工程文件 加载…

Mvc、Springmvc框架

一.Mvc&#xff1a; 1.概念&#xff1a; MVC它是一种设计理念。把程序按照指定的结构来划分: Model模型 、View视图 、Controller控制层&#xff1b; 结构图&#xff1a; 二.Springmvc: 1.概念&#xff1a; springmvc框架它是spring框架的一个分支。它是按照mvc架构思想设计…

spring使用rabbitmq当rabbitmq集群节点挂掉 spring rabbitmq怎么保证高可用,rabbitmq网络怎么重新连接

##spring rabbitmq代码示例 Controller代码 import com.alibaba.fastjson.JSONObject; import com.newland.mi.config.RabbitDMMQConfig; import org.springframework.amqp.core.Message; import org.springframework.amqp.core.MessageProperties; import org.springframewo…

前端面试问题集合

0 HTML5相关 websocket WebSocket 使用ws或wss协议&#xff0c;Websocket是一个持久化的协议&#xff0c;相对于HTTP这种非持久的协议来说。WebSocket API最伟大之处在于服务器和客户端可以在给定的时间范围内的任意时刻&#xff0c;相互推送信息。WebSocket并不限于以Ajax(或X…

RabbitMQ如何构建集群?

大家好&#xff0c;我是锋哥。今天分享关于【RabbitMQ如何构建集群&#xff1f;】面试题。希望对大家有帮助&#xff1b; RabbitMQ如何构建集群&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在RabbitMQ中&#xff0c;集群&#xff08;Cluster&#x…

3大Excel免费功能

推荐几个免费excel图表绘制工具 Power Map Power Map是Excel的内置功能 Power Map可在Windows用户的Excel 2013或者Excel 2016或者Office 365中使用,如下图, 看案例 动态地图1 动态地图2

概率论得学习和整理31: 连续型随机变量的概率本质是求面积,均匀分布等

目录 1 连续性随机变量 2 连续性随机变量和 离散型随机变量&#xff0c;分布的区别 3 不要混淆概念 4 均匀分布的相关 4.1 定义 4.2 例子 1 连续性随机变量 连续性随机变量最大的特点&#xff0c;单个点上的概率0多了一个分布函数&#xff0c;因为从1维变2维了&#xff…

素数回文数的个数

素数回文数的个数 C语言代码C 代码Java代码Python代码 &#x1f490;The Begin&#x1f490;点点关注&#xff0c;收藏不迷路&#x1f490; 求11到n之间&#xff08;包括n&#xff09;&#xff0c;既是素数又是回文数的整数有多少个。 输入 一个大于11小于1000的整数n。 输出…

FFmpeg库之ffmpeg

文章目录 ffmpeg命令行使用基本命令选择流 -map选项 主要命令视频选项音频选项多媒体格式转换滤镜裁剪加水印画中画 录制查看可用的录制设备查看录制设备选项参数录制桌面录制窗口录制摄像头录制麦克风录制系统声音同时录制桌面和麦克风 直播推流拉流 ffmpeg命令行使用 ffmpeg…