拾 ● 模型(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. Java之冒泡算法实现

    算法说明:给一列数组排序,当前一个元素大于后一个元素则交换这两个元素的顺序,直到最大的数字移动到最右边,以剩下n-1元素组成的数组当做最新数组,重复交换过程,直到这个数组全部处理完毕.传的参数一个是数 ...

  2. 中间件详解,Django复习

    day74 2018-05-21 课程安排周一: 中间件 auth模块+分析BBS项目需求(小组讨论把表结构设计出来) 1. 今日内容 中间件:http://www.cnblogs.com/liwen ...

  3. Arthas:线上问题排查工具

    安装 下载 java -jar arthas-boot.jar 查看版本: D:\Program Files\arthas $ java -jar arthas-boot.jar -version [ ...

  4. ios开启双重认证之填坑式教学

    2019.03.01.阳光明媚(不,,,有些雾霾..) 本来打算发布一个新版本app,修复一些小小bug, 然而,打包出错了,,错误是显示账号无连接.. 顿时慌出了天际,,以为是账号的证书问题,,最烦 ...

  5. Visual Studio color schemes

    Vs环境主题配置 下载地址:https://studiostyl.es/ Son of Obsidian 下载:son-of-obsidian_vs2015.zip Litle monokai vst ...

  6. 《R语言入门与实践》第四章:R 的记号体系

    这一章节将如何对 R 对象中的值进行选取,R 的符号规则有两种方式进行查询: 第一种记号体系:索引查询索引语法:deck[ , ](使用中括号)其中[ , ] 为索引,其中含有两个索引参数,用 &qu ...

  7. jmeter系列-如何实现像loadrunner一样,多个并发用户先通过登录初始化,然后做并发的接口性能压测

    自动转开发后,就很少关注性能测试方面的东西,最近在帮朋友做一个性能压测,由于朋友那边的公司比较小,环境比较简单,而且是对http服务进行的压测,所以最终 选用了jmeter来实现这个压测. 如下就是我 ...

  8. python爬取某站磁力链

    不同磁力链网站网页内容都不同,需要定制 1,并发爬取 并发爬取后,好像一会就被封了 import requests from lxml import etree import re from conc ...

  9. Python字符编码与转换

          需知: .在python2默认编码是ASCII, python3里默认是unicode .unicode 分为 utf-(占4个字节),utf-(占两个字节),utf-(占1-4个字节), ...

  10. scikit_learn lasso详解

    Lasso 回归 l1 正则化 The Lasso 是估计稀疏系数的线性模型. 它在一些情况下是有用的,因为它倾向于使用具有较少参数值的情况,有效地减少给定解决方案所依赖变量的数量. 因此,Lasso ...