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.rhkb.cn/news/492090.html

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

相关文章

【BUG】记一次context canceled的报错

文章目录 案例分析gorm源码解读gin context 生命周期context什么时候cancel的什么时候context会被动cancel掉呢&#xff1f; 野生协程如何处理 案例分析 报错信息 {"L":"ERROR","T":"2024-12-17T11:11:33.0050800","file"…

Qt WORD/PDF(四)使用 QAxObject 对 Word 替换(QWidget)

关于QT Widget 其它文章请点击这里: QT Widget 国际站点 GitHub: https://github.com/chenchuhan 国内站点 Gitee : https://gitee.com/chuck_chee 姊妹篇: Qt WORD/PDF&#xff08;一&#xff09;使用 QtPdfium库实现 PDF 操作 Qt WORD/PDF&#xff08;二…

使用nvm对node进行多版本管理

1.nvm下载及安装 下载链接 下载完成后&#xff0c;对文件进行解压安装&#xff0c;按照提示一步步安装&#xff0c;如果电脑上之前有安装过node&#xff0c;需要先卸载&#xff0c;再进行安装。 按照提示完成安装。 2.设置环境变量 可以现在C:\Users\name\AppData\Roamin…

基于Socket实现客户端和服务端的Tcp通信(C#)

0.前言 使用C#和Unity实现复刻Liar’s bar中的功能 软件开发大作业 本系列文章用于记录与分享开发过程中使用到的知识点&#xff0c;以及常见错误 本文主要描述有关网络编程的内容 目录 0.前言1.使用Socket搭建Server1.1Server端的Socket连接1.2 Server端接收Client的信息1.3…

eclipse 如何设置项目、不同类型文件的 utf8 编码

编码问题一直是软件开发中让人头疼的小细节&#xff0c;尤其是团队协作中&#xff0c;若编码格式不统一&#xff0c;乱码问题便会频繁出现。那么如何在 Eclipse 中统一设置项目和文件的 UTF-8 编码&#xff0c;避免因编码问题造成不必要的困扰呢&#xff1f;今天&#xff0c;我…

MVC基础——市场管理系统(四)

文章目录 项目地址六、EF CORE6.1 配置ef core环境6.2 code first6.2.1 创建Database context1. 添加navigation property2. 添加MarketContext上下文七、Authentication7.1 添加Identity7.2 Run DB migration for Identity7.3 使用Identity7.3.1 设置认证中间件7.3.2 设置权限…

java后端环境配置

因为现在升学了&#xff0c;以前本来想毕业干java的&#xff0c;很多java的环境配置早就忘掉了&#xff08;比如mysql maven jdk idea&#xff09;&#xff0c;想写个博客记录下来&#xff0c;以后方便自己快速搭建环境 JAVA后端开发配置 环境配置jdkideamavenMySQLnavicate17…

Edge Scdn用起来怎么样?

Edge Scdn&#xff1a;提升网站安全与性能的最佳选择 在当今互联网高速发展的时代&#xff0c;各种网络攻击层出不穷&#xff0c;特别是针对网站的DDoS攻击威胁&#xff0c;几乎每个行业都可能成为目标。为了确保网站的安全性与稳定性&#xff0c;越来越多的企业开始关注Edge …

CN-fnst::CTF Web

文章目录 ezphpez_pythoncomment_mefilechecker_revengei_am_eeeeeshili ezphp 直接数组绕过, 执行命令 GET: usn[]1&usn1[]1&signenv POST: pwd[]2&pwd1[]2 ez_python file参数任意文件读取 读取源码: ?fileapp.py from flask import Flask, request, render_…

AI自我进化的新篇章:谷歌DeepMind推出苏格拉底式学习,语言游戏解锁无限潜能

各位AI爱好者、技术研究者&#xff0c;大家好&#xff01;今天我们来聊聊一个令人兴奋的AI研究新进展——谷歌DeepMind推出的“苏格拉底式学习”方法。这项研究的独特之处在于&#xff0c;它让AI在没有外部数据的情况下&#xff0c;通过“语言游戏”实现自我进化&#xff0c;这…

《类和对象:基础原理全解析(上篇)》

目录 一、浅谈面向过程和面向对象二、C 中的结构体&#xff08;struct&#xff09;1. C 中 struct 的使用 三、C 中的类&#xff08;class&#xff09;四、类的封装性1. 类成员的权限控制关键字2. 权限控制关键字的使用 五、类的六大默认成员函数介绍六、构造函数1. 使用构造函…

电子应用设计方案-59:智能电动床系统方案设计

智能电动床系统方案设计 一、引言 智能电动床作为一种高端家居产品&#xff0c;旨在为用户提供更加舒适、便捷和个性化的睡眠体验。本方案将详细介绍智能电动床系统的设计架构、功能特点和技术实现。 二、系统概述 1. 系统目标 - 实现床体的多部位电动调节&#xff0c;满足不…

电商环境下的财务ERP系统架构

先介绍一下自己的工作经历&#xff0c;2002年开始进入ERP实施行业&#xff0c;专注于O记EBS系统&#xff0c;正好赶上中国经济和信息化高度发展的阶段&#xff0c;先后实施过很多大国企和民企的大型ERP项目&#xff0c;在实施过程中逐渐对ERP系统的架构、模块设计有更深入的认识…

【WRF教程第3.2期】预处理系统 WPS详解:以4.5版本为例

预处理系统 WPS 详解&#xff1a;以4.5版本为例 WPS 嵌套域&#xff08;WPS Nested Domains&#xff09;USGS 和 MODIS 土地利用重力波拖拽方案静态数据&#xff08;Gravity Wave Drag Scheme Static Data&#xff09;1. 什么是重力波拖拽方案&#xff08;GWDO&#xff09;静态…

在Proteus软件仿真STM32F103寄存器方式PID调速电机

因为电脑中只装了IAR&#xff0c;所以本次编译环境就只能是IAR&#xff0c;所用软件版本是9.32.1。 本次仿真为&#xff0c;纯手写代码&#xff0c;不用任何库&#xff0c;包括启动文件也是手写。 首先是启动文件&#xff0c;该文件是汇编文件&#xff0c;命名为start.s&…

QtitanChart组件——高效、灵活的Qt数据可视化解决方案

在现代应用开发中&#xff0c;数据可视化已经成为不可或缺的一部分。无论是商业分析工具、财务报表、工程图表&#xff0c;还是科学实验数据展示&#xff0c;如何以直观、易理解的方式展示数据&#xff0c;往往决定了软件的可用性与用户体验。对于Qt开发者来说&#xff0c;Qtit…

YOLOv11融合[CVPR2024]Starnet中的star block特征提取模块

YOLOv11v10v8使用教程&#xff1a; YOLOv11入门到入土使用教程 YOLOv11改进汇总贴&#xff1a;YOLOv11及自研模型更新汇总 《Rewrite the Stars》 一、 模块介绍 论文链接&#xff1a;https://arxiv.org/abs/2403.19967 代码链接&#xff1a;https://github.com/ma-xu/Rewri…

LabVIEW农机自主导航监控系统

随着现代农业技术的快速发展&#xff0c;自主导航农机的需求日益增加&#xff0c;提高作业效率和减少劳动成本成为农业现代化的关键目标。本文介绍了一个基于LabVIEW的农机自主导航监控系统的开发案例&#xff0c;该系统通过先进的传感器与控制技术&#xff0c;实现农机在田间作…

JAVA:代理模式(Proxy Pattern)的技术指南

1、简述 代理模式(Proxy Pattern)是一种结构型设计模式,用于为其他对象提供一种代理,以控制对这个对象的访问。通过代理模式,我们可以在不修改目标对象代码的情况下扩展功能,满足特定的需求。 设计模式样例:https://gitee.com/lhdxhl/design-pattern-example.git 2、什…

番外篇 | Hyper-YOLO:超图计算与YOLO架构相结合成为目标检测新的SOTA !

前言:Hello大家好,我是小哥谈。Hyper-YOLO,该方法融合了超图计算以捕捉视觉特征之间复杂的高阶关联。传统的YOLO模型虽然功能强大,但其颈部设计存在局限性,限制了跨层特征的融合以及高阶特征关系的利用。Hyper-YOLO在骨干和颈部的联合增强下,成为一个突破性的架构。在COC…