Karen


  • 首页

  • 关于

  • 标签

  • 分类

  • 归档

  • 搜索

未命名

发表于 2018-07-17

用户模块的项目拆分:

  • 注册:form提交,ajax加载

post

前端可以有一层验证,但是后端必须要有

  1. 验证数据完整性:
  2. 验证手机号码的正确性:

​ re.match():第一位开始

​ re.search():任意位置开始

  1. 验证密码:
  2. 保存用户数据:

​ 如果有用户信息:

​ 如果没有:

​ 写字段并保存

返回

  • 登录

mobile

password

  1. 验证数据完整性

  2. 验证手机正确性

  3. 验证用户存不存在

  4. 验证密码是否正确

    ​ 验证用户成功:向session写东西

    session

    配置

    ​ app.config[‘SECRET_KEY’] = ‘secret_key’

    ​ app.config[‘SESSION_TYPE’] = ‘redis’

    ​ app.config[‘SESSION_REDIS ‘] = redis.Redis(host=’127.0.0.1’, port=6379)

    写入redis数据库

    ​ session[‘user_id’] = user.id

    ​

    装饰器

    上传头像

    注销

    ​ 删除session中的值

    ​

​ 上传图片

装饰器

上传头像

注销

项目搭建:

环境:

  1. 创建: virtualenv –no-site-packages flaskenv

    python3创建虚拟环境的方式:python -m venv 名字

  2. 激活 :

    windows:

    1. cd flaskenv/Script

    2. activate/deactivate

      Linux,Mac:

      ​ source flaskenv/Script/bin/activate

  3. 安装flask:

    ​ pip3 install flask

    ​ 创建需要安装环境的txt文件:

    ​ requirement.txt

    ​ pip install -r requirement.txt

    1. 指定环境

    ​

    一个最小的web:

    按照MVC思路拆分项目

    ​

    ​

Hello World

发表于 2018-07-17

Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.

Quick Start

Create a new post

1
$ hexo new "My New Post"

More info: Writing

Run server

1
$ hexo server

More info: Server

Generate static files

1
$ hexo generate

More info: Generating

Deploy to remote sites

1
$ hexo deploy

More info: Deployment

未命名

发表于 2018-07-13

###投票应用,给老师投票,且每个用户只有三票

1.将字典转换成json格式
2.ajax请求

####views.py文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
def make_good_comment(request, no):
teacher = Teacher.objects.get(pk=no)
teacher.good_count += 1
teacher.save()

# 次一点的方法:发一个重定向参数,回到首页,写的是url的名字
# return redirect('index')
# 使用ajax分布式加载
# 构造一个字典,context
ctx = {'code': 200, 'good': teacher.good_count}
'''
将返回的字典转换成json格式:
# 将字典转成json格式的函数,一个字符串,返回文本,指定返回的是json格式
# 这是MIME类型,Multipurpose Internet Mail Extension 告诉浏览器给的是什么类型的数据
# image/jpeg, image/png, image/gif, application/msword, application/pdf, audio/mp3, video/mpeg
# 因特网是tcp/ip协议构建的网络
# 如果返回的json数据中有中文,还要加上charset=utf-8
'''
return HttpResponse(json.dumps(ctx), content_type='application/json')


def make_bad_comment(request, no):
teacher = Teacher.objects.get(pk=no)
teacher.bad_count += 1
teacher.save()
ctx = {'code': 200, 'bad': teacher.bad_count}
return HttpResponse(json.dumps(ctx), content_type='application/json')

urls文件

1
2
path('good/<int:no>/', views.make_comment),
path('bad/<int:no>/', views.make_comment),

teachers.html文件:使用ajax方法投票

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<script>
$(function(){
{#绑定点击事件#}
$('.basic .button').on('click', function(evt){
{#阻止a标签的默认行为#}
evt.preventDefault();
{#取到的原生js对象#}
var $a = $(evt.target);
{#attr方法可以取属性也可以改属性,jquery的方法#}
var url = $a.attr('href');
{#传入一个json对象,#}
$.ajax({
'url':url,
'type':'get',
'data':{},
'dataType':'json',
'success': function(json){
if(json.code == 200){
$a.text(json.result);
console.log('请求成功')
}else if(json.code == 403){
alert('票数不足')
}
},
'error': function(json){
console.log('请求错误')
}
});
});
});

优化:将两个投票的方法合二为一

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
def make_comment(request, no):
ctx = {'code': 200}
if 'user' in request.session and request.session['user']:
user = request.session['user']
if user.tcounter > 0:
try:
# 去request里面拿path属性,就是你请求的url,拿到like or dislike
# /good/3,拿到主机或者域名是host,get_full_path
# s是我的资源,?后面是请求参数,服务器传递的查询字符串
teacher = Teacher.objects.get(pk=no)
# request.method是拿到请求的类型
if request.path.startswith('/good'):
teacher.good_count += 1
ctx['result'] = f'like({teacher.gcount})'
else:
teacher.bad_count += 1
ctx['result'] = f'dislike({teacher.bcount})'
teacher.save()
user.tcounter -= 1
# 改变tcounter
User.objects.filter(username__exact=user.username).\
update(tcounter=user.tcounter)
request.session['user'] = user
# user.save()
# except Teacher.DoesNotExist:
# ctx['code'] = 404
except:
return render(request, 'error.html', {})
else:
ctx['code'] = 403
ctx['result'] = '票数不足'
else:
ctx['code'] = 302
ctx['result'] = '请先登录'
return HttpResponse(json.dumps(ctx), content_type='application/json', charset='utf-8')

未命名

发表于 2018-07-13

###如何建立展示页面

1.使用url传递参数:匹配url,捕获用户选择的no,但在Django1中使用正则表达式,命名捕获组在python中必须要加一个P
path(‘subjects/int:no/‘, views.show_teachers)
拿到的方法是:<a href=”/good/“
如何拿到?后面的数据?
2.ORM(对象关系映射)框架
3.模型的创建
4.属性访问器
5.加载静态资源

####展示student和teacher页面

#####首先建立模型:models.py文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
class Subject(models.Model):
no = models.AutoField(primary_key=True, db_column='sno', verbose_name='编号')
name = models.CharField(max_length=50, db_column='sname', verbose_name='名称')
intro = models.CharField(max_length=511, db_column='sintro', verbose_name='介绍')

def __str__(self):
return self.name

class Meta(object):
db_table = 'tb_subject'
ordering = ('no', )
verbose_name_plural = '学科'
verbose_name = '学科'


# Django 框架中包含了一个ORM(对象关系映射)框架
# ORM 可以帮助我们完成对象模型到关系模型的双向转换
class Teacher(models.Model):

# 自增长的字段, 对应的列是tno
no = models.AutoField(primary_key=True, db_column='tno', verbose_name='编号')
# 字符串, 数据库里面的名字(加前缀表示)
name = models.CharField(max_length=20, db_column='tname', verbose_name='姓名')
manager = models.BooleanField(default=False, db_column='tmanager', verbose_name='是否是主管')
# job = models.CharField(max_length=10, db_column='tjob', verbose_name='职位')
intro = models.CharField(max_length=1023, db_column='tintro', verbose_name='介绍')
motto = models.CharField(max_length=255, db_column='tmotto', verbose_name='理念')
photo = models.CharField(max_length=511, db_column='tphoto', null=True, blank=True)
# 多的这边通过外键列建立关系, 外键列参照了Subject, 外键类on_delete=PROTECT不运行删除,级联就是一起删除,有老师的学科不让删除
subject = models.ForeignKey(Subject, db_column='sno', on_delete=PROTECT, related_name='+', verbose_name='所属学科')
good_count = models.IntegerField(default=0, db_column='tgcount', verbose_name='好评')
bad_count = models.IntegerField(default=0, db_column='tbcount', verbose_name='差评')

# 属性的访问器,getter方法,将方法包装成属性,可以直接使用
@property
def gcount(self):
return f'{self.good_count}' \
if self.good_count <= 999 else '999+'

@property
def bcount(self):
return f'{self.bad_count}'\
if self.bad_count <= 999 else '999+'

# 内部类,给表改名字,Meta代表这个表的原数据
class Meta(object):
db_table = 'tb_teacher'
verbose_name = '讲师'
verbose_name_plural = '讲师'

views.py文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
'''
两个非常重要的对象:
HttpRequest
HttpResponse
'''


def show_subjects(request):
# no = randint(1, 6)
# 通过指定的主键取到某一个老师
# ctx = {'teacher': Teacher.objects.get(pk=no)}

ctx = {'subjects_list': Subject.objects.all()}

# teacher = {
# 'name': 'yt',
# 'intro': 'python',
# 'motto': 'happy',
# }
# ctx = {'teacher': teacher}
# teacher = {'name': '王',
# 'intro': 'python',
# 'motto': 'protact makes profect'}

return render(request, 'subject.html', ctx)


def show_teachers(request, no):
# 通过学科的编号查老师,1,查老师表,筛选学科;2,通过学科反查老师
# 拿到指定学科的一个模型实体,使用自带的teacher_set属性反查老师
# teachers = Subject.objects.get(pk=no).teacher_set.all()
# subject对象里的no属性等于我们传进来的no
teachers = Teacher.objects.filter(subject__no=no)
ctx = {'teachers_list': teachers}
return render(request, 'teacher.html', ctx)

####urls

1
2
3
4
urlpatterns = [
path('admin/', admin.site.urls),
# 匹配url,捕获用户选择的no,但在Django1中使用正则表达式,命名捕获组在python中必须要加一个P
path('subjects/<int:no>/', views.show_teachers),

subjects.html文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>学科信息</title>
</head>
<body>
<h1>学科信息</h1>
<hr>
<ul>
{% for subject in subjects_list %}
<li>
<a href="/subjects/{{ subject.no }}">{{ subject.name }}</a>
</li>
{% endfor %}
</ul>
</body>
</html>

teacher.html文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
<!DOCTYPE html>
{% load staticfiles %}
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title-information</title>
</head>

<body>
<style>
.basic{
width: 60%;
margin-right: 20px;
float:left;
}
#img{
width: 40%;

}
hr{
clear: both;
}
.button{
display:inline-block;
width: 80px;
height: 30px;
background-color: red;
color: white;
font: 16px/30px Arial;
text-decoration: none;
text-align: center;
}
</style>
{% for teacher in teachers_list %}
<div>
<div class="basic">
<h1>{{ teacher.name }}老师</h1>
<hr>
简介
<p>{{ teacher.intro }}</p>
理念
<p>{{ teacher.motto }}</p>
{#执行js功能链接#}
<a id="{{ teacher.no }}" href="javascript:void(0);" class="good button">like({{ teacher.good_count }})</a>
<a mydata="{{ teacher.no }}" href="javascript:void(0);" class="bad button">dislike({{ teacher.bad_count }})</a>
</div>
{# 加载静态资源#}
<div id="img" >
<p><img src="{% static teacher.photo %}" alt=""></p>
</div>
</div>
{% endfor %}

<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>

<script>
$(function(){
$('.good').on('click', function(evt){
{#拿到事件源 a标签#}
var a = $(evt.target);
$.getJSON('/good/' + a.attr('id'), function(json){
if (json.code == 200){
a.text('like(' + json.good + ')');
}
})
});
$('.bad').on('click', function(evt) {
var a = $(evt.target);
$.getJSON('/bad/' + a.attr('mydata'), function(json){
if (json.code == 200){
a.text('dislike(' + json.bad + ')')
}
})
})
});

</script>
</body>
</html>

未命名

发表于 2018-07-13

###登陆注册功能的实现

1.数据库数据的增删改查
2.拿到http协议中请求体中的内容
3.使用哈希码加密
4.重写方法
5.使用ModelForm表单对象自动验证

####views.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
def login(request):
if request.method.lower() == 'get':
return render(request, 'login.html', {})
else:
# request.META类似字典,可以获得请求头,比如user_agent就是浏览器,请求行中的:method是方法,is_secure真为https
# get和post是拿消息体
username = request.POST['username']
try:
# 比较用户名是否存在,密码对不对
user = User.objects.get(username=username)
password = request.POST['password']
hasher = proto.copy()
hasher.update(password.encode('utf-8'))
if hasher.hexdigest() == user.password:
# 返回302重新请求 httpresponse是200请求成功加载网页
return redirect('index')
except User.DoesNotExist:
pass
return render(request, 'login.html', {'hint': '用户名或密码错误'})


def register(request):
form = UserForm()
if request.method.lower() == 'get':
return render(request, 'register.html', {'f': form})
else:
# 使用表单判断信息是否全,将表单直接快速生成,快速验证
form = UserForm(request.POST)
if form.is_valid():
# 其实保存的是user对象
form.save(commit=True)
# user = User()
# # 访问他的post属性,像一个字典,里面是你提交的表单数据
# user.username = request.POST['username']
# user.password = request.POST['password']
# user.email = request.POST['email']
# # 生成哈希码实例
# # hasher = sha1()
# # # 通过update方法传入对象
# # hasher.update(user.password.encode('utf-8'))
# # # 利用哈希码函数对密码进行加密,16进制加密
# # user.password = hasher.hexdigest()
# user.save()
return render(request, 'login.html', {'hint': '注册成功请登录'})
else:
return render(request, 'register.html',
{'f': form})

###models

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 带_的库是不建议使用的
# from _sha1 import sha1

from hashlib import sha1

from django.db import models
from django.db.models import PROTECT

# 生成哈希码实例
proto = sha1()


class User(models.Model):
no = models.AutoField(primary_key=True, db_column='uno', verbose_name='用户编号')
username = models.CharField(max_length=20, unique=True, verbose_name='用户名')
password = models.CharField(max_length=40, verbose_name='用户口令')
email = models.CharField(max_length=255, verbose_name='邮箱')
tcounter = models.IntegerField(default=3, db_column='counter', verbose_name='票数')

# 重写save方法
def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
# 在对象基础上复制一份,比直接创建更快,内存拷贝性能更好
hasher = proto.copy()
# 通过update方法传入对象
hasher.update(self.password.encode('utf-8'))
# 利用哈希码函数对密码进行加密,16进制加密
self.password = hasher.hexdigest()
super().save(force_insert, force_update, using, update_fields)

class Meta(object):
db_table = 'tb_user'
verbose_name_plural = '用户'
verbose_name = '用户'

urls

1
2
3
path('register/', views.register),
path('login/', views.login),
path('check/', views.check_username),

login.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户登录</title>
</head>
<body>
<h1>用户登录</h1>
<hr>
<p>{{ hint }}</p>
<form action="/login/" method="post">
{% csrf_token %}
<div>用户名:</div>
<div>
<input type="text" name="username" required>
<div>密码</div>
<input type="password" name="password" required>

<div>
<button>登录</button>
</div>
</div>
</form>
<a href="/register">Register Rightnow!</a>
</body>
</html>

register.html

使用ajax来做验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
<!DOCTYPE html>
{% load staticfiles %}
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户注册</title>
</head>
<body>
<h1>用户注册</h1>
<hr>
{# {% for error in f.errors %}#}
{# <p>{{ error }}</p>#}
{# {% endfor %}#}
<form action="/register/" method="post">
{# 加上csrf_token的令牌, 防止跨站身份伪造 #}
{% csrf_token %}
{# <table>#}
{# 取出来的是行#}
{# {{ f }}#}
{# </table>#}

<div>用户名:</div>
<div>
{{ f.username }}
<span id="uhint"></span>
{% if f.errors.username %}
<span>用户名无效或已经被注册</span>
{% endif %}
</div>
<div>密码:</div>
<div>
{{ f.password }}
{% if f.errors.password %}
<span>无效的密码</span>
{% endif %}
</div>
<div>邮箱:</div>
<div>
{{ f.email }}
{% if f.errors.email %}
<span>邮箱无效或已经被注册</span>
{% endif %}
</div>
<div>
<button>注册</button>
</div>
</div>
</form>
<a href="/">返回登录</a>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>

<script>
$(function(){
$('#id_username').on('blur', function(evt){
var $input = $(evt.target);
$.ajax({
{#'url': '/check/?username=' + $input.val(),#}
'url': '/check',
'data': {'username':$input.val()},
'type':'get',
'dataType':'json',
'success':function(json){
var $img = $('<img>');
if(json.valid){
$img.attr('src', '/static/images/icon-yes.svg');
}else{
$img.attr('src', '/static/images/icon-no.svg');
}
$('#uhint').empty().append($img)
},
'error':function(){}
})
})
})
</script>


</body>
</html>

优化:使用form对象自动验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from django import forms

from hello.models import User


class UserForm(forms.ModelForm):
# 跟模型对应的表单.ModelForm/也可以写Form页面是什么样就什么样
# 自动帮我验证
username = forms.CharField(max_length=20, label='用户名')
password = forms.CharField(widget=forms.PasswordInput, max_length=20, min_length=8, label='密码')
email = forms.CharField(widget=forms.EmailInput, max_length=255, label='邮箱')

class Meta(object):
# 跟表单对应的模型是,因为写的是ModelForm,Form就不用加
model = User
# 对应的字段是
fields = ('username', 'password', 'email')
1…34
karen2066

karen2066

35 日志
8 标签
© 2018 karen2066
由 Hexo 强力驱动
|
主题 — NexT.Gemini v5.1.4