14 路由Routers
# 只要是继承ViewSetMixin的视图类,路由写法都变了:as_view({字典}) # 重点;以后视图类中可以写任意的方法,只需要继承ViewSetMixin后,使用路由做映射即可 # 路由使用的第一种方式: from rest_framework.viewsets import ModelViewSet,ReadOnlyModelViewSet,ViewSet,ViewSetMixin,GenericViewSet class PublishView(ModelViewSet): queryset = models.Publish.objects.all() serializer_class = Publishserializer from rest_framework.viewsets import ViewSet #ViewSet继承了ViewSetMixin,APIView # class BookView(ViewSetMixin,APIView): # def login(self,request): # return Response("登录成功") #class BookView(ViewSetMixin,GenericAPIView): #GenericViewSet继承了ViewSetMixin,GenericAPIView class BookView(GenericViewSet): queryset=None serializer_class=None #注意要加上这2句 def login(self,request): return Response("登录成功") path('publish/', views.PublishView.as_view(actions={'get': 'list','post':'create'})) # 自动生成路由 # 在urls.py中 # 第一步导入路由的类 from rest_framework.routers import SimpleRouter,DefaultRouter SimpleRouter,DefaultRouter的区别 SimpleRouter将路由做了汇总 # 第二步:类实例化得到对象(不用传参数) router=SimpleRouter() # 第三步:注册视图类, router.register('publish',views.PublishView,'publish') # router.register('book',views.BookView) # 第四步:加入到总路由中(两种方式) urlpatterns = [ # 第四步:加入到总路由中方式二 path('api/v1/', include(router.urls)), ] # 第四步:加入到总路由中:方式一 urlpatterns+=router.urls ###action装饰器的作用:给视图函数中自定义的方法做路径的映射 ###总结: -第一种:path('publish/', views.PublishView.as_view(actions={'get': 'list','post':'create'})) -第二种:自动生成 (SimpleRouter,DefaultRouter) -action有什么用 -5个方法:create,list,destory。。,不需要使用action映射 -如果继承的是 ViewSetMixin, views.APIView +5个视图扩展类之一或者9个视图子类,这种不需要使用action装饰器
1 在urls.py中配置
path('books4/', views.Book4View.as_view()), re_path('books4/(?P\d+) ', views.Book4DetailView.as_view()),
2 一旦视图类,继承了ViewSetMixin
path('books5/', views.Book5View.as_view(actions={'get':'list','post':'create'})), #当路径匹配,又是get请求,会执行Book5View的list方法 re_path('books5/(?P\d+) ', views.Book5View.as_view(actions={'get':'retrieve','put':'update','delete':'destroy'})),
3 继承自视图类,ModelViewSet的路由写法(自动生成路由)
# 3 继承自视图类,ModelViewSet的路由写法(自动生成路由) -urls.py # 第一步:导入routers模块 from rest_framework import routers # 第二步:有两个类,实例化得到对象 # routers.DefaultRouter 生成的路由更多 # routers.SimpleRouter router=routers.DefaultRouter() # 第三步:注册 # router.register('前缀','继承自ModelViewSet视图类','别名') router.register('books',views.BookViewSet) # 不要加斜杠了 # 第四步 # router.urls # 自动生成的路由,加入到原路由中 # print(router.urls) # urlpatterns+=router.urls ''' -views.py from rest_framework.viewsets import ModelViewSet from app01.models import Book from app01.ser import BookSerializer class BookViewSet(ModelViewSet): queryset =Book.objects serializer_class = BookSerializer
4 action的使用
get_1不在自动生成的路由中,所以要用action
# action干什么用?为了给继承自ModelViewSet的视图类中定义的函数也添加路由 # 使用 from rest_framework.decorators import action class BookViewSet(ModelViewSet): queryset =Book.objects.all() serializer_class = BookSerializer # methods第一个参数,传一个列表,列表中放请求方式, # ^books/get_1/$ [name='book-get-1'] 当向这个地址发送get请求,会执行下面的函数 # detail:布尔类型 如果是True #^books/(?P[^/.]+)/get_1/$ [name='book-get-1'] @action(methods=['GET','POST'],detail=True) def get_1(self,request,pk): print(pk) book=self.get_queryset()[:2] # 从0开始截取2条 ser=self.get_serializer(book,many=True) return Response(ser.data) # 装饰器,放在被装饰的函数上方,method:请求方式,detail:是否带pk
登录的5个接口
#models.py class User(models.Model): username=models.CharField(max_length=32) password=models.CharField(max_length=32) class UserToken(models.Model): token=models.CharField(max_length=32) #只要用户登录,生成一个随机字符串,存到这,再次登录,更新 user=models.OneToOneField(to="User",on_delete=models.CASCADE) #views.py
from rest_framework.viewsets import ViewSetMixin, ViewSet
from rest_framework.decorators import action
from .models import User,UserToken
import uuid # 生成一个永不(相对的)重复的随机字符串
from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet
from .seriazlizer import BookSerializer
from .models import Book
# 127.0.0.1:8080/user/login ---->post请求
class UserView(ViewSet):
authentication_classes = []
# class UserView(ViewSetMixin,APIView,):
@action(methods=['POST'], detail=False)
def login(self, request):
# post请求提交的数据都在request.data中
username = request.data.get('username')
password = request.data.get('password')
user=User.objects.all().filter(username=username,password=password).first()
if user:
# 登录成功,返回数据格式为 {code:100,msg:登录成功,token:'asdfasdf'}
token=str(uuid.uuid4())
# 存库(直接存),判断如果有了数据,就修改token,如果没有是新增
# user_token=UserToken.objects.create(token=token,user=user)
# user=user,通过这个去查,如果能查到,使用defaults更新,如果查不到,使用所有新增
UserToken.objects.update_or_create(defaults={'token':token},user=user)
return Response({'msg':'登录成功','code':100,'token':token})
else:
return Response({'msg': '用户名或密码错误', 'code': 101})
#urls.py
from django.contrib import admin
from django.urls import path,include
from app01 import views
from rest_framework.routers import SimpleRouter
router=SimpleRouter()
router.register("user",views.UserView,'user')
#router.register("book",views.BookView,'book')
urlpatterns = [
path('admin/', admin.site.urls),
path(r"",include(router.urls))
]