高考加油!
带好证件!

Django Api----djangorestframwork

2021-05-10 大聪明 0评论 42 1喜欢

Django restframwork

一切皆是资源,操作只是请求方式。

url里面不能出现任何一个动词

https://www.cnblogs.com/yuanchenqi/articles/8719520.html

pip install djangorestframework

使用

先到app中注册

# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'blog.apps.BlogConfig',
    'rest_framework',
]

views.py

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.renderers import JSONRenderer, BrowsableAPIRenderer
from django.shortcuts import HttpResponse
from rest_framework.versioning import QueryParameterVersioning, URLPathVersioning

# Create your views here.
class CourseView(APIView):
    renderer_classes = [JSONRenderer, BrowsableAPIRenderer]

    def get(self, request, *args, **kwargs):
        # self.dispatch
        print(request.version)
        return Response('....')
        # return HttpResponse('ok')

setting

版本

# restframework Version
REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': ['rest_framework.renderers.JSONRenderer', 'rest_framework.renderers.BrowsableAPIRenderer'],
    # 版本问题
    # 'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.QueryParameterVersioning',
    # 'ALLOWED_VERSIONS': ['v1', 'v2'],  # 允许的斑斑
    # 'VERSION_PARAM': 'version',  # 参数
    # 'DEFAULT_VERSION': 'v1',  # 默认版本
    'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.URLPathVersioning',
}


urlpatterns = [
    # re_path(r'^(?P<version>[v1|v2]+)/course/$', views.CourseView.as_view()),
    path('course/', views.CourseView.as_view()),
]

在mounted方法中发ajax请求后端api拿数据(axios) npm install axios --save

解决跨域问题

axios XHR network error

加响应头

from django.utils.deprecation import MiddlewareMixin


class CORSMiddleWare(MiddlewareMixin):

    def process_response(self, request, response):  # 必须定义这个名字的方法,两个参数也是必须写的
        # 添加响应头解决跨域问题
        # 允许你的域名来获取我的数据
        # response['Access-Control-Allow-Origin'] = "http://127.0.0.1:8080"
        # 允许所有
        response['Access-Control-Allow-Origin'] = "*"
        # 允许你携带Content-Type请求头, 不能写* 可以 , 加
        response['Access-Control-Allow-Headers'] = "Content-Type"
        # 允许你发送DELETE,PUT请求
        response['Access-Control-Allow-Methods'] = "DELETE,PUT"


        return response

restframework序列化queryset

restframework下的APIView

继承了Django的View

APIView下的dispatch()构建了一个新的request

request.data POSTde 数据都可以拿到

request.GET 拿到get的数据

from api import models

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.viewsets import ViewSetMixin
from rest_framework import serializers
from rest_framework.pagination import PageNumberPagination


class ArticleSerializers(serializers.ModelSerializer):
    # 自定义字段处理的onetoone/fk/choice
    category = serializers.CharField(source='category.name')
    # manytomany
    author = serializers.SerializerMethodField()
    tag = serializers.SerializerMethodField()

    class Meta:
        model = models.Article
        fields = ['title', 'author', 'content', 'desc', 'cover', 'add_time', 'upup', 'downdown', 'click_count',
                  'category', 'update_time', 'tag']

    # SerializerMethodField要定义get方法
    def get_tag(self, obj):
        # 获取所有的文章标签
        queryset = obj.tag.all()
        return [{'id':row.id, 'name':row.name, 'article_num':row.get_items()} for row in queryset]

    def get_author(self, obj):
        # 获取所有的文章标签
        queryset = obj.author.all()
        return [{'id':row.id, 'name':row.username} for row in queryset]


class PNPagination(PageNumberPagination):
    page_size = 2
    page_query_param = 'page'
    page_size_query_param = "size"
    max_page_size = 5


# 要重写as_view方法必须继承ViewSetMixin
class ArticleView(ViewSetMixin, APIView):

    def list(self, request, *args, **kwargs):
        """:arg
        文章列表接口
        """
        # 分页器
        page = PNPagination()
        ret = {'code': 200, 'data':None}
        try:
            queryset = models.Article.objects.all()
            page_list = page.paginate_queryset(queryset, request, self)
            ser = ArticleSerializers(instance=page_list, many=True)  # 如果单个序列化对象则many=False
            ret['data'] = ser.data
        except Exception as e:
            ret['code'] = '500'
            ret['error'] = '获取文章信息失败!'
        return Response(ret)

    def retrieve(self, request, *args, **kwargs):
        """:arg课程详细接口"""
        ret = {'code': 200, 'data': None}
        try:
            pk = kwargs.get('pk')
            obj = models.Article.objects.filter(id=pk).first()
            ser = ArticleSerializers(instance=obj, many=False)  # 如果单个序列化对象则many=False
            ret['data'] = ser.data
        except Exception as e:
            ret['code'] = '500'
            ret['error'] = '获取文章详细信息失败!'
        return Response(ret)

如果定制了多对多显示方法,还要进行bs.validate()下的bs.save()的话,则需要重写create方法

超链接字段

序列化时要加 context{"request": request}

视图

as_view传参 字典,指定get等方法用什么方法去处理

{'get':'list', 'put':'update', 'delete':'destroy', 'post':'create'}
{'get':'retrieve', 'put':'update', 'delete':'destroy', 'post':'create'}

# 评论
path('comment/', comment.CommentView.as_view({'get': 'list', 'post': 'create'})),
re_path(r'^comment/(?P<pk>\d+)/$', comment.CommentView.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),

# view
from rest_framework.viewsets import ModelViewSet
from api import models
from rest_framework import serializers
from rest_framework.pagination import PageNumberPagination


class CommentModelSerializers(serializers.ModelSerializer):

    class Meta:
        model = models.Comment
        fields = "__all__"
    # 自定义字段需要重写save方法
    # 自定义错误信息等


# 分页
class PNPagination(PageNumberPagination):
    page_size = 2
    page_query_param = 'page'
    page_size_query_param = "size"
    max_page_size = 5


class CommentView(ModelViewSet):
    queryset = models.Comment.objects.all()
    serializer_class = CommentModelSerializers
    pagination_class = PNPagination

认证与权限组件

认证

from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from api import models


class UserAuth(BaseAuthentication):

    def authenticate(self, request):
        ret = {'code': 200}
        token = request.query_params.get('token')
        obj = models.UserToken.objects.filter(token=token).first()
        if obj:
            return obj.username.username, obj
        else:
            ret = {'code':500, 'error': 'token值不正确!'}
            raise AuthenticationFailed(ret)

class CommentView(ModelViewSet):
    queryset = models.Comment.objects.all()
    serializer_class = CommentModelSerializers
    pagination_class = PNPagination
    # authentication_classes = [UserAuth, ]

REST_FRAMEWORK = {
    # 全局认证
    # "DEFAULT_AUTHENTICATION_CLASSES":["api.utils.userauth.UserAuth",]
}

权限

class UserPermission(object):
    message = '只有管理员才可以访问!'
    def has_permission(self, request, view):
        username = request.user
        user_obj = models.UserInfo.objects.filter(username=username).first()
        print(user_obj)
        if user_obj and user_obj.is_superuser:
            print(user_obj.is_superuser)
            return True
        else:
            return False


class CommentView(ModelViewSet):
    queryset = models.Comment.objects.all()
    serializer_class = CommentModelSerializers
    pagination_class = PNPagination
    authentication_classes = [UserAuth, ]
    permission_classes = [UserPermission, ]

频率

解析器

uri控制

分页

响应器

Responce:浏览器响应的一种方式。

发表评论 取消回复

电子邮件地址不会被公开。

请输入正确格式的qq邮箱
请输入以http或https开头的URL,格式如:https://libo_sober.top