• 前后端分离 项目(一)


    1. 后端Django项目

    目录结构:

    (1)settings.py文件

    # 下载 处理跨域问题的app:
    pip install django-cors-headers
    
    # 注册app:
    
    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'api.apps.ApiConfig',
        'corsheaders'  # 注册app
    ]
    
    # 注册中间件:
    
    MIDDLEWARE = [
        'corsheaders.middleware.CorsMiddleware', # 必须放在第一个位置
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
    ]
    
    # corsheaders配置项:
    CORS_ORIGIN_ALLOW_ALL = True  # 允许所有人 跨域请求 我的服务端
    

    (2)api/models.py文件

    项目表结构设计

    • 课程相关

      • 课程类表CourseCategory
      • 专题课程表Course
      • 课程详情表CourseDetail
      • 老师表Teacher
      • 价格与有课程效期表PricePolicy
      • 课程章节表CourseChapter
      • 课时目录表CourseSection
      • 常见问题表OftenAskedQuestion
    • 优惠券相关

      • 优惠券生成规则Coupon
      • 优惠券发放、消费纪录CouponRecord
    • 订单相关

      • 订单Order
      • 订单详情OrderDetail
    • 用户相关

      • 用户表UserInfo -- 继承AbstractUser
      • Token

    注意:settings.py文件中添加配置项

    # 告诉Django用我自己写的 UserInfo表 代替内置的 User表
    AUTH_USER_MODEL = 'api.UserInfo'    # app名.表名
    

    (3)api/admin.py文件

    from django.contrib import admin
    from api import models
    
    admin.site.register(models.Course)			# 课程表
    admin.site.register(models.CourseDetail)	# 课程详情表
    admin.site.register(models.CourseCategory)	# 课程分类表
    admin.site.register(models.CourseChapter)	# 课程章节表
    
    • 创建超级用户
    python manage.py createsuperuser
    
    • 启动Django项目, 进入admin页面, 对以上四个表的数据进行修改

    (4)urls.py文件

    路由分发:

    from django.conf.urls import url, include
    from django.contrib import admin
    
    urlpatterns = [
        url(r'^api/', include('api.urls')),
    ]
    

    (5)api/urls.py文件

    路由匹配:

    from django.conf.urls import url
    from api.views import course as course_view
    from api.views import login as login_view
    
    urlpatterns = [
        # 课程展示
        url(r'courses/$', course_view.CourseListView.as_view()),
    ]
    

    (6)api/views/course.py文件

    from rest_framework.generics import ListAPIView
    from api import models
    from api.serializers.course import CourseModelSerializer
    from rest_framework.response import Response
    
    class CourseListView(ListAPIView):
        queryset = models.Course.objects.all()
        serializer_class = CourseModelSerializer
        
        def get(self, request, *args, **kwargs):
            """"重写ListAPIView的get方法"""
            pass
    

    由于是前后端分离, 对于视图函数CourseListView, 我们要返回一个合适的接口, 因此,

    必须重写父类的get方法. 这个时候, 就需要看一看ListAPIView的源码了.

    • ListAPIView源码:

    • 点击进入list方法:

    现在, 我们回归到本来的问题上, 我们要重写ListAPIView的get方法, 从而返回一个合适的接口, 但是, 由于ListAPIView本身也有一些功能, 如果我们直接重写, 势必会对其他功能造成影响. 我们的解决办法是: 将list方法功能相关的代码直接粘贴到我们重写的get方法里, 然后在不改动这些代码的前提下, 进行我们自己的处理(主要是处理返回值, 即接口).

    course.py文件:

    from rest_framework.generics import ListAPIView
    from api import models
    from api.serializers.course import CourseModelSerializer
    from rest_framework.response import Response
    
    class CourseListView(ListAPIView):
        queryset = models.Course.objects.all()
        serializer_class = CourseModelSerializer
        
        def get(self, request, *args, **kwargs):
            try:
                #### list源码 ####
                queryset = self.filter_queryset(self.get_queryset())
                page = self.paginate_queryset(queryset)
                if page is not None:
                    serializer = self.get_serializer(page, many=True)
                    return self.get_paginated_response(serializer.data)
                serializer = self.get_serializer(queryset, many=True)
                #### list源码 ####
                data = serializer.data
            except Exception as e:
                code = 1
                msg = str(e)
            res = {'code': code, 'data': data, 'msg': msg}
            return Response(res)
    

    上面代码中, res这个字典就是我们与前端交互的接口. 由于每次都要自己硬编码该字典内部的key和value, 这样的做法是不可靠且极为繁琐的, 因此, 我们考虑将它们封装为一个对象. 如下所示:

    • 工具类: utils/response.py文件
    class BaseResponse(object):
    
        def __init__(self):
            self.code = 1000  # 状态码
            self.data = None  # 具体数据
            self.msg = ''     # 提示信息
    
        @property
        def dict(self):
            return self.__dict__  # __dict__把类的属性以字典的形式返回
    

    course.py文件: 改进版本

    from rest_framework.generics import ListAPIView
    from api import models
    from api.serializers.course import CourseModelSerializer
    from rest_framework.response import Response
    from utils.response import BaseResponse	# 引入自定义工具类
    
    class CourseListView(ListAPIView):
        queryset = models.Course.objects.all()
        serializer_class = CourseModelSerializer
        
        def get(self, request, *args, **kwargs):
            res_obj = BaseResponse()	# 实例化自定义工具类
            try:
                #### list源码 ####
                queryset = self.filter_queryset(self.get_queryset())
                page = self.paginate_queryset(queryset)
                if page is not None:
                    serializer = self.get_serializer(page, many=True)
                    return self.get_paginated_response(serializer.data)
                serializer = self.get_serializer(queryset, many=True)
                #### list源码 ####
                res_obj.data = serializer.data	# 赋值给data属性
            except Exception as e:
                res_obj.code = 1		  # 赋值给code属性
                res_obj.msg = str(e)	  # 赋值给msg属性
            return Response(res_obj.dict) # 通过dict方法就可以拿到所有属性组成的字典
    

    (7)api/serializers/course.py文件

    自定义序列化类CourseModelSerializer:

    from rest_framework import serializers
    from api import models
    
    class CourseModelSerializer(serializers.ModelSerializer):
        class Meta:
            model = models.Course
            fields = "__all__"
    

    2. 前端Vue项目

    (1)src/main.js文件

    配置根URL:

    // 导入Axios
    import Axios from 'axios'
    Axios.defaults.baseURL = 'http://127.0.0.1:8001/api';
    Vue.prototype.$axios = Axios;
    

    (2)src/router.js文件

    路由匹配:

    import Course from './views/Course.vue'
    
    Vue.use(Router);
    export default new Router({
        routes: [
                    {
                path: '/course',
                name: 'course',
                component: Course,
            },
        ]
    })
    

    (3)src/views/Course.vue文件

    自定义组件Course.vue:

    getCourseList() {
        this.$axios.get('/courses/')    // 修改路径,要与后端的路径信息相匹配
            .then((res) => {            // res 是接收到的后段的返回值
                // console.log(res);
                if (res.data.code === 1000) {   // code状态码
                    this.courseList = res.data.data;    // data具体数据信息
                    // 去掉加载动画
                    this.loading = false
                }
            })
    },
    
  • 相关阅读:
    WCF全面解析学习之地址Address(1)
    【转】理解和使用Oracle 8i分析工具-LogMiner
    【Wonder原创】NHibernate映射文件范例
    【转】C#经典面试题及答案
    【转】C#中abstract class和interface之探讨
    【转】130道C#面试题
    【Oracle学习】archivelog
    【转载】sql server 2005系统表详细说明
    【转】WINDOWS批处理命令详解
    【转】Linux find命令详解
  • 原文地址:https://www.cnblogs.com/haitaoli/p/10300651.html
Copyright © 2020-2023  润新知