• Django知识总结(二)


    模型(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>
    									
  • 相关阅读:
    this 关键字
    Win10 删除“此电脑-文件夹”中的七个快捷方式
    ESLint 配置(三)Vue 项目
    ESLint 配置(二)Standard 和 Prettier
    ESLint 配置(一)基础配置
    简易FTP
    选课系统
    ATM+购物车
    ATM+购物车导图
    函数作业
  • 原文地址:https://www.cnblogs.com/ArrozZhu/p/8463861.html
Copyright © 2020-2023  润新知