Django
django内容回顾
一.创建项目基本
1.创建项目
django-admin.py startproject app
目录说明:
app: 项目的容器。
manage.py: 一个实用的命令行工具,可让你以各种方式与该 Django 项目进行交互。
python manage.py startapp appname 运行某个应用
python manage.py makemigrations 用于记录数据库的所有修改
python manage.py migrate 将修改的数据进行提交
python manage.py createsuperuser 创建一个超级管理员
app/app/__init__.py: 一个空文件,告诉 Python 该目录是一个 Python 包。
app/app/settings.py: 该 Django 项目的设置/配置。
增加模版路径
TEMPLATE_DIRS = (
os.path.join(BASE_DIR,'templates'),
)
用于增加静态文件路径
STATICFILES_DIRS = (
os.path.join(BASE_DIR,'static'),
)
app/templates 此目录一把自动生成并且配置好,用于放置模版
app/static 此目录需自行创建,放置各类静态文件
app/urls.py: 该 Django 项目的 URL 声明; 一份由 Django 驱动的网站"目录"。
1、单一路由对应
1.url(r'^index$', views.index),
2、基于正则的路由
1.url(r'^index/(\d*)', views.index),
2.url(r'^manage/(?P<name>\w*)/(?P<id>\d*)', views.manage),
3、添加额外的参数
1.url(r'^manage/(?P<name>\w*)', views.manage,{'id':333}),
4、为路由映射设置名称
1.url(r'^home', views.home, name='h1'),
2.url(r'^index/(\d*)', views.index, name='h2'),
app/wsgi.py: 一个 WSGI 兼容的 Web 服务器的入口,以便运行你的项目。
2.进入app 目录输入以下命令,启动服务器:
python manage.py runserver 0.0.0.0:8000
0.0.0.0 让其它电脑可连接到开发服务器,8000 为端口号。如果不说明,那么端口号默认为 8000。
3.绑定 URL 与视图函数。打开 urls.py 文件
from django.conf.urls import url
from . import view
urlpatterns = [
url(r'^$', view.hello),
]
4.在views.py中写一个视图函数以返回
HttpResponse返回一个字符串给客户端(浏览器)
from django.shortcuts import render,HttpResponse,redirect
def hello(request):
return HttpResponse("Hello world ! ")
5.修改 view.py,增加一个新的对象,用于向模板提交数据:
使用 render 来替代之前使用的 HttpResponse。render直接返回一个html文件
PS:*****render的内部还是将html文件转换称为字符串返回给客户端
def hello(request):
context = 'Hello World!'
return render(request, 'hello.html')
模版
<h1>Hello world !</h1>
二.Django 模板标签
使用 render 来替代之前使用的 HttpResponse。render 还使用了一个字典 context 作为参数。 context 字典中元素的键值 "hello" 对应了模板中的变量 "{{ hello }}"。
1.直接进行位置替换
模版
<h1>{{ hello }}</h1>
2.if/else 标签
基本语法格式如下:
模版
{% if condition1 %}
... display 1
{% elif condition2 %}
... display 2
{% else %}
... display 3
{% endif %}
3.for 标签
与Python的 for 语句的情形类似,{% for %} 允许我们在一个序列上迭代。
<ul>
{% for athlete in athlete_list %}
<li>{{ athlete.name }}</li>
{% endfor %}
</ul>
4.函数
模板函数可以在变量被显示前修改它,函数使用管道字符,如下所示:
{{ name|lower }}
函数的参数跟随冒号之后并且总是以双引号包含。 例如:
{{ bio|truncatewords:"30" }}
5.include 标签
{% include %} 标签允许在模板中直接放入其它的模板的内容。
{% include "nav.html" %}
6.模板继承(母版)
模板可以用继承的方式来实现复用。
母版test.html
{% block mainbody %}
<p> text </p>
{% endblock %}
子版test2.html
{% extends "test.html" %} #写在第一行
{% block mainbody %}
<p>继承了 test.html 文件</p>
{% endblock %}
三.Django 模型
Django 对各种数据库提供了很好的支持,包括:PostgreSQL、MySQL、SQLite、Oracle。 MySQL 是 Web 应用中最常用的数据库。本章节我们将以 Mysql 作为实例进行介绍。你可以通过本站的 MySQL 教程 了解更多Mysql的基础知识。
1.数据库配置
settings.py: 文件代码:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', # 指定数据库类型
'NAME': 'test', # 指定数据库
'USER': 'test', # 数据库用户名
'PASSWORD': 'test123', # 密码
'HOST':'localhost', # 域名
'PORT':'3306', # 端口
}
}
在settings.py中找到INSTALLED_APPS这一项,如下:
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app0l', # 添加此项
)
2.数据库
Django规定,如果要使用模型,必须要创建一个app 目录结构如下:
test
|-- TestModel
| |-- __init__.py
| |-- admin.py
| |-- models.py
| |-- apps.py
| |-- tests.py
| `-- views.py
django用类代表 数据库表,对象代表每一行
常见的字段:
AutoField(Field)
- int自增列,必须填入参数 primary_key=True(一般会自动生成,无需手动)
FloatField(Field)
- 浮点型
CharField(Field)
- 字符类型
- 必须提供max_length参数, max_length表示字符长度
TextField(Field)
- 文本类型
EmailField(CharField):
- 字符串类型,Django Admin以及ModelForm中提供验证机制
IPAddressField(Field)
- 字符串类型,Django Admin以及ModelForm中提供验证 IPV4 机制
DateTimeField(DateField)
- 日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]
DateField(DateTimeCheckMixin, Field)
- 日期格式 YYYY-MM-DD
TimeField(DateTimeCheckMixin, Field)
- 时间格式 HH:MM[:ss[.uuuuuu]]
FloatField(Field)
- 浮点型
常见参数:
null 数据库中字段是否可以为空
default 数据库中字段的默认值
primary_key 数据库中字段是否为主键
db_index 数据库中字段是否可以建立索引
unique 数据库中字段是否可以建立唯一索引
blank Admin中是否允许用户输入为空
editable Admin中是否可以编辑
help_text Admin中该字段的提示信息
choices Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
连表结构
一对多:models.ForeignKey(其他表)
多对多:models.ManyToManyField(其他表)
一对一:models.OneToOneField(其他表)
在命令行中运行实现更改:
$ python manage.py makemigrations # 让 Django 知道我们在我们的模型有一些变更
$ python manage.py migrate # 创建表结构
3.数据库操作
Django提供了多种方式来获取数据库的内容,如下代码所示:
from django.http import HttpResponse
from app01 import model
# 数据库操作
def testdb(request):
# 通过objects这个模型管理器的all()获得所有数据行,相当于SQL中的SELECT * FROM
list = model.Test.objects.all()
# filter相当于SQL中的WHERE,可设置条件过滤结果
放在聚合函数后则代表 having
response2 = model.Test.objects.filter(id=1)
# 获取单个对象
response3 = model.Test.objects.get(id=1)
# 限制返回的数据 相当于 SQL 中的 OFFSET 0 LIMIT 2;
model.Test.objects.order_by('name')[0:2]
#数据排序
model.Test.objects.order_by("id")
# 上面的方法可以连锁使用
model.Test.objects.filter(name="runoob").order_by("id")
更新数据
def testdb(request):
# 修改其中一个id=1的name字段
#Test.objects.filter(id=1).update(name='Google')
# 修改所有的列
# Test.objects.all().update(name='Google')
删除数据 删除数据库中的对象只需调用该对象的delete()方法即可:
def testdb(request):
# 删除id=1的数据
test1 = Test.objects.get(id=1)
test1.delete()
# 另外一种方式
# Test.objects.filter(id=1).delete()
# 删除所有数据
# Test.objects.all().delete()
四.中间件
我们从浏览器发出一个请求 Request,得到一个响应后的内容 HttpResponse ,这个请求传递到 Django的过程如下:
也就是说,每一个请求都是先通过中间件中的process_request函数,这个函数返回 None 或者 HttpResponse 对象,如果返回前者,继续处理其它中间件,如果返回一个 HttpResponse,就处理中止,返回到网页上。假如我们通过一种技术,比如统计一分钟访问页面数,太多就把他的 IP 加入到黑名单 BLOCKED_IPS
五.web安全
1.CSRF(Cross-site request forgery跨站请求伪造,也被称为“one click attack”或者session riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本(XSS),但它与XSS非常不同,并且攻击方式几乎相左。XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性。
GET 请求不需要 CSRF 认证,POST 请求需要正确认证才能得到正确的返回结果。一般在POST表单中加入 {% csrf_token %}
<form method="POST" action="/post-url/">
{% csrf\_token %}
<input type="text" >
</form>
如果使用Ajax调用的时候,就要麻烦一些
$.ajax({
type: 'POST',
url:'URL地址',
data: {
username: $('#username').val(),
content: $('#content').val(),
'csrfmiddlewaretoken': '{{ csrf_token }}' 关键点
},
dataType: 'json',
success: function(data){
}
})
2.xss
xss表示Cross Site Scripting(跨站脚本攻击),它与SQL注入攻击类似,SQL注入攻击中以SQL语句作为用户输入,从而达到查询/修改/删除数据的目的,而在xss攻击中,通过插入恶意脚本,实现对用户游览器的控制。
防范:
# 对用户提交的内容进行关键字筛选,敏感字符不予提交
# django对于直接显示的内容有自己的安全机制,只要不给提交的内容加上安全豁免 "|safe" 那么用户提交的内容会全部以字符串的形式展示
六.Cookie
简单定义:保存在客户端的特殊键值对.
程序把每个用户的数据以cookie的形式写给用户各自的浏览器。当用户使用浏览器再去访问服务器中的web资源时,就会带着各自的数据去。这样,web资源处理的就是用户各自的数据了。
1.设置Cookie:
rep = HttpResponse(...) 或 rep = render(request, ...)
rep.set_cookie(key,value,...)
rep.set_signed_cookie(key,value,salt='加密盐',...)
--参数:
key, 键
value='', 值
max_age=None, 超时时间
path='/', Cookie生效的路径,/ 表示根路径,特殊的:跟路径的cookie可以被任何url的页面访问
domain=None, Cookie生效的域名
secure=False, https传输
httponly=False 只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖)
2.获取Cookie:
request.COOKIES['key']
request.COOKIES.get("key",default=None),取不到默认为Null
request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)
--参数:
default: 默认值
salt: 加密盐
七.session
Session是服务器端技术,利用这个技术,服务器在运行时可以为每一个用户的浏览器创建一个其独享的session对象,由于session为用户浏览器独享,所以用户在访问服务器的web资源时,可以把各自的数据放在各自的session中,当用户再去访问服务器中的其它web资源时,其它web资源再从用户各自的session中取出数据为用户服务。
Django中默认支持Session,其内部提供了5种类型的Session供开发者使用:
-
数据库(默认)
-
缓存
-
文件
-
缓存+数据库
-
加密cookie
1.配置 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,默认修改之后才保存(默认)
2.使用
def index(request):
# 获取、设置、删除Session中数据
request.session['k1']
request.session.get('k1',None)
request.session['k1'] = 123
request.session.setdefault('k1',123) # 存在则不设置
del request.session['k1']
# 所有 键、值、键值对
request.session.keys()
request.session.values()
request.session.items()
request.session.iterkeys()
request.session.itervalues()
request.session.iteritems()
# 用户session的随机字符串
request.session.session_key
# 将所有Session失效日期小于当前日期的数据删除
request.session.clear_expired()
# 检查 用户session的随机字符串 在数据库中是否
request.session.exists("session_key")
# 删除当前用户的所有Session数据
request.session.delete("session_key")
request.session.set_expiry(value)
* 如果value是个整数,session会在些秒数后失效。
* 如果value是个datatime或timedelta,session就会在这个时间后失效。
* 如果value是0,用户关闭浏览器session就会失效。
* 如果value是None,session会依赖全局session失效策略。
八.Form组件
Django的Form主要具有一下几大功能:
生成HTML标签 验证用户数据(显示错误信息) HTML Form提交保留上次提交数据 初始化页面显示内容
1.创建Form类 class UserInfo(models.Model): username = models.CharField() email = models.EmailField() user_type = models.ForeignKey() 2.参数
Field
required=True, 是否允许为空
widget=None, HTML插件
label=None, 用于生成Label标签或显示内容
initial=None, 初始值
help_text='', 帮助信息(在标签旁边显示)
error_messages=None, 错误信息 {'required': '不能为空', 'invalid': '格式错误'}
show_hidden_initial=False, 是否在当前插件后面再加一个隐藏的且具有默认值的插件(可用于检验两次输入是否一直)
validators=[], 自定义验证规则
localize=False, 是否支持本地化
disabled=False, 是否可以编辑
label_suffix=None Label内容后缀
3.字段
CharField(Field)
max_length=None, 最大长度
min_length=None, 最小长度
strip=True 是否移除用户输入空白
IntegerField(Field)
max_value=None, 最大值
min_value=None, 最小值
FloatField(IntegerField)
...
DecimalField(IntegerField)
max_value=None, 最大值
min_value=None, 最小值
max_digits=None, 总长度
decimal_places=None, 小数位长度
BaseTemporalField(Field)
input_formats=None 时间格式化
DateField(BaseTemporalField) 格式:2015-09-01
TimeField(BaseTemporalField) 格式:11:12
DateTimeField(BaseTemporalField)格式:2015-09-01 11:12
DurationField(Field) 时间间隔:%d %H:%M:%S.%f
...
RegexField(CharField)
regex, 自定制正则表达式
max_length=None, 最大长度
min_length=None, 最小长度
error_message=None, 忽略,错误信息使用 error_messages={'invalid': '...'}
EmailField(CharField)
...
FileField(Field)
allow_empty_file=False 是否允许空文件
ImageField(FileField)
...
注:需要PIL模块,pip3 install Pillow
以上两个字典使用时,需要注意两点:
- form表单中 enctype="multipart/form-data"
- view函数中 obj = MyForm(request.POST, request.FILES)
URLField(Field)
...
BooleanField(Field)
...
NullBooleanField(BooleanField)
...
ChoiceField(Field)
...
choices=(), 选项,如:choices = ((0,'上海'),(1,'北京'),)
required=True, 是否必填
widget=None, 插件,默认select插件
label=None, Label内容
initial=None, 初始值
help_text='', 帮助提示
ModelChoiceField(ChoiceField)
... django.forms.models.ModelChoiceField
queryset, # 查询数据库中的数据
empty_label="---------", # 默认空显示内容
to_field_name=None, # HTML中value的值对应的字段
limit_choices_to=None # ModelForm中对queryset二次筛选
ModelMultipleChoiceField(ModelChoiceField)
... django.forms.models.ModelMultipleChoiceField
TypedChoiceField(ChoiceField)
coerce = lambda val: val 对选中的值进行一次转换
empty_value= '' 空值的默认值
MultipleChoiceField(ChoiceField)
...
TypedMultipleChoiceField(MultipleChoiceField)
coerce = lambda val: val 对选中的每一个值进行一次转换
empty_value= '' 空值的默认值
ComboField(Field)
fields=() 使用多个验证,如下:即验证最大长度20,又验证邮箱格式
fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),])
MultiValueField(Field)
PS: 抽象类,子类中可以实现聚合多个字典去匹配一个值,要配合MultiWidget使用
SplitDateTimeField(MultiValueField)
input_date_formats=None, 格式列表:['%Y--%m--%d', '%m%d/%Y', '%m/%d/%y']
input_time_formats=None 格式列表:['%H:%M:%S', '%H:%M:%S.%f', '%H:%M']
FilePathField(ChoiceField) 文件选项,目录下文件显示在页面中
path, 文件夹路径
match=None, 正则匹配
recursive=False, 递归下面的文件夹
allow_files=True, 允许文件
allow_folders=False, 允许文件夹
required=True,
widget=None,
label=None,
initial=None,
help_text=''
GenericIPAddressField
protocol='both', both,ipv4,ipv6支持的IP格式
unpack_ipv4=False 解析ipv4地址,如果是::ffff:192.0.2.1时候,可解析为192.0.2.1, PS:protocol必须为both才能启用
SlugField(CharField) 数字,字母,下划线,减号(连字符)
...
UUIDField(CharField) uuid类型
4.常用选择插件 单radio,值为字符串 widget=widgets.RadioSelect(choices=((1,'上海'),(2,'北京'),)) 单select,值为字符串 widget=widgets.Select(choices=((1,'上海'),(2,'北京'),)) 多选select,值为列表 widget=widgets.SelectMultiple 单checkbox widget=widgets.CheckboxInput() 多选checkbox,值为列表 widget=widgets.CheckboxSelectMultiple
5.常用内置插件
TextInput(Input)
NumberInput(TextInput)
EmailInput(TextInput)
URLInput(TextInput)
PasswordInput(TextInput)
HiddenInput(TextInput)
Textarea(Widget)
DateInput(DateTimeBaseInput)
DateTimeInput(DateTimeBaseInput)
TimeInput(DateTimeBaseInput)
CheckboxInput
Select
NullBooleanSelect
SelectMultiple
RadioSelect
CheckboxSelectMultiple
FileInput
ClearableFileInput
MultipleHiddenInput
SplitDateTimeWidget
SplitHiddenDateTimeWidget
SelectDateWidget
6.用于验证
obj = XXOOModelForm()#创建验证对象
obj.is_valid() #进行验证
obj.errors #所有错误信息对象
obj.clean() #用与用户自定义规则
obj.cleaned_data #获取的数据
7.views处理
def index(request):
if request.method == "GET":
obj = MyForm()
return render(request, "index.html", {"obj": obj})
elif request.method == "POST":
obj = MyForm(request.POST, request.FILES)
if obj.is_valid():
v = obj.cleaned_data
print("用户验证成功信息", v)
return redirect("http://www.jd.com")
else:
v = obj.errors
print("错误信息", v)
return render(request, "index.html", {"obj": obj})
8.生成HTML标签
<form action="/index/" method="post" enctype="multipart/form-data" novalidate>
<p>{{ obj.user.label }}{{ obj.user }}{{ obj.user.errors.0 }}</p>
<p>{{ obj.gender.label }}{{ obj.gender }}{{ obj.gender.errors.0 }}</p>
<p>{{ obj.pwd.label }}{{ obj.pwd }}{{ obj.pwd.errors.0 }}</p>
<p>{{ obj.city.label }}{{ obj.city }}{{ obj.city.errors.0 }}</p>
<input type="submit" value="提交">
</form>