# Create your views here.
from rest_framework import serializers
from rest_framework.views import APIView
from rest_framework.response import Response
class PublisherSerializers(serializers.Serializer):
name = serializers.CharField()
email = serializers.CharField()
# class BookSerializers(serializers.Serializer):
# title = serializers.CharField()
# price = serializers.IntegerField()
# pub_date = serializers.DateField()
# publisher = serializers.CharField(source="publisher.email")
# # authors = serializers.CharField(source="authors.all") #多对多不好用
# authors =serializers.SerializerMethodField()
# def get_authors(self,obj):
# temp = []
# for obj in obj.authors.all():
# temp.append(obj.name)
# print(temp)
# return temp
class PublishSeria(serializers.ModelSerializer):
class Meta:
model = Publish
fields = "__all__"
class BookSeria(serializers.ModelSerializer):
class Meta:
model = Book
fields = "__all__"
#显示超链接
publish = serializers.HyperlinkedIdentityField(
view_name='publish_detail',
lookup_field="publish_id",
lookup_url_kwarg="pk")
# 改成连接之后,重新增加book表的话会出错,显示找不到publish_id
#自定义显示字段 可以不加,不加自定义字段就显示全部字段 用自定义的话post请求要重写create方法
# publisher = serializers.CharField(source="publisher.pk",read_only=True)#一对多可以用 自定义字段
# authors = serializers.CharField(source="authors.all") #多对多不好用
#多对多用下面这个
# authors =serializers.SerializerMethodField() 自定义字段
# def get_authors(self,obj):
# temp = []
# for obj in obj.authors.all():
# temp.append(obj.name)
# print(temp)
# return temp
# 自定义显示字段 用自定义的话post请求要重写create方法,不自定义用默认的就不需要create方法
# def create(self, validated_data):
# print("validated_data",validated_data)
# book = Book.objects.create(title=validated_data["title"],price=validated_data["price"],pub_date=validated_data["pub_date"],publisher_id=validated_data["publisher"]["pk"])
# book.authors.add(*validated_data["authors"])
# return book
class AuthorSeria(serializers.ModelSerializer):
class Meta:
model = Author
fields = "__all__"
# 第一种: 以APIView方式
#认证组件 验证用户名 局部验证
# from rest_framework import exceptions
# from rest_framework.authentication import BaseAuthentication
# class UserTokenCheck(BaseAuthentication):
# def authenticate(self,request):
# token = request.GET.get("token")
# token_obj = UserToken.objects.filter(token=token).first()
# if not token_obj:
# raise exceptions.AuthenticationFailed("验证失败")
# else:
# return token_obj.userinfo.name,token_obj.token
#如果继承于BaseAuthentication,authenticate_header就不用写了
#如果不继承就要加上
# def authenticate_header(self,request):
# pass
#解析器---> 无论post(请求)前面传的是JSON数据还是urlencoded数据,rest framework 中的request.data都帮我们解析成字典,而django中的request.POST只解析urlencode数据
from rest_framework.parsers import JSONParser,FormParser,MultiPartParser,FileUploadParser #默认使用前三个解析器
在视图类中添加 parser_classes = [JSONPaser,] #如果只写这一个,意味着只能解析JSON数据 FormParser解析urlencode数据
默认parser_classes = [JSONParser,FormParser]这两个够用
#分页
from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination
class MyPageNumberPagination(PageNumberPagination):
page_size = 2 #每页显示多少条数据
page_query_param = "page" #URL中输入的 page=2
page_size_query_param = "size" #临时浏览器中使用127.0.0.1:8000/books/?page=2&size=2 第二页显示两条数据
max_page_size = 3 #上面的size最大值,不能无限制显示10000条数据
class MyLimitOffsetPagination(LimitOffsetPagination):
default_limit = 1
class BookView(APIView):
# authentication_classes = [UserTokenCheck,]
def get(self,request,):
book_list = Book.objects.all()
# 分页*****************
# page_num = MyPageNumberPagination()
page_num = MyLimitOffsetPagination()
books_pagenum = page_num.paginate_queryset(book_list, request, self)
bs = BookSeria(books_pagenum, many=True, context={"request": request})
# bs = BookSeria(book_list,many=True)
# bs = BookSeria(book_list, many=True,context={"request":request})
bookser = BookSeria(book_list,many=True,context={'request': request})
return Response(bookser.data)
def post(self,request):
print(request.data)
bookser = BookSeria(data=request.data,context={'request': request})
print(bookser)
if bookser.is_valid():
bookser.save()
return Response(bookser.data)
else:
return Response(bookser.errors)
class BookDetailView(APIView):
def get(self,request,pk):
book_obj = Book.objects.filter(pk=pk).first()
bookser = BookSeria(book_obj,context={'request': request})
return Response(bookser.data)
def put(self,request,pk):
book_obj = Book.objects.filter(pk=pk).first()
bookser = BookSeria(book_obj, data=request.data,context={'request': request})
print(bookser)
if bookser.is_valid():
bookser.save()
return Response(bookser.data)
else:
return Response(bookser.errors)
def delete(self,request,pk):
Book.objects.filter(pk=pk).first().delete()
return Response()
class PublishView(APIView):
def get(self, request, *args, **kwargs):
publish_list = Publish.objects.all()
bs = PublishSeria(publish_list, many=True, context={'request': request})
return Response(bs.data)
def post(self, request, *args, **kwargs):
bs = PublishSeria(data=request.data, many=False)
if bs.is_valid():
# print(bs.validated_data)
bs.save()
return Response(bs.data)
else:
return Response(bs.errors)
class PublishDetailView(APIView):
def get(self, request, pk):
publish_obj = Publish.objects.filter(pk=pk).first()
bs = PublishSeria(publish_obj, context={'request': request})
return Response(bs.data)
def put(self, request, pk):
publish_obj = Publish.objects.filter(pk=pk).first()
bs = PublishSeria(publish_obj, data=request.data, context={'request': request})
if bs.is_valid():
bs.save()
return Response(bs.data)
else:
return Response(bs.errors)
#
# # 第二种 通过mixins generics
#
# from rest_framework import mixins
# from rest_framework import generics
# class BookView(mixins.ListModelMixin,
# mixins.CreateModelMixin,
# generics.GenericAPIView):
#
# queryset = Book.objects.all()
# serializer_class = BookSeria
#
# def get(self,request,*args,**kwargs):
#
# return self.list(request,*args,**kwargs)
#
# def post(self, request, *args, **kwargs):
# print("===========")
# print(request.data)
# return self.create(request, *args, **kwargs)
#
# class BookDetailView(mixins.RetrieveModelMixin,
# mixins.UpdateModelMixin,
# mixins.DestroyModelMixin,
# generics.GenericAPIView):
# queryset = Book.objects.all()
# serializer_class = BookSeria
# def 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)
#
# class PublishView(mixins.ListModelMixin,
# mixins.CreateModelMixin,
# generics.GenericAPIView):
#
# queryset = Publish.objects.all()
# serializer_class = PublishSeria
#
# def get(self,request,*args,**kwargs):
#
# return self.list(request,*args,**kwargs)
#
# def post(self, request, *args, **kwargs):
# print("===========")
# print(request.data)
# return self.create(request, *args, **kwargs)
#
# class PublishDetailView(mixins.RetrieveModelMixin,
# mixins.UpdateModelMixin,
# mixins.DestroyModelMixin,
# generics.GenericAPIView):
#
# queryset = Publish.objects.all()
# serializer_class = PublishSeria
# def 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)
#第三种 简化通用类视图
# class BookView(generics.ListCreateAPIView):
#
# queryset = Book.objects.all()
# serializer_class = BookSeria
#
# class BookDetailView(generics.RetrieveUpdateDestroyAPIView):
# queryset = Book.objects.all()
# serializer_class = BookSeria
# class PublishView(generics.ListCreateAPIView):
#
# queryset = Publish.objects.all()
# serializer_class = PublishSeria
#
# class PublishDetailView(generics.RetrieveUpdateDestroyAPIView):
# queryset = Publish.objects.all()
# serializer_class = PublishSeria
#
#第四种
# from rest_framework import viewsets
# class BookViewSet(viewsets.ModelViewSet):
# queryset = Book.objects.all()
# serializer_class = BookSeria
# #权限组件
# from rest_framework.permissions import BasePermission
# class SVIPPermission(BasePermission): #继承于BasePermission,/authous/2/才能查看每个具体的作者。否则报错
# message = "只有超级用户才能访问"
# def has_permission(self,request,view):
# username = request.user
# print(username)
# user_type = UserInfo.objects.filter(name=username).first().user_type
# if user_type == 3:
# return True
# else:
# return False
# from book.service import SVIPPermission
from rest_framework import viewsets
#*********频率组件*********
from rest_framework.throttling import BaseThrottle
VISIT_RECORD={}
class VisitThrottle(BaseThrottle):
def __init__(self):
self.history=None
def allow_request(self,request,view):
remote_addr = request.META.get('REMOTE_ADDR')
print(remote_addr)
import time
ctime=time.time()
if remote_addr not in VISIT_RECORD:
VISIT_RECORD[remote_addr]=[ctime,]
return True
history=VISIT_RECORD.get(remote_addr)
self.history=history
while history and history[-1]<ctime-60:
history.pop()
if len(history)<10:
history.insert(0,ctime)
return True
else:
return False
def wait(self):
import time
ctime=time.time()
return 60-(ctime-self.history[-1])
class AuthorViewSet(viewsets.ModelViewSet):
# authentication_classes = [UserTokenCheck, ] #局部验证
# permission_classes = [SVIPPermission,]
throttle_classes = [VisitThrottle]
pagination_class = MyPageNumberPagination
queryset = Author.objects.all()
serializer_class = AuthorSeria
#生成随机token
def get_random_Str(name):
import hashlib,time
currenttime = str(time.time())
md5 = hashlib.md5(bytes(name,encoding="utf-8"))
md5.update(bytes(ctime,encoding='utf-8'))
return md5.hexdigest()
#用户登录
import json
from django.http import JsonResponse
class LoginView(APIView):
authentication_classes = [] #全局配置后,不让login验证,直接加空列表就不验证
def post(self,request):
print(request.data)
name = request.data.get("name")
pwd = request.data.get("pwd")
user_obj = UserInfo.objects.filter(name=name,pwd=pwd).first()
ret = {"status":"1000","msg":"验证成功"}
if user_obj:
random_str = get_random_Str(user_obj.name)
UserToken.objects.update_or_create(userinfo=user_obj,defaults={"token":random_str})
ret["token"]=random_str
else:
ret["status"] = 404
ret["msg"] = "用户名或者密码错误"
return JsonResponse(ret)
return Response(json.dumps(ret,ensure_ascii=False))
#全局配置验证
REST_FRAMEWORK = {
# "DEFAULT_AUTHENTICATION_CLASSES":["book.service.UserTokenCheck"],
# "DEFAULT_PERMISSION_CLASSES":["book.service.SVIPPermission"],
"PAGE_SIZE":1
}
from django.conf.urls import url,include
from django.contrib import admin
from book import views
#URL路由分发
from rest_framework import routers
routers=routers.DefaultRouter()
routers.register("authors",views.AuthorViewSet)
#会自动添加以下地址
# ^authors/$ [name='author-list']
# ^authors.(?P<format>[a-z0-9]+)/?$ [name='author-list']
# ^authors/(?P<pk>[^/.]+)/$ [name='author-detail']
# ^authors/(?P<pk>[^/.]+).(?P<format>[a-z0-9]+)/?$ [name='author-detail']
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^books/$',views.BookView.as_view()),
url(r'^books/(?P<pk>d+)/',views.BookDetailView.as_view()),
url(r'^publish/$',views.PublishView.as_view()),
url(r'^publish/(?P<pk>d+)/',views.PublishDetailView.as_view(),name="publish_detail"),
#第四种
# url(r'^books/$', views.BookViewSet.as_view({"get": "list", "post": "create"}), name="book_list"),
# url(r'^books/(?P<pk>d+)/$', views.BookViewSet.as_view({'get': 'retrieve',
# 'put': 'update','patch': 'partial_update',
# 'delete': 'destroy'}), name="book_detail"),
url(r'^authors/$', views.AuthorViewSet.as_view({"get": "list", "post": "create"}), name="author_list"),
url(r'^authors/(?P<pk>d+)/$', views.AuthorViewSet.as_view({'get': 'retrieve',
'put': 'update','patch': 'partial_update',
'delete': 'destroy'}), name="author_detail"),
url(r'^login/$', views.LoginView.as_view(), name="login"),
]