目录
-Day20-ORM使用和安全防护
[1].创建表方法一
[2].创建表方法二
[3].创建表方法三:自关联
[4].FK关联
[5]. 普通索引和字段
[6]. EmailField使用和django管理员配置
[7].设置字段属性和索引
[8]. 安全方便:js脚本攻击
[9]. 安全方便:csrf:跨站请求伪造
[10]. 模板使用
[11]. session使用
[12]. yaf的介绍
-s2day20-settings.py
先注释下面的一行代码
MIDDLEWARE = [
# 'django.middleware.csrf.CsrfViewMiddleware',
]
添加静态文件路径
STATICFILES_DIRS=( os.path.join(BASE_DIR,'static'), )
-s2day20-urls.py
配置访问路径,然后初始化
from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^test/', views.test), ]
[1].创建表方法一:
-app01-models.py
构建表结构,然后初始化
from django.db import models # Create your models here. class Boys(models.Model): #不写id,默认创建一个字段名为id的自增主键 username=models.CharField(max_length=32,null=False,default='') nickname=models.CharField(max_length=32,null=False,default='') age=models.IntegerField(null=False,default='') class Girls(models.Model): username=models.CharField(max_length=32,null=False,default='') nickname=models.CharField(max_length=32,null=False,default='') age=models.IntegerField(null=False,default='') class Boys2Girls(models.Model): b=models.ForeignKey('Boys',on_delete=None) g=models.ForeignKey('Girls',on_delete=None)
初始化:
python3 manage.py makemigrations //执行生成sql文件
python3 manage.py migrate //执行文件
pycharm的sqlite3连接方法:
https://jingyan.baidu.com/article/e5c39bf5e4f32439d7603387.html
-app01-views.py
反向查找海峰有几个女朋友:
from django.shortcuts import render,HttpResponse from app01 import models def test(request): #第一种解法: #和海峰有关系的女的 res=models.Boys.objects.filter(username='hf').first() # print(res) # print(res.username,res.nickname) #Boys object #反向查找 #res.小写类名_set().all() #<QuerySet [<Boys2Girls: Boys2Girls object>, # <Boys2Girls: Boys2Girls object>, # <Boys2Girls: Boys2Girls object>]> info=res.boys2girls_set.all() for item in info: #正向查询 print(item.g.username) print(info) return HttpResponse('ok')
第二种解法:
正向查找海峰有几个女朋友 from django.shortcuts import render,HttpResponse from app01 import models def test(request): res = models.Boys2Girls.objects.filter(b__username='hf') print(res) for item in res: # 正向查询 print(item.g.username) print(res) return HttpResponse('ok')
关联关系查询
-app01-models.py
修改related_name='girls' related_name='boys' 参数
from django.db import models
class Boys2Girls(models.Model): b=models.ForeignKey('Boys',on_delete=None,related_name='girls') g=models.ForeignKey('Girls',on_delete=None,related_name='boys')
-app01-views.py
修改下面参数
related_name='girls'
info=res.girls.all()
related_query_name='girls'
info=res.girls_set.all()
[2].创建表方法二:
使用manytomanyfiled生成关系表appo1_girls_b,并添加数据
生成关系表appo1_girls_b
-app01-models.py
from django.db import models
class Boys(models.Model):
#不写id,默认创建一个字段名为id的自增主键
username=models.CharField(max_length=32,null=False,default='')
nickname=models.CharField(max_length=32,null=False,default='')
age=models.IntegerField(null=False,default='')
class Girls(models.Model):
username=models.CharField(max_length=32,null=False,default='')
nickname=models.CharField(max_length=32,null=False,default='')
age=models.IntegerField(null=False,default='')
b=models.ManyToManyField("Boys")
(1).manytomanyfiled在关系表appo1_girls_b添加数据
-app01-views.py
def test(request):
res=models.Girls.objects.filter(id=1).first()
res.b.add(2)
res.b.add(3,4)
res.b.add(*[1,2])
return HttpResponse('ok')
(2).manytomanyfiled在关系表appo1_girls_b删除数据
def test(request):
res.b.remove(2)
return HttpResponse('ok')
[3].创建表方法三:自关联
-app01-models.py
from django.db import models
class UserInfo(models.Model):
username=models.CharField(max_length=32,null=False,default='')
nickname=models.CharField(max_length=32,null=False,default='')
age=models.IntegerField(null=False,default='')
gender_choice=(
(1,'男'),
(2,'女'),
)
gender=models.IntegerField(choices=gender_choice)
class U2U(models.Model):
b=models.ForeignKey('UserInfo',on_delete=None,related_name='girl')
g=models.ForeignKey('UserInfo',on_delete=None,related_name='boy')
-app01-views.py
from django.shortcuts import render,HttpResponse
from app01 import models
def test(request):
res=models.UserInfo.objects.filter(username='hf').first()
info=res.girl.all()
for item in info:
#正向查询
print(item.g.username)
print(info)
return HttpResponse('ok')
[4].FK关联
'''
id new_id comment
user replay_id
1 1 别逼逼 张三 0
2 1 就比比 李四 0
3 2 瞎比比 xxx
0
4 1 sssss
eagon 1
5 2 bbbbb
alex 3
'''
class Comment(models.Model):
new_id=models.IntegerField(null=False,default=0)
comment=models.CharField(null=False,max_length=256,default='')
user=models.CharField(null=False,max_length=32,default='')
replay_id=models.ForeignKey("comment",on_delete=None)
[5]. 普通索引和字段
db_index
举例:
username=models.CharField(max_length=32,default='',null=False,db_index=True)
字段:
SmallIntegerField //小整数-32768~32767
IntegerField //正整数(有符号)-2147483648~2147483647
PositiveIntegerField //正数 0~2147483647
BigIntegerField
//长整数(有符号) -9223372036854775808~9223372036854775807
CharField //字符类型 max_length表示字符长度
TextField //文本类型
FloatField(Field)
-浮点型
DecimalField(Field)
-10进制小数
-参数
max_digits,小数总长度
decimal_places,小数位长度
[6]. EmailField使用和django管理员配置
EmailField()
在models中使用:
email=models.EmailField()
转换email varchar(254)在modle模板中不起作用,在django管理里面有作用(正则表达式)
django的配置:
-app01-admin.py中主编
from app01 import models
admin.site.register(models.Test)
-s2day20-urls.py中,
url(r'^admin/', admin.site.urls),
-命令行创建超级管理员
python3 manage.py createsuperuser
[7].设置字段属性和索引
null 数据库中字段是否可以为空
default 数据库中字段的默认值
primary_key 数据库中字段是否为主键
db_index 数据库中字段是否可以建立索引
unique 数据库中字段是否可以建立唯一索引
unique_for_date 数据库中字段[日期]部分是否可以建立唯一索引
unique_for_month 数据库中字段[月]部分是否可以建立唯一索引
unique_for_year 数据库中字段[年]部分是否可以建立唯一索引
在类中定义:
class Meta:
#设置联合索引
index_together=(
('username','age')
)
unique_together=(
('username', 'age')
)
[8]. 安全方便:js脚本攻击
xss:跨站脚本攻击
web网站:js脚本
js脚本:
<script>alert('123')</script>
加了safe之后,取消了对数据的转义,所以慎用safe
-攻击用处:
-<script>alert('123')</script>
-<script>document.cookies</script>
代码举例:
-s2day20-urls.py
urlpatterns = [
url(r'^test3/', views.test3),
url(r'^index/', views.index),
]
-app01-views.py
msg=[]
def test3(request):
if request.method=='GET':
return render(request,'comment.html')
else:
comment=request.POST.get('comment')
msg.append(comment)
return render(request,'comment.html')
def index(request):
return render(request,'index.html',{'msg':msg})
-templates-comment.html
<form action="/test3/" method="post">
<input type="text" name="comment">
<input type="submit" name="提交">
</form>
访问地址:http://127.0.0.1:8005/test3/
-templates-index.html
<h2>评论如下</h2>
{{ msg.0|safe }}
访问地址:http://127.0.0.1:8005/index/
[9]. 安全方便:csrf:跨站请求伪造
方法:
-加一串随机的字符串
只能防止一大部分人
django的方法:
全站使用csrf验证:
-开启'django.middleware.csrf.CsrfViewMiddleware',
-html页面,开启token
<form action="/csrf1/" method="post">
{% csrf_token %}
<input type="text" name="username">
<input type="submit" value="提交">
</form>
全站使用csrf,但是局部业务函数不使用csrf:
-开启'django.middleware.csrf.CsrfViewMiddleware',
-针对局部业务函数,加上如下装饰器:
from django.views.decorators.csrf import csrf_exempt,csrf_protect
@csrf_exempt
def csrf1(request):
if request.method=='GET':
return render(request,'csrf1.html')
else:
username=request.POST.get('username')
return HttpResponse('ok')
全站关闭csrf的验证,但是局部使用
-关闭'django.middleware.csrf.CsrfViewMiddleware',
from django.views.decorators.csrf import csrf_exempt,csrf_protect
@csrf_protect
def csrf1(request):
if request.method=='GET':
return render(request,'csrf1.html')
else:
username=request.POST.get('username')
return HttpResponse('ok')
ajax方式提交数据:
-s2day20-urls.py
urlpatterns = [
url(r'^csrf2/', views.csrf2),
]
-app01-views.py
def csrf2(request):
if request.method=='GET':
return render(request,'csrf_ajax.html')
else:
username=request.POST.get('username')
return HttpResponse('ok')
-templates-csrf_ajax.html
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="/static/jquery.min.js"></script>
</head>
<body>
<form action="">
{% csrf_token %}
<input type="text" name="username" id="username">
<input type="button" value="提交" id="btn">
</form>
</body>
方式一:
<script>
var csrf_token=$("input[name='csrfmiddlewaretoken']").val()
console.log(csrf_token)
$('#btn').click(function () {
$.ajax({
url:"/csrf2/",
type:"POST",
data:{"username":$('username').val(),"csrfmiddlewaretoken":csrf_token},
success:function (args) {
console.log(args)
}
})
})
</script>
方式二:
<script>
var csrf_token=$("input[name='csrfmiddlewaretoken']").val()
console.log(csrf_token)
$('#btn').click(function () {
$.ajax({
url:"/csrf2/",
type:"POST",
headers:{'X-CSRFToken':csrf_token},
data:{"username":$('username').val(),},
success:function (args) {
console.log(args)
}
})
})
</script>
[10]. 模板使用
-现在用的模板语言都是django自带的模板语言
-jinjia2的模板语言
模板标签:
字符串:{{name}}
列表:{{myli.0}} {{myli.1}}
字典:{{mydict['username']}}
{%for item in res%} content {%endfor%}
{%if true%}{%else%}
母版和子版
母版:
{%block xxx%}{%endblock%}
子版:
{%extends muban.html%}
{%block xxx%} content {%endblock%}
内部过滤函数:
{{ name }}
{{item.event_start|date:"Y-m-d H:i:s"}}
{{bio|truncatewords:"30"}}
{{ name|first|upper }}
{{ name|lower }}
自定义simple_filter:
1.在app中创建templatetags模块
-app01-templatetags-xx.py
2.在模块中创建任意.py文件,例如:xx.py
from django import template
register = template.Library()
@register.filter()
def my_upper(val):
return val.upper()
-s2day20-urls.py
urlpatterns = [
url(r'^test4/', views.test4),
]
-app01-views.py
def test4(request):
name='Frank'
return render(request,'test4.html',{"name":name})
-templates-test4.html
{% load xx %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{{ name|first|upper }}
{{ name|lower }}
{{ name|my_upper }}
</body>
</html>
-simple_filter
@register.filter()
def my_upper(val,args): //只能传2个参数
return val + args
使用:
{% load xx %}
{{ name|my_upper:"sss" }}
-simple_tag
@register.simple_tag()
def my_func(val,args,args1,args2): //可以传多个参数
return val+args+args1+args2
使用:
{% load xx %}
{% my_func name "sss" "aaa" "bbb" %} //拼接内容使用空格分开
html中可以引入别的组件
{% include "csrf1.html" %}
[11]. session使用
-cookie:
保存在客户端浏览器上
-session:
存储在服务器上
优势:安全,储存数据没有限制
session依赖cookie
服务端session接收处理:
1.当用户名和密码正确,将用户名存储到服务端{"abc":{"username"}:'frank'}
2.返回给客户端浏览器一个随机字符串,就是我们存储服务端abc,通过cookie来返回set_cookie('xxx':'abc')
举例session的使用
-s2day20-urls.py
urlpatterns = [
url(r'^login/', views.login),
url(r'^main/', views.main),
]
-app01-views.py
def login(request):
if request.method=='GET':
return render(request,'login.html')
else:
username=request.POST.get('username')
password=request.POST.get('password')
if username=='frank' and password=='123':
request.session['username']='frank'
return redirect('/main/')
else:
return render(request,'login.html')
def main(request):
res=request.session.get('username')
if res:
return render(request,'main.html',{"username":res})
else:
return render(request,'login.html')
-templates-login.html
<form action="/login/" method="post">
{% csrf_token %}
<input type="text" name="username">
<input type="password" name="password" >
<input type="submit" value="提交">
</form>
-templates-main.html
<h2>this is main,welcome,{{ username }}</h2>
访问地址:http://127.0.0.1:8005/login/
jango默认支持Session,并且默认是将Session数据存储在数据库中,即:django_session表中
settings.py
SESSION_ENGINE = 'django.contrib.sessions.backends.db' # 引擎(默认)
SESSION_COOKIE_NAME = "sessionid" # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认)
SESSION_COOKIE_PATH = "/" # Session的cookie保存的路径(默认)
SESSION_COOKIE_DOMAIN
= None # Session的cookie保存的域名(默认)
SESSION_COOKIE_SECURE
= False # 是否Https传输cookie(默认)
SESSION_COOKIE_HTTPONLY
= True # 是否Session的cookie只支持http传输(默认)
SESSION_COOKIE_AGE = 1209600 # Session的cookie失效日期(2周)(默认)
SESSION_EXPIRE_AT_BROWSER_CLOSE
= False # 是否关闭浏览器使得Session过期(默认)
SESSION_SAVE_EVERY_REQUEST
= False # 是否每次请求都保存Session,默认修改之后才保存(默认)
[12]. yaf的介绍:
MVC
models(存放数据库相关文件) views(存放html模板文件) controllers(处理和业务相关的文件)
MTV(django)
models(存放数据库相关的文件) template(存放html模板文件) views(处理和业务相关的文件)