一、README

线上教育平台:
接口得开发

1.建表models.py
2.引用admin
3.createsuperuser root root!2345
4.CC视频上传(账号),video.html显示
https://admin.bokecc.com/main.bo
http://127.0.0.1:8000/ccvideo/ (可看到上传得视频)
5.v1.3 - 接口: (与登录 课程 文章相关得接口)
1.查询所有课程
http://127.0.0.1:8000/api/v1/courses/
http://127.0.0.1:8000/api/v1/courses/?page=2 (全局设置得分页)
http://127.0.0.1:8000/api/v1/course/
http://127.0.0.1:8000/api/v1/course/?page=2 (自定义设置得分页)

2.查询课程详细
http://127.0.0.1:8000/api/v1/courses/1/ (简单得内容,继承)
http://127.0.0.1:8000/api/v1/course/1/ (自定制)

3.用户登录
http://127.0.0.1:8000/api/v1/auth/

- 返回随机字符串token
uid = str(uuid.uuid4())
- 库里update_or_create 新增或修改token
models.UserToken.objects.update_or_create(user=user_obj,defaults={'token':uid})

4.登录之后才能访问得页面,文章相关
http://127.0.0.1:8000/api/v1/articles/?page=2&token=22abe8c6-717a-4b1b-a164-84d4c18aea5b
http://127.0.0.1:8000/api/v1/articles/2/?token=22abe8c6-717a-4b1b-a164-84d4c18aea5b

# 不同得视图函数
http://127.0.0.1:8000/api/v1/article/?page=2&token=22abe8c6-717a-4b1b-a164-84d4c18aea5b
http://127.0.0.1:8000/api/v1/article/2/?token=22abe8c6-717a-4b1b-a164-84d4c18aea5b

- 认证组件
authentication_classes = [LuffyAuth, ]
- 验证从前端传来得token是否存在
token = request.query_params.get("token")
存在,返回元祖 return (obj.user.user,obj)
不存在,抛异常 raise AuthenticationFailed({'code':1001,'error':'认证失败'})

5.对文章评论,需要先登录,所以接口有登录认证
http://127.0.0.1:8000/api/v1/article/1/comment/?token=22abe8c6-717a-4b1b-a164-84d4c18aea5b
post请求:
{"content":"评论得内容"}
{"content":"评论得内容","pid":5}

6.对文章点赞,需要登录认证
http://127.0.0.1:8000/api/v1/article/1/agree/?token=22abe8c6-717a-4b1b-a164-84d4c18aea5b
post请求:
不需要传什么,文章得id随着url传过去了。

7.对文章收藏,需要登录认证
http://127.0.0.1:8000/api/v1/article/4/collect/?token=22abe8c6-717a-4b1b-a164-84d4c18aea5b
post请求:
不需要传什么,文章得id随着url传过去了。
delete请求:
取消对文章得收藏

6.v1.4 - 接口:(与购物车 相关得接口,需要登录认证)
方案一: 这种方式不好,每次都要全部拿出来,修改,在放进去
http://127.0.0.1:8000/api/v1/shopping/?token=22abe8c6-717a-4b1b-a164-84d4c18aea5b
post请求:
购物车中添加一条数据 {"courseid":2,"policyid":3}
get请求:
查看自己购物车中的所有数据 ...
delete请求:
删除购物车中的数据 {"delete_ids":[1,2]}
put请求:
更新价格策略 ... {"courseid":2,"policyid":3}

方案二:数据结构得设计好坏,直接影响了代码实现得复杂度;
http://127.0.0.1:8000/api/v1/shoppingcart/?token=22abe8c6-717a-4b1b-a164-84d4c18aea5b
post请求:
{"courseid":2,"policyid":3}
delete请求:
{"courseids":[1,2]}
patch请求:
{"courseid":2,"policyid":3}
get请求:
...

7.v1.5 - 接口:(与支付中心 相关得接口,需要登录认证)
方式一:这种方式不好,查询数据时,每次都要去数据库查询,优惠劵,逻辑还有点问题,查看版本二.
http://127.0.0.1:8000/api/v1/payment/?token=22abe8c6-717a-4b1b-a164-84d4c18aea5b
post请求:
将购物车得课程,加入到支付中心
{"courseids":[1,2]}
get请求:
获取支付中心得数据
。。。
patch请求:
修改课程得优惠券
{"courseid":1,"couponid":1}

方式二:
http://127.0.0.1:8000/api/v1/paymentview/?token=22abe8c6-717a-4b1b-a164-84d4c18aea5b
post请求:
将购物车得课程,加入到支付中心
{"courseids":[1,2]}
get请求:
获取支付中心得数据
。。。
patch请求:
修改课程得优惠券,全局得优惠劵
{"courseid":1,"couponid":1,"gcouponid":5}

8.v1.6 - 接口:(生成订单得接口,需要登录认证)
http://127.0.0.1:8000/api/v1/order/?token=22abe8c6-717a-4b1b-a164-84d4c18aea5b
post请求:
将redis中,支付中心得数据,生成订单,存到数据库中
{"balance":1000,"money":245} # balance用户得抵扣得贝里数,money是实付金额
对于用户,前端传来得数据,后台入库之前,一定要做校验,验证合法性。
           

二、v1.3 - 知识点 - 登录、课程、文章相关得接口 

版本 分页

REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES':['rest_framework.renderers.JSONRenderer','rest_framework.renderers.BrowsableAPIRenderer'],
    'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.URLPathVersioning',
    'ALLOWED_VERSIONS': ['v1', 'v2'],  # 允许的版本
    'VERSION_PARAM': 'version',  # 参数
    'DEFAULT_VERSION': 'v1',  # 默认版本
    "DEFAULT_PAGINATION_CLASS":"rest_framework.pagination.PageNumberPagination",
    "PAGE_SIZE":1,
}

 

from rest_framework.pagination import PageNumberPagination


class MyPageNumberPagination(PageNumberPagination):
    page_size = 1
    page_query_param = "page"
    

 

urls.py

url(r'^api/(?P<version>\w+)/',include('api.urls')),

-------------------------------------------------

from django.conf.urls import url, include
from rest_framework import routers

from api.views import course, account, article

routers = routers.DefaultRouter()
routers.register("courses", course.CourseViewSet)
routers.register("articles", article.ArticelViewSet)

urlpatterns = [
    url(r'^auth/$', account.AuthView.as_view()),

    url(r'^', include(routers.urls)),

    url(r'^course/$', course.CourseView.as_view({"get": "list"})),
    url(r'^course/(?P<pk>\d+)/$', course.CourseView.as_view({"get": "retrieve"})),

    url(r'^article/$', article.ArticleView.as_view({"get": "list"})),
    url(r'^article/(?P<pk>\d+)/$', article.ArticleView.as_view({"get": "retrieve"})),
    url(r'^article/(?P<pk>\d+)/comment/$', article.CommentView.as_view()),  # 对文章评论
    url(r'^article/(?P<pk>\d+)/agree/$', article.AgreeView.as_view()),  # 对文章点赞
    url(r'^article/(?P<pk>\d+)/collect/$', article.CollectView.as_view()),  # 对文章收藏、取消(post delete)

]

 

中间件 - 跨域处理 cors.py

from django.utils.deprecation import MiddlewareMixin


class CORSMiddleware(MiddlewareMixin):
    def process_response(self, request, response):
        # 允许你的域名来访问
        response['Access-Control-Allow-Origin'] = "*"

        if request.method == 'OPTIONS':
            # 允许你携带 Content-Type 请求头 不能写*
            response['Access-Control-Allow-Headers'] = 'Content-Type'
            # 允许你发送 DELETE PUT请求
            response['Access-Control-Allow-Methods'] = 'DELETE,PUT'

        return response
       

 

课程  文章  登录  (相关得接口)

涉及到 

  分页 

  视图    ViewSetMinin  ModelViewSet  APIView

  序列化   

  认证    authentication_classes = [LuffyAuth, ]

  事务    with transaction.atomic(): ... ... 

  异常    try ... except  异常捕获

# -*- coding:utf-8 -*-
from rest_framework import mixins
from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.viewsets import ViewSetMixin, GenericViewSet

from utils.response import BaseResponse
from api.models import Course, CourseDetail
from utils.paginator import MyPageNumberPagination
from api.serializers.course import CourseSerializers, CourseDetailSerializers


class CourseView(ViewSetMixin, APIView):
    """
    课程相关得接口
    """
    def list(self, request, *args, **kwargs):
        """
        查看全部课程
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        ret = BaseResponse()
        pnp = MyPageNumberPagination()
        try:
            course_list = Course.objects.all()
            courses_page = pnp.paginate_queryset(course_list, request, self)
            ser = CourseSerializers(courses_page, many=True)
            ret.data = ser.data
        except Exception as e:
            ret.code = "1001"
            ret.error = "获取课程失败"

        return pnp.get_paginated_response(ret.dict)

    def retrieve(self, request, *args, **kwargs):
        """
        查看单条课程
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        ret = BaseResponse()
        try:
            pk = kwargs.get("pk")
            course_obj = CourseDetail.objects.filter(course_id=pk).first()
            ser = CourseDetailSerializers(instance=course_obj, many=False)
            ret.data = ser.data
        except Exception as e:
            ret.code = 1001
            ret.data = "获取课程失败"
        return Response(ret.dict)


class CourseViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet):
    """
    查看全部、单条课程
    """
    queryset = Course.objects.all()
    serializer_class = CourseSerializers


def video(request):
    """ 播放视频 """
    return render(request, 'video.html')
course.py

相关文章: