模型(M)

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

----一张表

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

映射关系

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

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

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

 

开始使用DjangoORM

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

13API查询:allfilterget valuesvalues_listdistinctorder_by ,reverse , excludecountfirstlastexists(判断是否存在)

基于双下划线查询

 

● ※ 单表查询详解

使用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()获取Buildingnumber字段列表
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等于112233的数据

(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的子查询)

基于双下划线查询(对应sqljoin查询)

 

● ※ 跨表查询详解

'''
# 出版社与书是一对多的关系
# 作者与书是多对多的关系
# 作者与作者详细信息是一对一的关系
'''

 

# (下面是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.authorsnid=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()

 


											# AuthorBook是多对多的关系, 因此关联字段也可以建立于此:
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

 

 

查询的地址在烟台并且email789的作者的名字(正向查询,按字段)
   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, ---------  基于双下划线查询(对应sqljoin查询)
###基于双下划线的查询:正向查询,按字段;反向查询,按表名###

 


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

 


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

 


											 #  查询email456开头的作者出版过的所有书籍名称以及出版社名称
 # 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}}

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

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

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

{{ value|length }}

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

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

{{ value|filesizeformat }}

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

4date

value=datetime.datetime.now()

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

5slice:切片

如果 value="hello world"

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

6truncatechars: 截断

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

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

value="Arroz is a boy"

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

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

7safe

为了安全, 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 %}

1for标签(注:循环序号可以通过{{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 %}

 

2for....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_tagfilterhtml文件中导入之前创建的 my_tags.py

{% load my_tags %}

 

5、使用filtersimple_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都是静态文件

分两种情况:

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

部署到nginxweb服务器时引入静态文件

 

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

# 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

 

部署到nginxweb服务器时引入静态文件

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

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

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

 

● ※ URIURL的区别

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配置

staticmedia的区别:

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

 

 

 

拾叁 ● cookiesession

一、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" : {id1, name"alex"},

"zxcvbnmzxcvbnm" : {id1, name"eric"}

}

 

※ {id1,nam"alex"account1000000000 }这些数据会被加密, 例如:

 

三、session依赖于cookie

 

● ※ Djangosessioncookie的实现原理

版本一:

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

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

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

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

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

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

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

版本二:

浏览器向服务器发送请求, 请求头包括url地址;
如果请求方式是POST, 服务器生成session数据, 例如:  {idasdfg, name"alex", account1000000000 },由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>
									

 

 posted on 2018-02-01 13:15  Arroz  阅读(355)  评论(0编辑  收藏  举报