拾 ● 模型(M)

一 ● ORM(对象关系映射, Object Relational Mapping)

类----一张表

类的实例对象----表中的一条记录

映射关系

①python的类名对应的SQL语句的表名

② python的类属性对应的SQL语句的表名下的字段

③ python的类属性的约束对应的SQL语句的表名下的字段类型

开始使用Django的ORM

from django.db import models
class ModelName(models.Model):
    field1 = models.XXField(...)   # 表单字段是field1 = forms.XXField(...)
    field2 = models.XXField(...)
    ... ...

class Meta:

db_table = ...
        other_metas = ...

① model字段类型都继承自抽象类django.db.models.Field

普通字段: 模型类中除外键外的字段属性, 如:

CharField(),

IntegerField(),

FloatField(),

DateField(),

EmailField()

② 有一些每个字段都可以设置的公共参数:

● primary_key = True--字段是否为主键

● unique=True--在数据库中是否是唯一的字段

③ class Meta中的tb_table是映射的数据表名, 例如: tb_table = 'moments'

如果不提供上述字段, 自动生成表名, 格式为"应用名_模型名"

※ model字段类型 & 表单字段类型总结: (这些字段其实都是类!!!)

model字段类型 & 字段选项

http://mode1943.blog.163.com/blog/static/7921843620140641159627/

表单字段类型

http://python.usyiyi.cn/documents/django_182/ref/forms/fields.html#built-in-field-classes

对比: "Django的表单系统: 主要分两种"这一节

查询记录

1 ● 单表查询

① 使用API

13个API查询:all,filter,get ,values,values_list,distinct,order_by ,reverse , exclude,count,first,last,exists(判断是否存在)

② 基于双下划线查询

● ※ 单表查询详解

① 使用API

(1)Student.objects.all() #返回的QuerySet类型(集合对象), 查询所有记录 [obj1,obj2....]

(2)Student.objects.filter() #返回的QuerySet类型, 查询所有符合条件的记录

(3)Student.objects.exclude() #返回的QuerySet类型, 查询所有不符合条件的记录

(4)Student.objects.get() #返回的models对象, 查询结果必须有且只有一个,否则报错

(5)Student.objects.all().first() #返回的models对象, 查询结果集合中的第一个

(6)Student.objects.filter().last( #返回的models对象, 查询结果集合中的最后一个

(7)Student.objects.all().values("name","class_id") #返回的QuerySet类型 ,列表中存放的是字典

(8)Student.objects.all().values_list("name","class_id") #返回的QuerySet类型 ,列表中存放的是元组

(9)Student.objects.all().order_by("class_id") # 按指定字段排序,不指定,按主键排序

(10)Student.objects.all().count() # 返回的记录个数

(11)Student.objects.all().values("name").distinct() # 从返回剔除重复纪录的结果

(12)Student.objects.all().values("name").reverse() #对查询结果反向排序

(13)Student.objects.all().exist() # 如果QuerySet包含某数据,就返回True,否则返回False

※ values()、values_list()获取Building的number字段列表
from apps.dormitory.models import Building
buildings = Building.objects.values('number')
# [{'number': u'1'}, {'number': u'2'}, {'number': u'3'}, {'number': u'4'}, {'number': u'5'}]
buildings_ = Building.objects.values_list('number')
# [(u'1',), (u'2',), (u'3',), (u'4',), (u'5',)]
buildings_list = Building.objects.values_list('number', flat=True)
# [u'1', u'2', u'3', u'4', u'5']
# 因此:
# values()可以获取number字段的字典列表。
# values_list()可以获取number字段的元组列表。
# values_list()加个参数flat=True可以获取number字段的值列表。

② 基于双下划线查询

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

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

(3)models.Tb1.objects.exclude(id__in=[11, 22, 33]) # 相当于not in

(4)models.Tb1.objects.filter(name__contains="ven") # 包含

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

(6)models.Tb1.objects.filter(id__range=[1, 2]) # 范围吗相当于bettwen and

(7)startswith, istartswith(对大小写不敏感)

(8)endswith, iendswith(对大小写不敏感)

2 ● 跨表查询

① 基于对象跨表查询(对应sql的子查询)

② 基于双下划线查询(对应sql的join查询)

● ※ 跨表查询详解

'''
# 出版社与书是一对多的关系
# 作者与书是多对多的关系
# 作者与作者详细信息是一对一的关系
'''
# (下面是SQL对照ORM)
# 表1--书籍: 出版社与书是一对多的关系; 作者与书是多对多的关系
'''
create table book(

nid int primary key auto_increment,

title char(20) ,

price float(6,2),
    pulishDate Date,
    pub_id int(),
    foreign key (pub_id) references publish(nid) //出版社与书是一对多的关系
)
'''
class Book(models.Model):
    title = models.CharField(max_length=32)
    publishDate = models.DateField()
    price = models.DecimalField(max_digits=5, decimal_places=2)   #  999.99
    # ①
publish=models.ForeignKey("Publish")

# 更详细的写法是 publish=models.ForeignKey(to="Publish",to_field="nid")
    # publish字段会默认关联到Publish表的主键
    # 创建一对多的关联字段publish, 出版社与书是一对多的关系:
    # publish是与某个书籍对象关联的出版社对象(注意,一本书只对应一个出版社对象)
    # 对于外键字段(关联字段),Django 会在字段名上添加"_id" 来创建数据库中的列名, 即publish_id
    # 注意, 不可以在"一对多"中"一"的那边, 即publish表建立关联字段book
    # ②
    # 创建多对多的关系, 书与作者是多对多的关系
authors=models.ManyToManyField("Author")

# 注意, 也可以在"多对多"中的另一张表建立关联字段,
    # 即在Author表中建立: books=models.ManyToManyField("Book")
def __str__(self):

return self.title
# book_obj=Book.objects.get(nid=1)  # 没有all()
# print(book_obj.publish.addr)
# book_obj.publish 是nid=1的书籍对象关联的出版社对象,
# print(book_obj.authors.all())
# book_obj.authors是nid=1的书籍对象关联的所有作者对象
################################################################
# 表2--出版社:
'''
create table publish(

nid int primary key auto_increment,

name char(20),

addr char(20)
)
'''
class Publish(models.Model):
    nid = models.AutoField(primary_key=True)
    name=models.CharField( max_length=32)
    email=models.EmailField()
################################################################
# 表3--作者: 与作者详细信息表是一对一的关系, 两种表一旦确定是一对一的关系, 在任何一张表中都可建立关联字段,但是注意关联字段必须唯一约束
'''
create table Author(

nid int primary key auto_increment,

name char(20),

age int
)
'''
class Author(models.Model):
    name=models.CharField(max_length=32)
    age=models.IntegerField()

# Author和Book是多对多的关系, 因此关联字段也可以建立于此:
books=models.ManyToManyField("Book")

# 注意, 此时通过作者莫言找书是正向查询, 通过<<红高粱>>找作者是反向查询
def __str__(self):

return self.name
##################################################
# 表4--作者详细信息:
'''
create table AuthorDetail(

nid int primary key auto_increment,

tel char(20),

addr char(20),

author_id int unique, //注意关联字段author_id必须约束为unique
    foreign key (author_id) references Author(nid) //因为是一对一的关系, foreign key写在Author表也行
)
'''
class AuthorDetail(models.Model):

# 创建一对一的关系
addr=models.CharField(max_length=32)
    email=models.EmailField()
    author=models.OneToOneField("Author")
##################################################
# 表5--书到作者: 书与作者是多对多的关系, 两种表一旦确定是多对多的关系, 必须建立第三张表
'''
create table book2author(

nid int primary key auto_increment,

book_id int,

author_id int,
    foreign key (book_id) references book(nid),
    foreign key (author_id) references author(nid)
)
'''
# 没有对应的类, 因为书与作者的多对多的关系在Book类中已经建立了
###########################################################
1, ---------  基于对象跨表查询(对应sql的子查询)
                        .publish

① ==== 一对多(Book----------------->Publish)
                    <----------------
                      .book_set.all()
查询python这本书的出版社的名字(正向查询, 用字段; Book类的对象, 即这里的book_obj有出版社字段, 即publish)
  book_obj=Book.objects.get(title="python")
  print(book_obj.publish.name)
查询沙河出版社出版过的书籍名称    (反向查询, 用表名; Publish类的对象, 即这里的pub_obj没有和书籍有关的字段)
  pub_obj=Publish.objects.get(name="沙河出版社")
  print(pub_obj.book_set.all())
                        .authors.all()

② ==== 多对多(Book------------------->Author)
                     <--------------------
                        .book_set.all()
查询python这本书的所有作者的名字(正向查询,按字段)
  book_obj=Book.objects.get(title="python")
  print(book_obj.authors.all())
查询alex出版过的所有书籍 (反向查询按:表名_set)
  author_obj=Author.objects.get(name="alex")
  print(author_obj.book_set.all()) # <QuerySet [<Book: 西游记4>, <Book: 西游记5>]>
                                 .author

③ ==== 一对一(AuthorDetail--------------->Author)
                             <----------------
                               .authordetail
查询的地址在烟台并且email是789的作者的名字(正向查询,按字段)
   authordetail=AuthorDetail.objects.get(addr="烟台",email=789)
   print(authordetail.author.name)
查询文州的email (反向查询按:表名)
   wenhzou=Author.objects.get(name="文州")
   print(wenhzou.authordetail.email) # 123@qq.com
   # 查询住在沙河的作者出版过的所有书籍的名称以及出版社名称
   author_obj=Author.objects.get(name="alex")
   print(author_obj.book_set.all()) # <QuerySet [<Book: 西游记4>, <Book: 西游记5>]>
2, ---------  基于双下划线查询(对应sql的join查询)
###基于双下划线的查询:正向查询,按字段;反向查询,按表名###

① # 查询沙河出版社出版过的书籍名称
 # ret=Publish.objects.filter(name="人民出版社").values("book__title")
 # print(ret)

② # 查询人民出版社出版过的书籍名称
 # Book.objects.filter(publish__name="人民出版社").values("title")

③ # 查询email以456开头的作者出版过的所有书籍名称以及出版社名称
 # ret=Book.objects.filter(authors__authordetail__email__startswith="456").values("title","publish__name")
 # print(ret)

3 ● 聚合查询

与SQL的聚合函数相关

aggregate(*args, **kwargs)

aggregate是只选择你感兴趣的,返回的是一个字典

4 ● 分组查询

为调用的QuerySet中每一个对象都生成一个独立的统计值(统计方法用聚合函数), 该统计值对应一个字段

可理解为我们可以给该模型加个字段作为注释。

annotate是在返回原来的queryset的基础之上,再加上额外的存储统计值字段。

例如: 查询每一本书的名字,对应出版社名称以及作者的个数

bookList = Book.objects.annotate(authorsNum=Count('authors'))

那么for book_obj in bookList: print(book_obj.__dict__); 我们可以发现多了一个authorsNum属性.

5 ● F查询

※ 前面的例子是比较字段值与某个常量

※ 现在要比较两个字段的值, 例如:

※ 查询评论数大于收藏数的书籍

from django.db.models import F

Book.objects.filter(commnetNum__gt=F('keepNum'))

6 ● Q查询

※ filter()等函数实现的查询是"逻辑与(AND)"的查询, 现在要实现"逻辑或(OR)"的查询

from django.db.models import Q

bookList=Book.objects.filter(Q(authors__name="yuan")|Q(authors__name="egon"))

等价于sql的:

WHERE name ="yuan" OR name ="egon"

四、添加记录

1 ● 单表添加记录

方式1:

s=Student(name='Arroz',age=18) # 指定多个键值对, 也可以写成s=Student(**{"name":"Arroz", "age":18})

s.save()

方式2:

stu_obj=Student.objects.create(name='Arroz',age=18) # stu_obj是添加的记录对象

2 ● 跨表添加记录

一对多添加方式:

方式1:

# 建立出版社和书的一对多的关系

book_obj=Book.objects.create(title="python",price=223,publisher_id=2)

方式2:

book_obj=Book.objects.get(nid=1)

print(book_obj.publisher) # 是nid=1的这本书的关联的出版社对象(一个对象)

book_obj=Book(title="Linux",price=122,publisher=publish_obj)

多对多的添加方式:

ManyToManyField:

# 绑定关系

book_obj=Book.objects.get(nid=2)

author_list=Author.objects.all()

# 建立书和作者的多对多的关系

book_obj.authors.add(*author_list) # book_obj.authors: nid=2 的书籍关联的作者的对象集合

# 解除关系

book_obj.authors.clear() #解除所有绑定关系

book_obj.authors.remove(author) #解除单个绑定关系

手动创建第三张表:

Book2Author.objects.create(book_id=1,author_id=1)

● ※ 中介模型(intermediate model)

对于"多对多"关系的两张表, Django会为我们自动创建第三张表,但是这张表只有关联字段;

如果要添加额外的字段(extra field) 或者约束(如联合唯一索引),此时就需要自己建立第三张表, 即中介模型(此时, 关联字段没有自动创建, 需要自己创建)

修改记录

Book.objects.filter(id=3).update(title="西游记")
Book.objects.filter(id__gt=10).update()
# 出错--Book.objects.get(id=5).update()    # models对象不能调用update方法
※ 注意:
表.object.filter():得到的是一个集合对象比如 [obj1,obj2]
表.object.get():得到的是一个model对象
# 收藏数都加1
from django.db.models import F
Book.objects.update(num=F(''keepNum'')+1)

删除记录

Book.objects.filter(id=1).delete()
(3, {'app01.Book_authors': 2, 'app01.Book': 1})
# 我们表面上只删除了1条信息,实际上删除了3条记录--这叫级联删除, 即删除和id=1的书的相关记录.

拾壹 ● 模板(T)

一 ● 模板定义

模块----模板包含① HTML代码( 输出静态部分) + ② 逻辑控制代码(动态插入部分)

※ 模板语法

二 ● 模板语法之变量

语法:{{var_name}}

def index(request):

import datetime

s = "hello"
l = [111, 222, 333]  # 列表
dic = {"name": "yuan", "age": 18}  # 字典
date = datetime.date(1993, 5, 2)  # 日期对象
class Person(object):

def __init__(self, name):

self.name = name
    person_yuan = Person("yuan")  # 自定义类对象
person_egon = Person("egon")
    person_alex = Person("alex")
    person_list = [person_yuan, person_egon, person_alex]

return render(request, "index.html", {"l": l, "dic": dic, "date": date, "person_list": person_list})
<h4>{{s}}</h4>                                  <!--hello-->
<h4>列表:{{ l.0 }}</h4>                           <!--111-->
<h4>列表:{{ l.2 }}</h4>                           <!--333-->
<h4>字典:{{ dic.name }}</h4>                      <!--yuan-->
<h4>日期:{{ date.year }}</h4>                      <!--2018-->
<h4>类对象列表:{{ person_list.0.name }}</h4>        <!--yuan-->

注意:句点符也可以用来引用对象的方法(无参数的方法)。

<h4>字典:{{ dic.name.upper }}</h4> <!--YUAN-->

※ 调试方法

>>> python manage.py shell (进入该django项目的环境)

>>> from django.template import Context, Template

>>> t = Template('My name is {{ name }}.')

>>> c = Context({'name': 'Stephane'})

>>> t.render(c)

'My name is Stephane.'

三 ● 模板语法之过滤器

语法 {{obj|filter_name:param}}

1、default如果一个变量是false或者为空,使用给定的默认值。否则,使用变量的值。例如:

<p>default过滤器:{{ li|default:"内容为空" }}</p>

2、length返回值的长度。它对字符串和列表都起作用。例如:

{{ value|length }}

如果 value 是 ['a', 'b', 'c', 'd'],那么输出是 4。

3、filesizeformat将值格式化为一个 "人类可读的" 文件尺寸(例如 '13 KB', '4.1 MB', '102 bytes', 等等)。例如:

{{ value|filesizeformat }}

如果 value 是 123456789,输出将会是 117.7 MB。

4、date:

value=datetime.datetime.now()

{{ value|date:"Y-m-d" }}

5、slice:切片

如果 value="hello world"

{{ value|slice:"2:-1" }}

6、truncatechars: 截断

如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列("...")结尾。

参数:要截断的字符数()、单词数

value="Arroz is a boy"

<p>截断字符:{{ value|truncatechars:10 }}</p> <!---->

<p>截断单词:{{ value|truncatewords:4 }}</p> <!---->

7、safe

为了安全, Django的模板中会对HTML标签和JS等语法标签进行自动转义,safe过滤器告诉Django这段代码是安全的,不必转义:

value="<a href="">点击</a>"

{{ value|safe}}

其它过滤器详见:

http://python.usyiyi.cn/translate/django_182/ref/templates/builtins.html#ref-templates-builtins-tags

四 ● 模板语法之标签(流程控制)

语法: {% tag %}

1、for标签(注:循环序号可以通过{{forloop}}显示)

<h3>循环取值1</h3><hr>
{% for item in person_list %}

<p>{{ item.name }},{{ item.age }}</p>
{% endfor %}
<h3>循环取值2:倒序</h3><hr>
{% for item in person_list reversed %}

<!--序号从1开始-->

<p>{{ forloop.counter }}----->{{ item.name }},{{ item.age }}</p>
<!--序号从0开始-->
<p>{{ forloop.counter0 }}----->{{ item.name }},{{ item.age }}</p>
<!-- 序号倒序-->
<p>{{ forloop.revcounter }}----->{{ item.name }},{{ item.age }}</p>
{% endfor %}
<h3>循环取值3:字典</h3><hr>
{% for k,v in d.items %}

<p>{{ k }},{{ v}}</p>
{% endfor %}

2、for....empty :for 标签带有一个可选的{% empty %} 从句,给出的列表为或列表不存在时,执行此处:

案例1:
{% for person in person_list %}

<p>{{ person.name }}</p>
{% empty %}

<p>sorry,no person here</p>
{% endfor %}
案例2:
{%  for i in li %}

<li>{{ forloop.counter0 }}----{{ i }}</li>
{% empty %}

<li>this is empty!</li>
{% endfor %}
# [11, 22, 33, 44, 55]
# 0----11
# 1----22
# 2----33
# 3----44
# 4----55

3

、if标签:{% if %}会对一个变量求值,如果它的值是"True"(存在、不为空、且不是boolean类型的false值),对应的html代码会输出。
{% if i > 300 %}

<p>大于{{ i }}</p>
{% elif i == 200  %}

<p>等于{{ i }}</p>
{% else %}

<p>小于{{ i }}</p>
{% endif %}

4

、with:使用一个简单的名字缓存一个复杂的变量,当你需要使用一个"昂贵的"方法(比如访问数据库)很多次的时候是非常有用的
案例1:
{% with total=business.employees.count %}
    {{ total }} employee{{ total|pluralize }}
{% endwith %}
案例2:
<p>{{ person_list.2.name }}</p>
{% with name=person_list.2.name %}

<p>{{ name }}</p>
{% endwith %}

5

、csrf_token:这个标签用于防止跨站请求伪造
<h3>scrf_token</h3>
<form action="/tag/" method="post">
    {% csrf_token %}

<p><input type="text" name="haiyan"></p>
<input type="submit">
</form>

6

、{% url %}用于url反向解析

● ※ (了解)自定义标签和过滤器

1、在settings中的INSTALLED_APPS列表中配置当前app,不然django无法找到自定义的simple_tag.

2、在app中创建templatetags包(包名只能是templatetags)

3、在templatetags里面创建任意 .py 文件,如:my_tags.py

from django import templatefrom django.utils.safestring import mark_safe
register = template.Library()   #register的名字是固定的,不可改变
@register.filter   过滤器
def multi(x,y):
    return x*y
@register.simple_tag  标签
def multitag(x,y,z):
    return x*y*z
@register.simple_tag  标签
def my_input(id,arg):
   result = "<input type='text' id='%s' class='%s' />" %(id,arg,)
   return mark_safe(result)

4、在需要使用自定义的simple_tag和filter的html文件中导入之前创建的 my_tags.py

{% load my_tags %}

5、使用filter和simple_tag(注意如何调用)

※ 过滤器:{{ var|filter_name:参数 }} # 参数只能是两个,一个参数是变量var ,一个是filter_name:后面的那个参数

※ 标签:{% simple_tag 参数1 参数2 ... %}

<!--某html文件-->
{% load xxx %}  
#
首行
# ① filter {{}}
# view中定义num=12
# html中定义如下
{{ num|filter_multi:2 }} #24  # filter只能接受一个参数
{{ num|filter_multi:"[22,333,4444]" }}
# 传入一个集合,循环集合内部的元素,但实现比较复杂,结果为12*22*333*4444
# ② simple_tag {% %}
{% simple_tag_multi 2
5
%}
# 参数不限,当然传入的参数和定义的参数个数要一直,但不能放在if for语句中
{% simple_tag_multi num 5 %}

※ 自定义过滤器函数的参数只能两个,可以进行逻辑判断; 自定义标签无参数限制,不能进行逻辑判断. 也就是说:

filter可以用在if等语句后,simple_tag不可以(因为simple_tag也用的是{% %}(调用的时候必须加) 会和外层if的{% %} 冲突)

五 ● 模板语法之继承

定义:模板继承可以减少页面内容的重复定义,实现页面内容的重用

典型应用:网站的头部、尾部是一样的,这些内容可以定义在父模板中,子模板不需要重复定义, 例如:

● 继承中用到的两个标签

block标签:在父模板中预留区域,在子模板中填充

extends标签:继承,写在模板文件的第一行

● 继承的步骤

1, 定义父模板base.html

{ %block block_name%}
这里可以定义默认值
如果不定义默认值,则表示空字符串
{ %endblock%}

2, 定义子模板index.html

{ % extends "base.html" %}

<!--在子模板中使用block填充预留区域-->

{ %block block_name%}

实际填充内容

{ %endblock%}

● 模板语法总结

{{ item }}

{% for item in item_list %} <a>{{ item }}</a> {% endfor %}

  forloop.counter

  forloop.first

forloop.last

{% if ordered_warranty %} {% else %} {% endif %}

母板:{% block title %}{% endblock %}

子板:{% extends "base.html" %}

   {% block title %}{% endblock %}

帮助方法:

{{ item.event_start|date:"Y-m-d H:i:s"}}

{{ bio|truncatewords:"30" }}

{{ my_list|first|upper }}

{{ name|lower }}

拾贰 ● Django静态文件的引入使用

项目中的CSS、图片、js都是静态文件

分两种情况:

① 在开发环境中引入静态文件

② 部署到nginx等web服务器时引入静态文件

一 ● 在开发环境中引入静态文件

# settings.py

# settings.py
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
STATIC_URL = '/statics/'  # 别名, 引用名
STATIC_ROOT = os.path.join(BASE_DIR,'statics')  # 运行manage.py collectstatic后静态文件将复制到的目录。注意:不要把你项目的静态文件放到这个目录下, 这个目录只有在运行collectstatic时才会用到。
STATICFILES_DIRS = (os.path.join(BASE_DIR, 'app01', 'statics'),    #实际名 ,即实际文件夹的名字
)
# 试着看看静态文件有没有加载成功:
# <img src="/statics/images/1.jpg">
# http://127.0.0.1:8000/static/jquery.js

二 ● 部署到nginx等web服务器时引入静态文件

URI请求-----> 按照Web服务器里面的配置规则先处理,以nginx为例,主要求配置在nginx.conf里的location

----如果是静态文件,则由nginx直接处理

----如果不是则交由Django处理,Django根据urls.py里面的规则进行匹配

● ※ URI和URL的区别

URI (Uniform Resoure Locator, 统一资源标识符)是从虚拟根路径开始的

URL(Uniform Resoure Identifier, 统一资源定位符)是整个链接

例如:

URL---http://zhidao.baidu.com/question/68016373.html

URI----/question/68016373.html搜索

Baidu的服务器上把http://zhidao.baidu.com/制作成了虚拟的路径的根

● ※ media配置

static和media的区别:

static是不变的,形成网站的核心部件,如 CSS文件,JS文件,背景图片等;

media是变动的,由用户定义的文件,如用户头像,用户上传的图片或视频等。

# 第一步: settings.py
import os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
MEDIA_URL="/media/"
MEDIA_DIR=os.path.join(BASE_DIR,"blog","media")
MEDIA_ROOT=MEDIA_DIR
# 第二步: 直接在项目下的urls.py:
from django.conf.urls import url,include
from django.views.static import serve
urlpatterns = [

# media 配置
url(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}), # 需要引入settings, 例如:from MyBlog import settings
    # The serve() view can be used to serve any directory you give it.
    # 将{'document_root': settings.MEDIA_ROOT}传给serve
]
# 试试看有没有加载成功
# http://127.0.0.1:8000/media/1.png

拾叁 ● cookie和session

一、cookie

定义和作用

ookie是在客户端记录用户信息的键值对

cookie 是怎么在浏览器和服务器之间交互的?

是通过http的响应头和请求头使客户端和服务器端进行交互的。

cookie数据格式

{

name : value,

name : value,...

}

例如:

{

"is_login" : True,

"csrftoken" : "vdfvdfdfgf43r32",

"sessionid" :"asdfghjkasdfghjk" # 随机字符串"asdfghjkasdfghjk"是服务端session 的name

}

※ 手动抓包两种方法

wireshark抓包和fiddler抓包

详见: http://www.chinaz.com/web/2015/0326/393344.shtml

● 二、session

定义和作用

session是在服务端记录用户信息的键值对, 避免密码等敏感信息保存在客户端,并且防止客户端修改cookie信息.

session数据格式

{

session_key(随机字符串) : {session_data}(加了密的用户1的信息字典),

session_key(随机字符串) : {session_data}(加了密的用户2的信息字典),

... ...

}

例如:

{

"asdfghjkasdfghjk" : {id:1, name:"alex"},

"zxcvbnmzxcvbnm" : {id:1, name:"eric"}

}

※ {id:1,nam:"alex",account:1000000000 }这些数据会被加密, 例如:

● 三、session依赖于cookie

● ※ Django的session与cookie的实现原理

版本一:

① 服务器会生成两份相同的cookie字符串,一份保存在本地,一份发向浏览器。

② 浏览器将收到的cookie字符串保存下来,当下次再请求时,会将这段cookie发送到服务器,

服务器得到这段cookie会与本地保存的那份判断是否相同,如果相同就表示用户已经登录成功,保存用户登录成功的状态。

※ Django cookie的有一个key是sessionid, value是随机字符串

※ Django session保存在数据库的数据相当于一个大字典,key(session_key)为cookie的随机字符串,

value(session_data)是一个加密的字典,字典的key和value为用户设置的相关信息。

※ 如过打开一个网页没有提交sessionID上来,服务器会认为你是一个全新的请求,服务器会给你分配一个新的sessionID,这就是为什么我们每次打开一个新的浏览器的时候(无论之前我们有没有登录过)都会产生一个新的sessionID(或者是会让我们重新登录)。

版本二:

① 浏览器向服务器发送请求, 请求头包括url地址;
② 如果请求方式是POST, 服务器生成session数据, 例如:  {id:asdfg, name:"alex", account:1000000000 },由request.session来保存这个字典, 例如request.session['name']='alex',注意, request.session默认隐含了通过sessionID找到用户信息那一步;
③ 将第②步生成的session数据中的session_key对应的随机字符串asdfg作为cookie的键(key)发送给浏览器
④ 当浏览器再次向上述服务器发送请求时, 会发送第③步的cookie, 服务器会根据这个cookie, 获取响应的键值对, 例如{iflogin:'true'}, 然后做出相应的操作.

※ JQuery中$.cookie()方法的使用

使用背景

① 浏览器存储了cookie

② 借助jquery.cookie.js插件

<!--使用案例-->
<script type="text/javascript" src="js/jquery-1.6.2.min.js"></script>
<script type="text/javascript" src="js/jquery.cookie.js"></script>
<script>

//新增cookie:

$
.cookie('cookieName', 'cookieValue');

//注:如果没有设置cookie的有效期,则cookie默认在浏览器关闭前都有效,故被称为"会话cookie"。
    // 创建一个cookie并设置有效时间为7天:

$
.cookie('cookieName', 'cookieValue', {expires: 7});

// 创建一个cookie并设置cookie的有效路径:

$
.cookie('cookieName', 'cookieValue', {expires: 7, path: '/'});

//读取cookie:

$
.cookie('cookieName'); // //若cookie存在则返回'cookieValue';若cookie不存在则返回null
    //删除cookie:把ncookie的值设为null即可

$
.cookie('the_cookie', null);
</script>

Django知识总结(二)的更多相关文章

  1. Python 学习第十九天 django知识

    一,django 知识总结 1,同一个name属性的标签,多个值获取 <form action="/login/" method="POST" encty ...

  2. Python学习---django知识补充之CBV

    Django知识补充之CBV Django: url    -->  def函数      FBV[function based view]  用函数和URL进行匹配 url    --> ...

  3. Django学习笔记二

    Django学习笔记二 模型类,字段,选项,查询,关联,聚合函数,管理器, 一 字段属性和选项 1.1 模型类属性命名限制 1)不能是python的保留关键字. 2)不允许使用连续的下划线,这是由dj ...

  4. Django之Models(二)

    Django之Models(二) 创建一对多的关系 一个出版商可以有多本出版的书 一本书只有一个出版商 创建一对多的语法: 字段名= models.ForeignKey(关联表(类名),on_dele ...

  5. Django开发笔记二

    Django开发笔记一 Django开发笔记二 Django开发笔记三 Django开发笔记四 Django开发笔记五 Django开发笔记六 1.xadmin添加主题.修改标题页脚和收起左侧菜单 # ...

  6. {django模型层(二)多表操作}一 创建模型 二 添加表记录 三 基于对象的跨表查询 四 基于双下划线的跨表查询 五 聚合查询、分组查询、F查询和Q查询

    Django基础五之django模型层(二)多表操作 本节目录 一 创建模型 二 添加表记录 三 基于对象的跨表查询 四 基于双下划线的跨表查询 五 聚合查询.分组查询.F查询和Q查询 六 xxx 七 ...

  7. Java JDBC的基础知识(二)

    在我的上一篇Java JDBC的基础知识(一)中,最后演示的代码在关闭资源的时候,仅仅用了try/catch语句,这里是有很大的隐患的.在程序创建连接之后,如果不进行关闭,会消耗更多的资源.创建连接之 ...

  8. Django 知识补漏单例模式

    Django 知识补漏单例模式 单例模式:(说白了就是)创建一个类的实例.在 Python 中,我们可以用多种方法来实现单例模式: 1.文件导入的形式(常用) s1.py class Foo(obje ...

  9. 基于Ubuntu Server 16.04 LTS版本安装和部署Django之(二):Apache安装和配置

    基于Ubuntu Server 16.04 LTS版本安装和部署Django之(一):安装Python3-pip和Django 基于Ubuntu Server 16.04 LTS版本安装和部署Djan ...

随机推荐

  1. 手机app抓包

    简介 爬虫是cs架构中的c端 原理是模拟浏览器向服务器发送请求 如果要爬取手机APP的数据,APP也是服务端与浏览器性质相同 我们只要获取到手机APP给服务器发送数据 并加以分析就能模拟它的请求 从而 ...

  2. django url 反响解析,视图

    1. 内容回顾 1. 模板语言(字符串替换) 1. 母版和继承 1. 什么时候用母版? html页面有重复的代码,把它们提取出来放到一个单独的html文件. (比如:导航条和左侧菜单) 2. 子页面如 ...

  3. Native App自动化测试及Appium框架介绍

    一  自动化工具简介 1 Appium : 开源,跨平台的自动化测试工具,用于测试Native(原生)和Hybrid(混合)应用,支持IOS/Android/FirefoxOS 平台. 2  环境 : ...

  4. linux服务基础之DNS正反向解析、主从同步、子域授权及视图

    关键词: 正向解析 反向解析 主从复制 自域授权 视图 一.DNS基本原理 1.1 什么是DNS?BIND又是什么? DNS:Domain Name Service,它是一个基于应用层的协议,是C/S ...

  5. 论文笔记:Auto-DeepLab: Hierarchical Neural Architecture Search for Semantic Image Segmentation

    Auto-DeepLab: Hierarchical Neural Architecture Search for Semantic Image Segmentation2019-03-18 14:4 ...

  6. 优雅的使用windows

    1. 快捷键 win+数字键:打开任务栏对应位置的程序 eg:快捷打开程序,重复该组合键有两个效果,如果只打开了一个窗口,再次按下组合键即可最小化,如果打开了多个窗口,则可以在同一程序的多个窗口中切换 ...

  7. Java 学习笔记- classpath classpath*

    转自:https://blog.csdn.net/javaloveiphone/article/details/51994268 1.src不是classpath, WEB-INF/classes,l ...

  8. 近视BFC

    首先按照常规解释一下名词,BFC(Block formatting context)直译为"块级格式化上下文".一个独立的渲染区域,只有Block-level box参与, 它规定 ...

  9. 北京AI外包团队 祝大家2019事业有事,大吉大利!

    未来已来,以人工智能为核心的科技力量,在重新塑造着我们生活的环境.这种重新塑造的现象如此之明显,力量如此强大,以至于越来越多的人在讨论,我们面临着新一轮的工业革命.而且现在我们面临的这次新的科技力量, ...

  10. git\CentOS6.5中gitlab安装教程

    一.Git 起源: Git是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目. Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本 ...