Python的web框架--Django

1. Django的MTV模式:

Model(模型):负责业务对象与数据库的对象(ORM)

Template(模板):负责如何把页面展示个用户

View(视图):负责业务逻辑,并在适当的时候调用Model和Template

此外,Django还有一个url分发器,它的作用是将一个个URL的页面请求分发给不同的view处理,view再调用相应的Model和Template


2. Django工程

1)创建一个django工程:djando-admin.py startproject mysite

manage.py Django项目里面的工具,通过它可以调用django.shell和数据库等

settings.oy 包含了项目的默认设置,包括数据库信息,调试标志以及其他一些工作的变量

urls.py 负责把URL模式映射到应用程序


2)在mysite目录下创建blog应用:python manage.py startapp blog


3)启动djando项目:python manage.py runserver 8080




3. settings配置文件

TEMPLATES下的

'DIRS': [os.path.join(BASE_DIR, 'templates')]

做了一个路径拼接




4. Django URL(路由系统)

本质上是url模式与视图函数之间的对应

urlpatterns = [

    path(正则表达式, views视图函数, 参数, 别名),

 ]

正则表达式:一个正则表达式字符串

views视图函数:一个可调用对象,通常为一个视图函数或一个指定视图函数路径的字符串

参数:可选的要传递给视图函数的默认参数(字典形式)

别名:一个可选的name参数

from django.contrib import admin
from django.urls import path
from blog import views
from django.conf.urls import url,include

urlpatterns = [
    path('admin/', admin.site.urls),
    path("current_time", views.current_time),
    path("user_info", views.user_info),
    # 按照位置接收参数
    url(r"^articles/([0-9]{4})/$", views.year_archive),
    # 按照参数名接收参数
    url(r"^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$", views.month_archive),
    # 参数三
    url(r"^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$", views.month_archive,
        {"year": "1990", "month": "8"}),
    # 参数四
    url(r"^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$", views.month_archive,
        {"year": "1990", "month": "8"}, name="articles"),

    # url映射分发
    url(r"^blog/", include('blog.urls'))

]



5. Django视图函数

http请求中产生两个核心对象:

http请求:HttpRequest对象

Http响应:HttpResponse对象

所在位置:django.http


1) HttpRequest对象的属性:

path: 请求页面的全路径,不包括域名

method:请求中使用的http方法的字符串表示。全大写表示

if request.method == "GET":

    pass

elseif request.method == "POST":

    pass

GET:包含所有HTTP GET参数的类字典对象

POST:包含所有HTTP POST参数的类字典对象

COOKIES:包含所有cookies的标准Python字典对象;keys和values都是字符串

FILES:包含所有上传文件的类字典对象;FILES中的每个key都是<input type="file" name=""/>标签中

name属性的值,FILES中的每一个value同时也是一个标准的python字典对象,包含下面三个Keys:

    filename:上传文件名,用字符串表示

    content_type:上传文件的Content Type

    content:上传文件的原始内容

user:是一个django.contrib.auth.models.User对象,代表当前登录的用户。如果访问用户当前没有登录,user将被初始化为django.contrib.auth.models.AnonymousUser的实例。你可以通过user的is_authenticated()方法来辨别用户是否登录:

    if request.user.is_authenticated(): 只有激活Django中的AuthenticationMiddleware时该属性才可用


2)HttpResponse对象:

每个view请求处理方法必须返回一个HttpResponse对象。HttpResponse类在django.http.HttpResponse

在HttpResponse对象上扩展的常用方法:

    页面渲染:render(), render_to_response(),

    页面跳转:redirect()

    locals():可以直接将函数中所有的变量传给模板




6. 模板语言

html+逻辑控制语言

1){{ 变量 }}


2)万能的句点号: .

列表、字典、属性、类都可以用.来取到


3){% if %}

{% if 1%}

    <p>Hello World</p>

{% elif obj %}

    <p>Buy</p>

{% endif %}


4){% for %}

{% for i in obj %}

    <p>{{ i }}</p>

{% endfor %}


{% for i in obj %}

    <p>{{ forloop.counter0 }}:{{ i }}</p>

{% endfor %}


5)过滤器(filter)的使用

{{ ship_date|date:"FJ,Y"}},ship_date变量传给date过滤器,date过滤器通过使用“FJ,Y”这几个参数来格式化日期数据。“|”

{{ obj|upper }}

{{ obj|lower }}


常用过滤器:

add:给变量加上相应的值

addslashes:给变量中的引号前加上斜线

capfirst:首字母大写

cut:从字符串中移除指定的字符

date:格式化日期字符串

default:如果值是False,就替换成设置的默认值,否则就使用本来的值

default_if_none:如果值是None就替换成设置的默认值,否则就使用本来的值

filesizeformat:文件大小


6)告知浏览器可以渲染(可能经常用到,推荐第二种safe方法)

{# value6='<a href="#">跳转</a>' #}

{% autoescape off %}

    {{ value6 }}

{% endautoescape %}


{{ obj|safe}} 也可以达到相同的效果


7){% csrf_token %}(加在form标签最后一行)

用于生成csrf_token的标签,用于防止跨站攻击验证


8){% load%}:加载标签库


9){% url %}:引用路由配置的地址

<form action={% url 别名 %}>


10){% with %}:用更简单的变量名替代复杂的变量名


11){% verbatim %}:禁止render




7. 自定义模板标签

a. 在app中创建templatetags模块(必须)

b. 创建任意.py文件,如add100.py

from django import template
from django.utils.safestring import mark_safe

register = template.Library() # register的是固定变量名,不能改变


@register.simple_tag
def my_add100(v1):
    return v1 + 100


@register.simple_tag
def my_input(id, arg):
    result = "<input type='text' id='%s' class='%s' />" % (id, arg)
    return mark_safe(result)

c. 在自定义simple_tag的html文件中导入之前创建的add100.py文件名

{% load add100 %}

d. 使用simple_tag

{% my_add100 3 %}

{% my_input 'id_username' 'hide' %}




8. django模板

在模板中将变化的部分改为(以下的block名为“content”):

{% block content %}

{% endblock %}


然后在继承的网页中引入模板

{% extends "base.html" %}
{% block content %}
<div class="content">订单</div>
{% endblock %}



9. djando ORM

1)创建表

from django.db import models

# Create your models here.

class UserInfo(models.Model):
    username = models.CharField(max_length=64)
    gender = models.CharField(max_length=64)
    email = models.CharField(max_length=64)
    age = models.IntegerField()
    publisher = models.ForeignKey("Publisher") # 一对多关系

    # 接受对象
    author = models.ManyToManyField("Author")

    def __str__(self):
        return self.title


创建类之后,输入如下代码创建表

python manage.py makemigrations

python manage.py migrate


2)添加对象

create方式一:

Book.objects.create(
  title="A",
  price=1,
  color="green",
  publisher_id=4,
  # 因为外键关系是一对多,publisher只能对应一个对象
)

create方式二(推荐使用这种方式):

Book.objects.create(**{"title":"A", "price":1, "color":"green"})

save方式一:

book=Book(title="B", price=10, color="grey")

book.save()

save方式二:

book=Book()

book.title="C"

book.price=100

book.color="yellow"

book.save()


3)删(delete)

Book.objects.filter(id=1).delete()


4)改(update和save)

save方式:

book = Book.objects.get(title="A")

book.price = 30

book.save()


update方式(这种方式效率更高):

Book.objects.filter(title="C").update(price=25) # 不能用get方法

注意:update方式不能使用get的原因是:update是QuerySet对象的方法,get返回的是一个model对象,它没有update方法,而filter返回的是一个QuerySet对象

注意,这里因为update返回的是一个整型,所以没法用query属性;对于每次创建一个对象,想显示对应的raw sql,需要在settings加上日志记录部分:

LOGGING={
  'version':1,
  'disable_existing_loggers':False,
  'handlers':{
    'console':{
      'level':'DEBUG',
      'class':'logging.StreamHandler',
    },
  },
  'loggers':{
    'django.db.backends':{
      'handlers':['console'],
      'propagate':True,
      'level':'DEGUG',
    },
  }

}



5)查(filter, value等)

查询API:

(1)filter(**kwargs):它包含了与所给筛选条件相匹配的对象

(2)all():查询所有结果

(3)get(**kwargs):返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。


下面的方法都是对查询的结果再进行处理:比如objects.filter.values()

(4)values(*field):返回一个ValueQuerySet--一个特殊的QuerySet,运行后得到的并不是一系列model的实例化对象,而是一个可迭代的字典序列

(5)exclude(**kwargs):它包含了与所给筛选条件不匹配的对象

(6)order_by(*field):对查询结果排序,倒序:order_by("-id")

(7)reverse():对查询结果反向排序

(8)distinct():从返回结果中剔除重复记录

(9)values_list(*field):它与values()非常相似,它返回的是一个元祖序列,values返回的是一个字典序列

(10)count():返回数据库中匹配查询(QuerySet)的对象数量

(11)first():返回第一个条记录

(12)last():返回最后一条记录

(13)exists():如果QuerySet包含数据,就返回True,否则返回False


惰性机制:Book.objects.all()或者filter()等都只是返回了一个QuerySet(查询结果集对象),他并不会马上执行sql,而是当调用QuerySet的时候才执行。


QuerySet特点:可迭代的、可切片

objs = models.Book.objects.all()
for obj in objs:
  print(obj)

print(objs[1:4])
print(objs[::-1])



正向查询:

book=models.Book.objects.filter(id-2)[0]
authors=models.Author.objects.filter(id_gt=2)
book.author.add(*authors)
book.author.remove(*author)

obj.book_set.values("title").distinct()


反向查询:

author=models.Author.objects.filter(id=3)[0]
books=models.Book.objects.filter(id_gt=2)
author.book_set.add(*books)



单表条件查询(注:是双下划线):

models.TB.objects.filter(id__lt=10, id__gt=1) # 获取id大于1且小于10的值

models.TB.objects.filter(id__in=[11, 22, 33]) # 获取id等于11、22、33的数据

models.TB.objects.exclude(id__in=[11, 22, 33]) # not in

models.TB.objects.filter(name__contains="Ti") # 获取名字中包含“Ti”的数据

models.TB.objects.filter(name__icontains="Ti) # icontains大小写不敏感

models.TB.objects.filter(id__range=[1, 10]) # 范围between a and b

startswith, istartswith, endswith, iendswith


聚合查询和分组查询

(1)aggregate(*args, **kwargs)

通过对QuerySet进行计算,返回一个聚合值得字典。aggregate()中每一个参数都指定一个包含在字典中的返回值。即在查询集上生成聚合。

from django.test import TestCase

# Create your tests here.
from django.db.models import Avg,Min,Sum,Max

# aggregate(*args, **kwargs)
# 计算所有书的平均价格
Book.objects.all().aggregate(Avg("price"))
# aggregate()子句的参数描述了我们想要计算的聚合值

# 如果为聚合值制定一个名称,可以向聚合子句提供它:
Book.objects.aggregate(average__price=Avg('price'))

Book.objects.filter(title="A").aggregate(Avg("price"), Max("price"), Min("price"))

# ----------------------------------------------------------------------

# annotate(*args, **kwargs) 分组
# 可以通过计算查询结果中每一个对象所关联的对象集合,从而得出总计值(也可以是平均值或总和),即为查询集的每一项生成聚合。
Book.objects.filter(author__name='Bob').aggregate(Sum('price'))

# 查询各个作者的书的总价格,这里就涉及到分组了,分组条件是authors__name
Book.objects.values("authors__name").annotate(Sum('price'))

# 查询各个出版社最便宜的书价是多少
Book.objects.values("publisher_name").annotate(Min('price'))



F查询和Q查询:

仅仅靠单一的关键字参数查询已经很难满足查询要求。

# F使用查询条件的值,专门取对象中某列值的操作(只能操作数值)
from django.db.models import F
models.Book.objects.all().update(num=F('num')+1)

# Q构建搜索条件
from django.db.models import Q
# 1 Q对象(django.db.models.Q)可以对关键字参数进行封装,从而更好地应用多个查询
q1 = models.Book.objects.filter(Q(title__startswith='P')).all()

# 2 可以组合使用&,|操作符,当一个操作符是用于两个Q的对象,它产生一个新的对象
obj = models.Book.objects.filter(Q(id=3) | Q(title='python'))

# 3 Q对象可以用~操作符放在前面表示否定,也可允许否定与不否定形式的组合
models.Book.objects.filter(Q(title__startswith='p') | ~Q(author="A"))

# 4 Q对象可以与关键字参数查询一起使用,不过一定要把Q对象放在关键字参数查询的前面
models.Book.objects.filter(Q(price__gt=50)&(Q(id=3)|Q(title='php')),
                           color='yellow,')



6)创建多种关系

创建一对多关系:

publisher = models.ForeignKey("Publish")

创建多对多关系(会创建第三张表):

author = models.ManyToManyField("Author")


模型之间的三种关系:一对一,一对多,多对多

一对一:实质就是在主外键(author_id就是foreign key)的关系基础上,给外键加了一个UNIQUE=True的属性;


一对多:就是主外键关系(foreign key)

(1)models.Book.objects.create(title="Python",price=12,publish_id=2)

(2)(推荐)models.Book.objects.create(title="Python",price=12,publish=obj)


多对多:彼此一对多,自动创建第三张表(当然也可以自己创建第三张表)


自己创建第三张表

class Book2Author(models.Model):
  author=models.ForeignKey("Author")
  book=models.ForeignKey("Book")
  # 创建联合唯一索引
  class Meta:
    unique_together=["author","book"]


8)models字段

AutoField(Field)   int自增列,必须填入参数primary_key=True

BigAutoField(Field) bigint自增列

IntegerField(Field)  整数列

BooleanField(field)  布尔值类型

NullBooleanField(Field)  可以为空的布尔值

CharField(Field)  字符类型,必须提供max_Length参数,max_length表示字符长度

TextField(Field)  文本类型

IPAdressField(Field)  字符串类型,Django Admin以及ModelForm中提供验证IPV4机制

URLField(CharField)  字符串类型,Django Admin以及ModelForm中提供验证URL

FileField(Field) 字符串,路径保存在数据库,文件上传到指定目录;

参数:

upload_to="" :上传文件的保存路径

storage = None:存储组件,默认django.core.files.storage.FileSystemStorage

ImageField(FileField):字符串,路径保存在数据库,文件上传到指定目录

参数:

upload_to="" :上传文件的保存路径

storage = None:存储组件,默认django.core.files.storage.FileSystemStorage

width_field = None:上传图片的高度保存的数据库字段名(字符串)

height_field = None:上传图片的宽度保存的数据库字段名

DateTimeField(DateField):日期+时间格式 YYYY-MM-DD HH:MM:SS

FLoatField(Field):浮点型

DecimalField(Field): 10进制小数

BinaryField(Field):二进制整数


9)参数:

null 数据库中字段是否可以为空

db_column 数据库中字段的列名

default 数据库中字段的默认值

primary_key 数据库中字段是否为主键

db_index 数据库中字段是否可以建立索引

unique 数据库中字段是否可以建立唯一索引

unique_for_date 数据库中字段【日期】部分是否可以建立唯一索引

unique_for_month 数据库中字段【月】部分是否可以建立唯一索引

unique_for_year 数据库中字段【年】部分是否可以建立唯一索引


verbose_name Admin中显示的字段名称

blank Admin中是否允许用户输入为空

editable Admin中是否可以编辑

help_text Admin中该字段的提示信息

choices Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作,例:city = models.IntegerField(choices=[(0, '邯郸'),(1, "邢台"),], default=1)

error_messages  自定义错误信息(字典类型),从而定制想要显示的错误信息。字典键:null, blank, invalid, invalid_choice, unique, unique_for_date,例:{'null': '不能为空','invalid': '格式错误'}

validators 自定义错误验证(列表类型),从而定制想要的验证规则

 

from django.core.validators import RegexValidator
from django.core.validators import EmailValidator, URLValidator, DecimalValidator,\
    MaxLengthValidator, MinLengthValidator, MaxValueValidator, MinValueValidator
test = models.CharField(
    max_length = 32,
    error_messsage={
        'c1': "自定制错误1",
        'c2': "自定制错误2",
        'c3': "自定制错误3",
    },
    validators={
        RegexValidator(regex='root_\d+', message='错误了', code='c1'),
        RegexValidator(regex='root_[abc]\d+', message='错误了', code='c1'),
        EmailValidator(message='邮箱验证错误了', code='c3')
    }
)





10. Admin简介

Django admin是django自带的一个后台app,提供了后台的管理功能

1)认识ModelAdmin

管理界面的定制类,如需扩展特定的model界面须从该类继承

2)注册model类到admin的两种方式:

(1)使用register方法

(2)使用register的装饰器

3)掌握一些常用的设置技巧

list_display:指定要显示的字段

search_fields:指定搜索的字段

list_filter:指定列表过滤器

ordering:指定排序字段


4)为项目后台创建超级管理员:python manage.py createsuperuser

from django.contrib import admin

# Register your models here.
from blog.models import *


class MyAdmin(admin.ModelAdmin):
    # 用以展示数据
    list_display = ('username', 'gender', 'email')

    # 指定搜索字段
    search_fields = ("username")

    # 指定列表过滤器
    list_filter = ("gender")

    # 指定排序字段
    ordering = ("-username")

    # 隐藏字段的设置
    fieldsets = (
        (None, {'fields': ('username', "gender")}),
        ("Advanced options", {'classes':('collapse',),
                              'fields':('email', )
                              })
    )


admin.site.register(UserInfo, MyAdmin)


11. 基于mysql的数据库连接

1)在app应用下的__init__.py文件下写入

import pymysql

pymysql.install_as_MySQLdb()


2)在settings.py文件中加入mysql的配置

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': "ORM",
        "HOST": "127.0.0.1",
        "PORT": "3306",
        "USER": "root",
        "PASSWORD": "root",
    }
}




12. Ajax的介绍

AJAX(Asynchronous Javascript And XML)就是“异步Javascript和XML”,即使用Javascript语言与服务器进行异步交互,传输的数据为XML。当服务器响应时,不用刷新整个浏览器页面,而是可以局部刷新

1)优点:

Ajax使用Javascript技术向服务器发送异步请求;

Ajax无须刷新整个页面;

因为服务器相应内容不再是整个页面,而是页面中的局部,所以Ajax性能高;


2)缺点

Ajax并不适合所有场景,很多时候还是要使用同步交互

Ajax虽然提高了用户体验,但无形中向服务器发送的请求次数增多了,导致服务器压力增大;

因为Ajax是在浏览器中使用Javascript技术完成的,所以还需要处理浏览器兼容性问题;


3)四步操作

创建核心对象

使用核心对象打开与服务器的连接

发送请求

注册监听,监听服务器响应


4)XMLHTTPRequest

open(请求方式,URL,是否异步)

send(请求体)

onreadystatechange,指定监听函数,它会在xmlHttp对象的状态发生变化时被调用

readyState,当xmlHttp对象的状态,其中4状态表示服务器响应结束

status:服务器相应的状态码,只有服务器响应结束时才有,200表示响应成功

responseText:获取服务器的响应体




13. jQuery使用ajax

两种方式:

$.ajax("url",{})

$.ajax({})


请求数据:data,processData,contentType,traditional

data:当前ajax请求要携带的数据,是一个json的object对象,ajax方法就会默认把它编码成某种格式(urlencoded:?a=1&b=2)发送给服务端;此外,ajax默认以get方式发送请求

processData:声明当前的data数据是否进行转码或预处理,默认为true,即预处理;if为false,那么对data:{a:1, b:2}会调用son对象的toString()方法,最后得到一个[object, object]形式的结果

contentType:默认值为"application/x-www-form-urlencoded"。发送信息至服务器时内容编码类型。用来指明当前请求的数据编码格式;urlencoded:?a=1&b=2;如果想以其它方式提交数据,比如contentType:"application/json",即向服务器发送一个json字符串;

traditional:一般是我们的data数据有数组时会用到

案例一  

function Test2(){
        $.ajax({
        url:"/jquery_post",
        type:"POST",
        data:{a:1, b:[2,3,4]},
        processData:false,
        contentType:"application/json",
        traditional:true,
    })
    }

dataType:预期服务器返回的数据类型,服务器端返回的数据会根据这个值解析后,传递给回调函数。默认不需要显性指定这个属性,ajax会根据服务器返回的contentType来进行转换:比如我们的服务器相应的contentType为json格式,这时ajax方法就会对相应的内容进行一个json格式的转换,if转换成功,我们在success的回调函数里就会得到一个json格式的对象;转换失败就会触发error这个回调函数。如果我们明确地指定目标类型,就可以使用dataType。比如服务器响应(Response Headers)的contentType是json格式,但我们希望得到的是json字符串,那就可以把dataType: text,这样ajax方法就不会把返回的数据进行json格式的转换。



14. JSON

JSON是一种轻量级的数据交换格式

JSON是用字符串来表示Javascript对象,Javascript可以执行这个字符串,得到一个Javascript对象

json就是js对象的一种表现形式(字符串的形式)

1)python与json类型转换时的对应

python        json

dict             object

list,tuple     array

str,unicode   string

int,long,float    number

True            true

False           false

None          null


2)ajax中执行的函数

beforeSend 前置处理,发送之前的函数

success 成功执行后的函数

error 发送错误后执行的函数

complete 不管成功与否都会执行的函数

function testData(){
        $.ajax('ajax_get',{
            beforeSend: function(jqXHR, settings){
                console.log(arguments);
                console.log('beforeSend');
                jqXHR.setRequestHeader('test', 'haha');
                jqXHR.testData = {a:1, b:2};
            },
            
            error: function(){
                
            },

            success: function(data){
                console.log(data);
            },

            complete: function(xhr){
                console.log(xhr);
                console.log(xhr.testData)
            }

        });
    }


状态码:

statusCode:{
                '403': function(jqXHR, textStatus, err){
                    console.log(arguments);
                    console.log('status code 403');
                    console.log("ahha403");
                },
                "400": function(){
                    console.log('status code 400');
                    console.log("hhh400")
                }
            }
 



15. 同源策略机制

所谓同源是指,域名,协议,端口相同。不同源的客户端脚本(javascript、ActionScript)在没明确授权的情况下,不能读写对象的资源。


跨域请求数据的解决方式:

<script src="http://127.0.0.1:8001/jquery.get/"></script>



16. JSONP 

以下为JSONP的一个简单例子:创建一个回调函数,然后在远程服务上调用这个函数并且将JSON数据作为参数传递,完成回调

<script>
    function fun1(arg){
        alert("hello" + arg);
    }
</script>
<script src="http://127.0.0.1:8001/get_byjsonp/"></script>
def get_byjsonp(req):
    print("Hello JSONP")
    return HttpResponse('func1("Steve")')

可以通过javascript动态地创建script标签,这样就可以灵活调用远程服务了。

<script>
    function addScriptTag(src){
        var script = document.createElement('script');
        script.setAttribute("type", "text/javascript");
        script.src = src;
        document.body.appendChild(script);
    }
    
    function fun1(arg){
        alert("Hello" + arg);
    }
    
    window.onload = function(){
        addScriptTag("http://127.0.0.1:8002/get_byjsonp?callback=fetch");
    }
</script>



17. jQuery对JSONP的实现

<script type="text/javascript">
    $.getJSON("http://127.0.0.1:8001/get_byjsonp?callback=?", function(arg){
        alert("hello" + arg);
    });
</script>
注意:在url后面必须添加一个callback参数,这样getJSON方法才会知道是用JSONP方式去访问服务,callback后面的那个问号是内部自动生成的一个回调函数。


可以使用$.ajax方法来实现:

$.ajax({
        url:"http://127.0.0.1:8001/get_byjsonp",
        dataType:"jsonp",
        jsonp:'callback',
        success: function(data){
            alert(data);
        }
    });
def get_byjsonp(req):
    callback = req.GET.get("callback")
    return HttpResponse("%s('yuan')" % callback)



18. Cookie

1)保存在用户浏览器端

2)可以主动清除

3)也可以被“伪造”

4)跨域名cookie不共享

5)浏览器可以设置禁用cookie

django案例:

from django.shortcuts import render,redirect
from app01 import models
# Create your views here.


def login(request):
    models.Administrator.objects.create(
        username = 'root',
        password = 'root',
    )
    message = ""

    if request.method == "POST":
        user = request.POST.get('user')
        pwd = request.POST.get('pwd')

        c = models.Administrator.objects.filter(username=user, password=pwd).count()
        if c:
            # 在Cookie当中放置当前的用户名
            rep = redirect('/index.html')
            # 设置有效时间
            rep.set_cookie('username', user, max_age=10)
            rep.set_cookie('email', user+"@live.com")
            return rep
        else:
            message = "用户名或密码错误"

    return render(request, "login.html", {'msg': message})


def index(request):
    # 如果用户已经登录,获取当前登录的用户名
    # 否则返回登录页面
    username = request.COOKIES.get('username')
    email = request.COOKIES.get('email')

    if username:
        return render(request, "index.html", {'username': username, 'email':email})
    else:
        return redirect('/login.html')

7)path参数:“/”表示全局生效,“/xxxx”表示当前url生效

8)domain:顶层域名,例domain='alexander.com'

9)httponly:仅仅http网络传输使用


10)jquery操作cookie

html页面:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <script src="/static/jquery.cookie.js"></script>
    <script src="/static/jquery-3.2.1.js"></script>

    // $.cookie()
    // 一个参数: $.cookie(k) 获取值
    // 两个参数: $.cookie(k, v) 设置值
    <script>
        $.cookie('k','v', {"path": "/"})
    </script>
</body>
</html>


11)Cookie的应用:

    登录认证

        - 敏感信息不宜放置在cookie中,敏感信息放在数据库,频繁操作数据库


    加密Cookie,敏感信息(可能会解密)

rep.set_signed_cookie('email', user+"@live.com")    


19. Session

session是服务器端的一个键值对

session内部机制依赖于cookie

# 获取session值

request.session['k']

request.session.get('k1', None)

# 设置session值

request.session['k1'] = v

request.session.setdefault('k1', 123) # 存在则不设置


# 删除session中的键值对

del request.session['k1']

request.session.clear()


# 所有键、值、键值对

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")




20. Form类

1)创建Form类时,主要涉及“字段”和“插件”,字段用于对用户请求数据的验证,插件用于自动生成HTML

Field:

required=True, 是否允许为空

widget=None, HTML插件

label=None, 用于生成label标签或显示内容

initial=None, 初始值

help_text=' ', 帮助信息(在标签旁边显示)

error_message=None,  错误信息{'required': '不能为空', 'invalid': '格式错误'}

show_hidden_initial=False, 是否在当前插件后面再加一个隐藏的且具有默认值的插件(可用于检验两次输入输入是否一致)

validators=[], 自定义验证规则

localize=False, 是否支持本地化

disabled=False, 是否可以编辑

label_suffix=None label内容后缀


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:22

DateTimeField(BaseTemporalField) 格式:2015-09-01 11:22


DurationField(Field) 时间间隔


RegexField(CharField):

regex, 自定制正则表达式

max_length=None, 最大长度

min_length=None, 最小长度

error_message=None, 忽略,错误信息使用error_message={'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)


TypedCHoiceField(ChoiceField)

coerce = lambda val: val  对选中的值进行一次转换

empty_value='' 空值的默认值


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类型


2)Django内置插件, widget=

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





21. 请求头获取用户设备

request.environ.get('HTTP_USER_AGENT')





22. 循环实现评论数据结构

ret = []
    comment_list_dict = {}

    for row in comment_list:
        row.update({'children': []})
        comment_list_dict[row['id']] = row
        
    for item in comment_list:
        parent_row = comment_list_dict.get(item['parent_id'])
        if not parent_row:
            ret.append(item)
        else:
            parent_row['children'].append(item)




23. Model&Form&ModelForm:

Model:用于数据库操作

Form:用于用户请求的验证

ModelForm:用于数据库操作(部分),用于用户请求的验证(部分)


1)Model操作:

a. 数据表操作

Code First:创建类->自动生成表

DB First:创建表->自动生成类


字段:数字、字符串、时间、文件、关系

参数:用以指定生成数据库列信息;用于验证(admin、ModelForm);关系(一对一,一对多,多对多)



24. model数据库查询进阶操作

获取个数

models.tb.objects.filter(name='seven').count()


大于,小于

models.tb.objects.filter(id__gt=1) # 获取id大于1的值

models.tb.objects.filter(id__gte=1) # 获取id大于等于1的值

models.tb.objects.filter(id__lt=1) # 获取id小于10的值

models.tb.objects.filter(id__lte=1) # 获取id小于等于10的值

models.tb.objects.filter(id__lt=1, id__gt=1) # 获取id大于1且小于10的值


in

models.tb.objects.filter(id__in=[11,22,33]) # 获取id等于11,22,33的数据

models.tb.objects.exclude(id__in=[11,22,33])# not in


isnull

models.tb.objects.filter(pub_date__isnull=True)


contains

models.tb.objects.filter(name__contains="ven")

models.tb.objects.filter(name__icontains="ven") # icontains大小写不敏感

models.tb.objects.exclude(name__icontains="ven")


range

models.tb.objects.filter(id__range=[1,2]) # 范围between and


其他类似

startswith, istartswith, endswith, iendswith


order by

models.tb.objects.filter(name='seven').order_by('id') # asc

models.tb.objects.filter(name='seven').order_by('-id') # desc



group by

from django.db.models import Count, Min, Max, Sum

models.tb.objects.filter(c1=1).values('id').annotate(c=Count('num'))

select "app_tb"."id", count("app_tb", "num") as "c" from "app_tb" where "app_tb"."c1" = 1 group by "app_tb"."id"


limit, offset

models.tb.objects.all()[10:20]


regex正则匹配,iregex不区分大小写

Entry.objects.get(title__regex=r'^(An?|The)+')

Entry.objects.get(title__iregex=r'^(an?|the)+')


date

Entry.objects.filter(pub_date__date=datetime.date(2005,1,1))

Entry.objects.filter(pub_date__date__gt=datetime.date(2005,1,1))


year

Entry.objects.filter(pub_date__year=2005)

Entry.objects.filter(pub_date__year__gte=2005)





25.


猜你喜欢

转载自blog.csdn.net/wayne12081213/article/details/79794592