免费课程相关表设计

models的设计

from django.contrib.contenttypes.fields import GenericRelation
class Course(models.Model):
name = models.CharField(verbose_name="课程名", max_length=32)
title = models.CharField(verbose_name="课程简介", max_length=128, null=True, blank=True)
# 存放media文件夹下图片的相对路径:eg: media/python入门.jpeg
image = models.CharField(verbose_name="海报", max_length=64, null=True, blank=True)
# 用户连表查询,不会在数据库中产生字段
price_policy = GenericRelation(to='PricePolicy') def __str__(self):
return self.name
class Meta:
verbose_name_plural = "免费课程" class CourseDetail(models.Model):
level = models.IntegerField(default=1, choices=((0, '初级'), (1, "中级"), (2, "高级")))
movie_url = models.CharField(max_length=64)
info = models.TextField()
course = models.OneToOneField(to='Course', null=True, on_delete=models.SET_NULL, db_constraint=False)
teacher = models.OneToOneField(to='Teacher', null=True, on_delete=models.SET_NULL, db_constraint=False) def __str__(self):
return self.course.name + '的详情'
class Meta:
verbose_name_plural = "免费课程详情" class Teacher(models.Model):
name = models.CharField(max_length=32)
info = models.TextField()
image = models.CharField(max_length=64)
level = models.IntegerField(default=0, choices=((0, '初级讲师'), (1, "金牌讲师"), (2, "特约讲师")))
def __str__(self):
return self.name
class Meta:
verbose_name_plural = "讲师" class DegreeCourse(models.Model):
name = models.CharField(max_length=32)
price_policy = GenericRelation(to='PricePolicy')
def __str__(self):
return self.name
class Meta:
verbose_name_plural = "学位课程" from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey
class PricePolicy(models.Model):
day = models.IntegerField()
price = models.CharField(max_length=8)
object_id = models.IntegerField()
content_type = models.ForeignKey(to=ContentType, null=True)
# 改操作只用于ContentType连表查询,不会产生表字段, 就是关联课程表的对象
model_obj = GenericForeignKey() def __str__(self):
return "%s:(%s天 ¥:%s)" % (self.model_obj.name, self.day, self.price) class Meta:
verbose_name_plural = "价格策略"

前台路由与页面

APP.vue组件

<div id="nav">
<router-link to="/">主页</router-link>
|
<router-link to="/login">登录</router-link>
|
<router-link to="/course">免费课程</router-link>
|
<!-- 在页面中转跳路由传递参数, 传递了params参数,this.$router.params可以拿到这个参数字典 -->
<!--<router-link :to="{'name': 'degree-course', 'params': {'id': 1, 'name': 'owen'}}">学位课程</router-link>-->
<router-link :to="{'name': 'degree-course'}">学位课程</router-link>
</div>

router.js路由配置

# 在views文件夹中建立对应的组件
{
path: '/login',
name: 'login',
component: () => import('./views/Login.vue')
},
{
path: '/course',
name: 'course',
component: () => import('./views/Course.vue')
},
{
path: '/degree-course',
name: 'degree-course',
component: () => import('./views/DegreeCourse.vue')
},
{
path: '/course-detail',
name: 'course-detail',
component: () => import('./views/CourseDetail.vue')
}

项目开发视图与响应的二次封装

响应

# api.utils.py
class ApiResponse:
def __init__(self, status=0, message='ok'):
self.status = status
self.message = message
# 要返回给前台的api字典
@property
def api_dic(self):
return self.__dict__

视图

# 在api应用文件夹下创建包views
# 1.分文件管理不同的视图类,视图类继承ModelViewSet管理一系列视图函数
# 2.在__ini__文件中统一管理到 视图类 # __init__.py
from .Course import CourseView # views文件夹/Course文件/CourseView
from rest_framework.viewsets import ModelViewSet
from rest_framework.response import Response
from api.utils import ApiResponse
from api import models, objectjson class CourseView(ModelViewSet):
def get(self, request, *args, **kwargs):
api_response = ApiResponse()
course_list = models.Course.objects.all()
course_data = objectjson.CourseJson(course_list, many=True).data
api_response.results = course_data
return Response(api_response.api_dic)

免费课程首页展示

main.js配置后台请求根路径

// 后台根接口
Vue.prototype.$base_api = 'http://127.0.0.1:8000/';

views/Course.vue

<template>
<div class="course">
<h2>免费课程</h2>
<!--course_list是从后台获取,有多少条数据,就会渲染多少个子组件CourseView-->
<div v-for="(course,i) in course_list" :key="course.name+i">
<!--通过绑定属性的方式,将course传给属性course,在组件内部提高props=['course']拿到父组件的数据-->
<CourseView :course="course"></CourseView>
</div>
</div>
</template> <script>
import CourseView from "../components/CourseView"; export default {
name: "Course",
data: function () {
return {
course_list: []
}
},
components: {
CourseView: CourseView,
},
mounted: function () {
let _this = this;
this.$ajax({
method: 'get',
url: this.$base_api + 'courses/',
}).then(function (response) {
_this.course_list = response.data.results
})
}
}
</script> <style scoped> </style>

components/CourseView.vue

<template>
<div class="course-view">
<div class="box">
<h3 @click="goDetail(course.id)">{{course.name }}</h3>
<p>{{ course.title }}</p>
</div>
<img @click="goDetail(course.id)" :src="$base_api + course.image" alt="">
</div>
</template> <script>
export default {
name: "CourseView",
props: ['course'],
methods: {
goDetail: function (pk) {
//前往详情页,在方法中,router如何完成路由的跳转
this.$router.push('/course-detail');
// 业务逻辑下,路由转跳携带参数
this.$router.course_id = pk;
window.console.log(pk)
}
}
}
</script> <style scoped>
.course-view {
padding: 0 200px;
margin: 25px 0;
} .course-view .box {
float: left;
width: 380px;
} .course-view img {
width: 400px;
float: left;
} .course-view:after {
display: block;
clear: both;
content: '';
}
</style>

views/Course.vue/CourseDetail.vue

<template>
<div class="course-detail">
<h2>免费课程详情</h2>
<p>{{ detail }}</p>
</div>
</template> <script>
export default {
name: "CourseDetail",
data: function () {
return {
detail: {},
}
},
mounted: function () {
let _this = this;
this.$ajax({
method: 'get',
url: this.$base_api + 'course/' + this.$router.course_id + '/',
}).then(function (response) {
window.console.log(response);
_this.detail = response.data.results;
})
}
}
</script> <style scoped> </style>

前后台登录认证

时区国际化settings.py

TIME_ZONE = 'Asia/Shanghai'
USE_TZ = False

models.py

class User(models.Model):
username = models.CharField(max_length=32)
password = models.CharField(max_length=32) class UserToken(models.Model):
token = models.CharField(max_length=64)
user = models.OneToOneField(to='User', null=True, on_delete=models.SET_NULL, db_constraint=False)
update_time = models.DateTimeField(auto_now=True)
failed_time = models.FloatField(default=10)

objectson.py

class UserJson(serializers.ModelSerializer):
class Meta:
model = models.User
fields = '__all__' class UserTokenJson(serializers.ModelSerializer):
class Meta:
model = models.UserToken
fields = '__all__'

auth.py

from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed from api import models class LoginAuthenticate(BaseAuthentication):
def authenticate(self, request):
token = request.META.get('HTTP_TOKEN')
result = models.UserToken.objects.filter(token=token).first() # type:models.UserToken
if result:
# 最近一次登录的时间
before_time = result.update_time
# 过期时长秒数
failed_time = result.failed_time
# 当你时间往前推演到过期的时长前的最后时刻
import datetime
time_difference = datetime.datetime.now() - datetime.timedelta(seconds=failed_time)
import time
# 存在时区问题,通过国际化解决
before_time_stamp = time.mktime(before_time.timetuple()) # 拿到时间戳
time_difference_stamp = time.mktime(time_difference.timetuple())
if before_time_stamp >= time_difference_stamp:
return result.user, token
raise AuthenticationFailed('登录过期')
else:
raise AuthenticationFailed('认证失败')

前台安装操作cookie的模块

<template>
<div class="login">
<h2>登录页面</h2>
<div class="form">
<el-form :model="form" label-width="100px">
<el-form-item label="用户名">
<el-input v-model="form.username"></el-input>
</el-form-item>
<el-form-item label="密码">
<el-input type="password" v-model="form.password" autocomplete="off"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">登录</el-button>
</el-form-item>
</el-form>
</div>
</div>
</template> <script>
export default {
name: "Login",
data: function () {
return {
form: {
username: '',
password: '',
}
}
},
methods: {
onSubmit() {
// window.console.log('aaaa');
let _this = this;
this.$ajax({
method: 'post',
url: this.$base_api + 'login/',
data: {
username: this.form.username,
password: this.form.password
}
}).then(function (response) {
window.console.log(response);
let token = response.data.token;
_this.$cookie.set('token', token);
_this.$router.push('/')
})
}
}
}
</script> <style scoped> </style>

router.js

{
path: '/login',
name: 'login',
component: () => import('./views/Login.vue')
},

登录、认证、token处理、前台cookie存储token的更多相关文章

  1. app与php后台接口登录认证、验证(seesion和token)

    简要:随着电商的不断发展,APP也层次不穷,随着科技的发展主要登录形式(微信.QQ.账号/密码):为此向大家分享一下"app与php后台接口登录认证.验证"想法和做法:希望能够帮助 ...

  2. 如何区别cookie和token?---测试cookie和token接口时先看。

    cookie 是什么? cookie--------------在浏览器中的长相?火狐浏览器 ----------------------------------------------------- ...

  3. cookie session token详解

    cookie session token详解 转自:http://www.cnblogs.com/moyand/ 发展史 1.很久很久以前,Web 基本上就是文档的浏览而已, 既然是浏览,作为服务器, ...

  4. Cookie、Token与Session介绍(非原创)

    文章大纲 一.Cookie介绍二.Token介绍三.Session介绍四.Token.Cookie与Session比较五.参考文章   一.Cookie介绍 1. Cookie是什么 cookie机制 ...

  5. cookie,session,token介绍

    本文目录 发展史 Cookie Session Token 回到目录 发展史 1.很久很久以前,Web 基本上就是文档的浏览而已, 既然是浏览,作为服务器, 不需要记录谁在某一段时间里都浏览了什么文档 ...

  6. cookie,session,token的理解

    Get  POST 区别异同点 淘宝token的 理解   过程算法 防止伪造请求  伪造相对难 简单发展史  登录的操作: 哪些人往自己的购物车中放商品,  也就是说我必须把每个人区分开,这就是一个 ...

  7. session、cookie、token

    各自应用场景考虑session.token.cookie是不是有各自的应用场景,比如传统项目适合用session和cookie单页应用适合用token分布式适合用token等等 token如果非要选择 ...

  8. 基于JWT的Token登录认证(一)

    1.JWT简介 JSON Web Token(缩写 JWT),是目前最流行的跨域认证解决方案. session登录认证方案:用户从客户端传递用户名.密码等信息,服务端认证后将信息存储在session中 ...

  9. 权限认证 cookie VS token

    权限认证 cookie VS token 我前公司的应用都是 token 授权的,现公司都是维护一个 session 确认登录状态的.那么我在这掰扯掰扯这两种权限认证的方方面面. 工作流程 先说 co ...

随机推荐

  1. go module 获取码云私有仓库代码

    因为码云免费组织有5人限制,其他人想获得代码 只能通过别的方式 go mod 底层使用的git 获取代码, 所以首先解决如何通过git clone代码 思路为通过ssh密钥的方式获取 首先在码云仓库部 ...

  2. JavaScript学习系列博客_11_JavaScript中的for语句

    for循环 - 语法: for(①初始化表达式 ; ②条件表达式 ; ④更新表达式){ ③语句... } - 执行流程: 首先执行①初始化表达式,初始化一个变量,(这里只会执行一次) 然后对②条件表达 ...

  3. 12. oracle 常用函数

    一.字符函数字符函数是oracle中最常用的函数,我们来看看有哪些字符函数:lower(char):将字符串转化为小写的格式.upper(char):将字符串转化为大写的格式.length(char) ...

  4. centos7 + nginx+django 运行环境

    .easy_install和pip都是用来下载安装Python一个公共资源库PyPI的相关资源包的 首先安装easy_install 下载地址:https://pypi.python.org/pypi ...

  5. 深入理解k8s中的访问控制(认证、鉴权、审计)流程

    Kubernetes自身并没有用户管理能力,无法像操作Pod一样,通过API的方式创建/删除一个用户实例,也无法在etcd中找到用户对应的存储对象. 在Kubernetes的访问控制流程中,用户模型是 ...

  6. 计算机网络-网络层(6)ICMP协议

    互联网控制报文协议(ICMP,Internet Control Message Protocol),被主机和路由器用来彼此沟通网络层的信息 ICMP报文是承载在IP分组中的,即lCMP报文是作为IP有 ...

  7. Eligibility Traces and Plasticity on Behavioral Time Scales: Experimental Support of neoHebbian Three-Factor Learning Rules

    郑重声明:原文参见标题,如有侵权,请联系作者,将会撤销发布! Abstract 大多数基本行为,如移动手臂抓住物体或走进隔壁房间探索博物馆,都是在几秒钟的时间尺度上进化的:相反,神经元动作电位则是在几 ...

  8. 牛客网PAT练兵场-打印沙漏

    题目地址:https://www.nowcoder.com/pat/6/problem/4053 题意:模拟题 /** * Copyright(c) * All rights reserved. * ...

  9. 玩转Spring——Spring事务

    事务的概念:多个sql 操作 要么都成功 要么都失败 ACID特性:原子性(Atomicity)原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生.一致性(Consisten ...

  10. ms-data(转载)

    转载:https://www.cnblogs.com/zll-52011/p/10960905.html 1.从美国矿物数据库下载矿物CIF(有晶格) 2.晶胞CIF导入MS 3.选择display ...