目录
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
}
})
},