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>
posted @ 2017-07-10 12:23  _至尊宝  阅读(320)  评论(7编辑  收藏  举报