django目录下的路由系统和视图函数

  一、Django路由系统(url)

  1、什么是路由系统

      路由系统的本质是URL模式以及要为该URL模式调用的视图函数之间的一个映射表即不同的url路径对应的不同的函数,该路由系统是存放在全局配置文件urls.py中,之所以叫路由系统是为了好听

  2、路由系统格式:

    urlpatterns = [url(正则表达式, views视图函数,参数,别名),]
    注释:1、正则表达式就是Python中提及到的正则表达式,匹配的是url下的路径
          2、视图函数就是url路径对应的函数
          3、参数就是需要往视图函数传递的参数,是一个字典的形式
          4、别名就是正则表达式所匹配到数据结果的别名
    eg:
       1、如图无名函数
               
     如果在路由规则中的正则表达式内既有无名分组又有通过字典形式传递给视图函数的参数,那么就相当于传递了一个位置参数,两个关键字参数,且遵循位置实参在关键字参数之前。       
       2、如图有名函数      
        django目录下的路由系统和视图函数_第1张图片        
    当路由规则中出现有名函数,那么视图函数中传递的形参名称和这个有名函数名称一样,必须叫ttt(相当于默认函数)。
          3、如图name参数:
   
         django目录下的路由系统和视图函数_第2张图片                              
        主要是和html页面中的form表单中的action路径进行交互的,之所以加了/blog是由于我做了路由重分发,如果添加别名就不能对正则表达式进行无名分组和有名分组了
  3、路由重分发(当有多个项目时可以把url对应的函数写在每个项目内,需要在全局urls内做路由重分发,相当于给每个项目分配小组长)
    1、格式
      urlpatterns = [url(正则表达式,include(分发的文件路径),]
      urlpatterns = [ url(r'^blog/', include('blog.urls')),]
      注释:该正则表达式匹配的是项目名称,include的是项目名称下写路由系统的文件,以后访问的路径需要在其端口后加项目名称。
    全局urls配置文件需要先引入一个include模块才能路由重分发(from django.conf.urls import url,include
  4、客户端向服务器端传递参数的方式:
       1、通过数据传递参数,把数据写在url上,通过?&传参
      eg: http://1277.0.0.1:8080/blog/?id=1200
         2、通过路径传递参数
        eg:http://1277.0.0.1:8080/blog/1200
       5、客户端向服务器端发送请求的方式:
     1、GET方式:
        请求数据存放在url路径里面
     2、POST方式:
        请求数据存放在post请求体里面
     3、注意:get方式请求的参数只能存放在url路径上,但是post方式请求的参数可以即可以存放在post请求体内也可以在url内。
 
二、Django视图函数(views)
  1、在http协议中会产生两个对象
     http请求:HttpRequest对象,django自动创建          
    http响应:HttpResponse对象,需要自己手动创建,其实就是导入对象下的属性(  HttpResponse类django.http.HttpResponse)  
  2、HttpRequest对象下的方法和属性   
       1、path:请求页面的全路径,不包括请求ip和端口   
       2、method:请求是使用的什么方式,post或get,得到的结果是大写的POST,GET     
       3、GET:get请求方式的请求体信息,得到的是个字典对象   
       4、POST:post请求方式的请求体信息,得到的是个字典对象    
       5、COOKIES: 包含所有cookies的标准Python字典对象;keys和values都是字符串。
  3、HttpResponse对象下的方法和属性    
    1、render():主要是做模板渲染用的      
      1、格式:render(req,"网页名称",{前端键:后端值}|locals())    
    2、redirect("路径"):主要是页面跳转用的    
    3、locals() :可以直接将函数中所有的变量传给模板    
    4、关于redirect与render的区别:
                       redirect走的是路径,页面跳转路径重新加载
                       render返回的是模板,只是返回一个页面,路径不会重新加载。
三、Template基础 (模板系统)  
    1、模板系统的组成    
      组成:HTML代码+逻辑控制代码  
    2、逻辑控制代码的组成(语法格式)    
      1、格式1:使使用一个大括号加两个百分号来渲染标签,可以渲染任意类型的html标签
        {% %}    
      2、格式2:使用两个大括号来渲染标签内的变量,可以引用任意格式的变量。   
        { {   }}     
      注释:只要带有模板语法的html都称之为模板,render方法渲染时 把后端变量嵌入到模板中,其格式为:      
       render(客户端请求体名称,"发送的html模板",{''模板的值":"传入的数据"})  
      3、逻辑控制代码的语句    
        1、万能的句点号     
           模板系统可以通过点数字的方式来索取后端数据传过来的列表和字典  
        2、{% if %} 的使用      
            1、使用{% if %} 时必须和{% endif %}连用,主要是在模板中进行判断的其语法结构和python相同,都支持if elif  else等
            2、{% if %} 标签接受and,or或者not来测试多个变量值或者否定一个给定的变量       
            3、{% if %} 标签不允许同一标签里同时出现and和or,否则逻辑容易产生歧义,例如下面的标签是不合法的:                      eg: {% if obj1 and obj2 or obj3 %}    
          3、{% for %}的使用     
             1、格式:{% for obj in list [ 方法 ]%}    处理的对象  {% endfor %}       
            2、具体方法:        
              1、reversed:在标签里添加reversed来反序循环列表    
            3、{% for %}标签可以嵌套:     
              1、格式:
             {% for country in countries %}

{ {  country }}

               {% for city in country.city_list %}             
               
  • { { city }}
  •                {% endfor %}   
                 {% endfor %}       
                  2、具体的嵌套对象:         
                     1、forloop.counter表示循环的次数,它从1开始计数,第一次循环设为1    
                     2、forloop.counter0 类似于forloop.counter,但它是从0开始计数,第一次循环设为0    
                     3,forloop.revcounter        
                      4,forloop.revcounter0          
                      5,forloop.first当第一次循环时值为True,在特别情况下很有用:               
              4、empty的用法        
                  { {li }}        
                   { {% for i in list %}           
                    
  • { { forloop.counter0 }}----{ { i }}
  •         
                  {% empty %}           
                    
  • this is empty!
  •         
                  {% endfor %}          
              注释:富有魔力的forloop变量只能在循环中得到,当模板解析器到达{% endfor %}时forloop就消失了,当用for循环一个list时,如果该list 为空那么就会走empty下面的语法      
              5、使用{% for %}时必须和{% endfor %}连用,基本语法和python一样    
          4、filter过滤器的使用方式      
            1、语法格式:{ {obj|filter:param}}    obj为要操作的对象,filter为具体的操作方法,param为要做的值
              filter所指代的具体操作方法:
              1、add : 给obj变量加上相应的值,主要用于数字的相加    
              2、 addslashes : 给obj变量中的引号前加上斜线         
               3、 capfirst : obj首字母大写,主要是对字符串进行设置   
               4、 cut : 从obj字符串中移除指定的字符 比如说是移除obj中的空格         
                 eg:#value3='he llo wo r ld'   { { value3|cut:' ' }}
        
               5、 date : 格式化日期字符串  
               eg:#value4=datetime.datetime.now()
                {
           { value4|date:'Y-m-d' }}   以年-月-日的方式访问
    
               6、 default : 如果值是False,就替换成设置的默认值,否则就是用本来的值     
               eg:#value5=[ ]      { { value5|default:'空的' }}  
                7、 default_if_none: 如果值是None,就替换成设置的默认值,否则就使用本来的值   
             8、truncatechars  按照字符串的个数截断数据,截断的数据按照省略号显示 
                 eg:{ { i|truncatechars:3}}                
             9、truncatewords 按照单词的个数截断数据,截断的数据按照省略号显示
              eg:{ { i|truncatewords:4}}   
         5、{% url %}:  引用路由配置的地址 (别名的使用)
               
         6、with重新取名,就是说后端传到前端的数据名字太长了就可以用with重新给他定义一个名称     
          {% with total=fhjsaldfhjsdfhlasdfhljsdal %} { { total }} {% endwith %}   
         7、禁止模板渲染:verbatim 
          {% verbatim %}
             { { hello }}  
          {% endverbatim %}
        8、自定义filter和simple_tag
          1、检测settings配置文件的INSTALLED_APPS是否有自己的项目应用的文件名
          2、在app应用中创建templatetags模块包(必须这样创建且模块名称不能改变)
          3、创建任意 .py 文件,如:my_tags.py
         django目录下的路由系统和视图函数_第3张图片django目录下的路由系统和视图函数_第4张图片
          4、在使用自定义simple_tag和filter的html文件中导入之前创建的 my_tags.py :{% load my_tags %}    
          5、simple_tag和filter的区别
            1、调用方式不同:
              filter是通过{ {}}的方式来调用的,比如{ { num|filter_multi:2 }}
              simple_tag是通过{%%}的方式来调用的,比如{% simple_tag_multi num 5 6%}
            2、所传递的值得个数不同
              无论是自定义的filter还是模板自带的filter只能传递一个值到模板中,也就是说":"后面最多只能有一个值
              而simple_tag呢,后端自定义多少个值,前端就能接收多少个值。
            3、filter可以在if等语句后使用,而simple_tag不可以
              
        9、extend模板继承
          1、首先需要了解后台管理布局(主要是通过position:fixed、overflow=auto的方式对布局进行定位)
          2、模板继承步骤
            1、先在templates中创建好一个模板(母版)取名为base.html,以供子模板继承
            2、在需要继承模板的子模板中添加上{% extends "母版名称" %}即{% extends "base.html" %}之后子模板就继承了母版的全部代码
            3、如果子模板需要替换母版上的代码内容需要提前在母版需要替换的部分创建好盒子
              格式:{% block x % } y {% endblock %}    其中x代表盒子的名称,必须与后端替换的盒子名称一样,y代表需要替换的内容
             4、在子模板中创建母版内一样的盒子,然后在其里面写入你想要替换的代码就可以了
               格式:{% block x % } y {% endblock %}   其中x代表的是盒子的名称与前端母版盒子名称一样,y代表的是替换后的内容
           5、在子模板中可以通过 { { block.super }}这个标签来获取到母版中盒子的内容
             格式:{% block x % }  { { block.super }} y {% endblock %}   { { block.super }}代表获取到母版盒子内的内容,y代表需要添加的内容,母版中盒子越多在子模板中可更改性就越强
    四、Models数据库
      1、  django默认支持sqlite,mysql, oracle,postgresql数据库,但是在测试环境默认选择使用的是sqlite数据库  
      2、orm对象映射关系         
         1、如图所示:    
             
         注释:类实例化对象一次就相当于是向表中添加一条记录。  
      3、设置数据库链接(setting中设置)    
        DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql',
                 'NAME': 'books', #你的数据库名称       
                 'USER': 'root', #你的数据库用户名      
                 'PASSWORD': '', #你的数据库密码     
                  'HOST': '', #你的数据库主机,留空默认为localhost     
                  'PORT': '3306', #你的数据库端口 } } 
         注释:由于django对python3不支持mysqldb的搜素引擎,需先下载pymysql第三方模块,然后在django程序中导入该模块引用后正常连接
            
      4、在models中设计数据库表(就是设计表字段) 
         1、设计表字段方式  
             
        注释:程序的models.py文件中需先引入一个模块(from django.db import models),然后才能通过类来继承该模块从而设计表字段 
         2、字段类型参数
           1、CharField(max_length=x) :字符串字段,用于较短的字符串,x指代的是字符串的长度
           2、IntegerField():用于保存一个整数
           3、DecimalField(max_digits=x,decimal_places=y)   :用于保存一个浮点数,且必须要有两个参数,x代表的是总位数,y代表的是小数点后面的位数
           4、AutoField():添加一条记录时会自增,一般应用于主键(my_id=models.AutoField(primary_key=True)----主键自增)
           5、DateField()  :存放日期专门用的(日期格式为x-y-z)
           6、TextField() :存放一个容量很大的文本字段
           7、EmailField() :个带有检查Email合法性的 CharField,不接受 maxlength 参数
           8、ImageField()  :存放图片
      5、在数据库中创建表(将设计好的表进行创建,在终端上运行命令)   
               
          只要运行完第一条命令就会在自己创建项目下的migrations文件夹下产生一条rom表。    
          只要运行完第二条命令就会吧rom表中的对应信息在数据库中创建出来。
      6、数据库表记录的增删改查    
          1、向数据库插入一条记录   
            方式1:通过表名.object.create(表字段=前端数据,表字段=前端数据)的方式插入记录
     
                
            方式2:通过类属性赋值然后实例化产生一个对象,最后save的方式来插入记录
            
           方式3:批量插入数据
                django目录下的路由系统和视图函数_第5张图片

     

     

          2、向数据库查询记录 
            方式1:单表查询
              通过all()查询表中所有的记录,得到的是个对象列表   
                 
              通过get()查询表中某一条记录,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。
               
                  通过filter()过滤的方式来查询 特定的记录,返回的结果是个列表对象
                  
              由于返回的是个对象列表,可以通过.属性的方式来调用对象下的属性值
                 
              也可以通过在models.py的类中添加__str__的方式来直接打印属性值
                  django目录下的路由系统和视图函数_第6张图片
            其他查询方式:下面的方法都是对查询的结果再进行处理     
           values(*field): 返回一个ValueQuerySet对象,以字典序列的形式返回。
           exclude(**kwargs): 它包含了与所给筛选条件不匹配的对象,取反的意思  
           order_by(*field): 对查询结果排序     
           reverse(): 对查询结果反向排序       
           distinct(): 从返回结果中剔除重复纪录          
           values_list(*field): 它返回的是一个元组序列。      
           count(): 返回数据库中匹配查询(QuerySet)的对象数量。         
           first(): 返回第一条记录           
           last(): 返回最后一条记录         
           exists(): 如果QuerySet包含数据,就返回True,否则返回False,只查找到第一条数据就返回。
           iterator():遍历查询数据库数据
     
          补充:django 数据库的特点  
              1、django 数据库的惰性机制  --.all()或者.filter()等都只是返回了一个QuerySet(查询结果集对象),它并不会马上执行sql,而是当调用QuerySet的时候才执行。
              2、返回的QuerySet是个集合对象,可以对该对象进行可迭代查询,也可以对其进行切片操作
              3、由于惰性机制的原因,django数据库会有一个cache缓存机制,同一时间内发送两条相同的sql命令,第一条命令会从数据库中获取数据然后缓存到cache中,第二条命令就会在cache中获取数据
              4、当只是需要判定一个数据是否存在时就可以用exists()这个属性进行判定,当查询的数据过大时为了防止数据库cache撑爆,可以在查询条件的后面添加iterator()迭代属性来迭代查询。
              5、 queryset的cache是用于减少程序对数据库的查询,在通常的使用下会保证只有在需要的时候才会查询数据库。 使用exists()和iterator()方法可以优化程序对内存的使用。不过,由于它们并不会生成queryset cache,可能会造成额外的数据库查询。
                  
            方式2:一对一查询之正反向查询
                1、正向查询格式:
                  外键表名称.objects.filter(过滤条件).first().外键字段名称.非外键表字段()
                2、反向查询格式:
                  非外键表名称.objects.filter(过滤条件).last().外键表名.外键字段名()
                

             方式3:一对多查询之正反向查询(通过x_set的方式就可以实现反向查询,x指代的是外键名称)

              1、正向查询:

                外键表名称.objects.filter(过滤条件).first().外键字段名称.非外键表字段()

              2、反向查询:

                非外键表名称.objects.filter(过滤条件).last().外键表名__set.外键字段名()

               

                 补充:反向查询得到的是个集合对象,而正向查询得到的是个对象。

          了不起的双下划线之单表查询  

          eg:表名.objects.filter(id__lt=10, id__gt=1)         获取id大于1 且 小于10的值

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

            表名.objects.exclude(id__in=[11, 22, 33])          获取id不在列表内的数据,而not in是与之相反

            表名.objects.filter(name__contains="x")             获取包含x字段的数据,

            表名.objects.filter(name__icontains="ven")      获取不区分大小写的数据

              表名.objects.filter(id__range=[x, y])              获取id在x到y范围内的数据

            范围bettwen and 、 startswith、istartswith、endswith、 iendswith,

          了不起的双下划线(__)之多表条件关联查询

            正向查找(条件)之一对多     

          格式:外键表名.objects.filter(过滤条件).values("外键名称__非外键字段名") 

          正向查找(条件)之多对多

          格式:外键表名.objects.filter(过滤条件).values("外键名称__非外键字段名")

         反向查找(条件)

         反向查找之一对多

          格式:非外键表名.objects.filter(外键表名__外键字段="外键字段值").values("非外键字段名")                                   

         反向查找之多对多:

          格式:非外键表名.objects.filter(外键表名__外键字段="外键字段值").values("非外键字段名")

          总结: 正向查找是先查表,查到的是个列表对象,然后再再连表,反向查找是先连表,连到的是个列表对象,然后再查表,查表是既可以查自己表中字段也可以查对端表中字段

         3、向数据库中删除记录    
            直接删除(django默认支持级联删除,意思就是说只要删除该记录,该记录对应的外键关系就会一并删除) 
               
          注释:表名.object.filter(过滤条件).具体操作,其中filter内写的是你的过滤条件,id1是表字段,id2是前端模板传递过来的过滤条件值,过滤得到的结果是个列表,后面可以跟筛选条件([索引值]、first()、last()、delete())来进行具体操作 
         4、向数据库更新一条数据  
          方式1:通过表名.filter(过滤条件).updae(表字段=值,表字段=值)的方式更新一条记录或记录内的某行内容
          django目录下的路由系统和视图函数_第7张图片  
          方式2:通过save()的方式来更新一条记录内的某行内容
          
          注释:表名.filter(过滤条件).updae(表字段=值,表字段=值),其中过滤条件可以有多个用逗号隔开,格式为(表字段=值,表字段=值),过滤结果也是一个列表,可以通过筛选条件筛选出自己想要的某条记录然后对其进行更新。    
          5、在settings中添加配置记录数据库操作     
           LOGGING = { 'version': 1,     
                  'disable_existing_loggers': False,           
                     'handlers': { 'console':{ 'level':'DEBUG',       
                    'class':'logging.StreamHandler', }, },        
                 'loggers': { 'django.db.backends': {          
                 'handlers': ['console'],            
                 'propagate': True,            
                  'level':'DEBUG', }, } }      
          注释:只要在settings配置文件的任意位置条件上这条记录后,数据库的所有操作都会被打印出来
     
        7、聚合查询和分组查询

          1、聚合查询 (aggregate),返回的是个字典形式的值

            1、首先导入相应模板:from django.db.models import Avg,Min,Sum,Max

            2、格式:表名称.objects.[filter(过滤条件)].aggregate([x=]Avg('字段名'))    结果为: {x:值}

              注释:x指代的是个得到的结果的key键的名称,如果不填写就自动写字段名作为key名称

            3、格式:表名称.objects.filter(过滤条件).aggregate([x=]Avg('字段名1'),([x=]Min('字段名2')([x=]Max('字段名3'))

              注释:如果想求多个值就可以用逗号隔开,得到的结果是个字典形式的集合,过滤条件既可以是正向查找也可以是反向查找,还可以

              ge:

              

           2、分组查询( annotate())
            1、首先导入相应模板:from django.db.models import Avg,Min,Sum,Max
            2、格式:表名称.objects.[filter(过滤条件)].values(过滤条件).annotate(([x=]Avg('字段名')

              注释:x指代的是个得到的结果的key键的名称,如果不填写就自动写字段名作为key名称

            3、格式:表名称.objects.[filter(过滤条件)].values(过滤条件).aggregate(([x=]Avg('字段名1'),([x=]Min('字段名2'),)

              注释:如果想求多个值就可以用逗号隔开,得到的结果是个字典形式的集合,过滤条件既可以是正向查找也可以是反向查找

              ge:

              django目录下的路由系统和视图函数_第8张图片

          8、F查询和Q查询

            1、导入相应的模块:from django.db.models import F,Q

            2、F查询主要是更新字段中的数据用:

              格式:表名称.object.[filter(过滤条件)].update(表字段名=F("表字段名")+值)

              注释:主要是对表字段中的数字进行操作的

              eg:

              

            3、Q查询主要是应对多个条件的查询,分别用& | ~ 操作符来作为多个条件之间的链接介质

                格式: 表名.objects.filter(Q(条件1) 操作符 Q(条件2) 操作符 Q(条件3),Q(条件4),条件5
              注释:&和|可让多个Q查询合并成一个Q查询,其中&表示且而|表示或,~表示取反,在所有的Q查询末尾可以直接跟查询条件,但是不能放在Q查询之前。
              eg:
              django目录下的路由系统和视图函数_第9张图片
        9、创建外键方法(一对多记录,且外键必须建立在多的那张表上,比如说一个出版署出版多本书,外键就建立在多的那张表上)
          1、方式1:在建表的时候就已经创建好外键对应关系,插入记录时就可以直接写对端主键的值
            利用ForeignKey(需要关联的表名)方法来创建外键,注意在book类中创建的publish对象默认会在表中变成publish_id形式的字段
            django目录下的路由系统和视图函数_第10张图片

          2、方式2:建表时没有创建外键对应关系,插入记录的时候创建外键对应关系,即写对端对应的对象

            1、需要先获取被绑定的对象,也就是说创建的外键需要绑定那个对象

            2、然后在需要绑定外键的记录中将类中对应创建外键对象的值改为获取的对象

             django目录下的路由系统和视图函数_第11张图片

        10、创建外键方法(多对多记录,第三张表绑定关系)

          方式1:在建表的时候就已经创建好外键对应关系,因为是第三张表绑定关系,所以可以在任意第一张和第二张表中添加对应关系

              通过ManyToManyField(第二张表名称)的方式来创建,

                 

              django自己创建的第三张表,三个字段分别为第三张表主键,第一张表主键,第二张表主键

              

             通过add(第一张表记录1,第一张表记录2...)的方式向第三张表中添加字段

              

             注释:首先需要得到第一张表中表多对多的记录对象,然后得到第二张表中多对多的记录对象,最后通过add的方式将两张表多对多记录添加到第三张表中(注意在那个类中添加多对多对象,就用那个表记录对象 添加多对多记录)

             也可以通过添加列表的方式添加到第三张表中

             

          方式2:在建表的时候没有创建外键对象,需要自己创建第三张表添加多对多的外键

              每个字段中都添加一对多的对应关系,然后就可以django中看见第三张表就可以对其进行具体的操作了。

              通过添加具体的id的方式来创建两个字段之间多对多的关系。

              

     

        11、解除外键方法

          1、方式1:正向删除(通过clear()的方式来解除外键关系,以及通过remover(对象)的方式来删除特定外键)

             django目录下的路由系统和视图函数_第12张图片

            注释:先写出需要删除外键关系的表记录,然后再根据外键绑定对象来删除相应 的对应关系

          2、方式2:反向删除()

           

            注释:先写出非外键关系的表记录,然后根据book_set反向查找从而删除相应的对应关系

     五、django的settings配置文件
        1、添加静态文件(每个独立的项目都应该有相应的静态文件)     
           django目录下的路由系统和视图函数_第13张图片  
          注释:appbook指的是你的项目文件名,static指的是项目下存放的静态文件的文件夹名,其余不变  
        2、网页引入静态文件方式    
          1 、将所有静态文件放到一个static的文件夹中,该文件夹需要手动创建(叫什么名字无所谓,但是便于区分就叫static)
        
           2 、将static文件夹放到应用下,最好是一个项目对应一个static的文件夹
        
           3 、在setting里面设置引入静态文件的方式     
             STATIC_URL = '/static/'      静态文件的路径别名,就是前段引入静态文件时的名称

                  STATIC_ROOT=(os.path.join(BASE_DIR,"appBook/static"),  )    添加上静态文件的路径,django才能找到
            
            4、 在模板首行加上{% load staticfiles %}    相当于读取静态文件配置
        
           5 、 引入文件: {% static 具体路径 %}     相当于引入静态文件    
     
            
          注释:static指的是静态文件路径别名,后面写的是需要引入的文件    
          6、需要注意的事项:         
          注意1:为了后端的更改不会影响前端的引入,避免造成前端大量修改,在前段添加的都是引用名

         STATIC_URL = '/static/' #引用名      STATICFILES_DIRS = (os.path.join(BASE_DIR,"statics") ) #实际名 ,即实际文件夹的名字       #django对引用名和实际名进行映射,引用时,只能按照引用名来,不能按实际名去找       #       #------error----不能直接用,必须用STATIC_URL = '/static/'这个别名引用       #       注意2:statics文件夹写在不同的app下,静态文件的调用,意思就是说当settings需要引入多个静态文件时,需要在每个静态文件前加入一个元素。      STATIC_URL = '/static/'      STATICFILES_DIRS=(('hello',os.path.join(BASE_DIR,"app01","statics")), )      #    注意3:要想在网页模板中引入静态文件就必须先读取静态文件,然后才能引用,且是通过别名引用。      STATIC_URL = '/static/'    
            {% load staticfiles %}      #

     

        

        

     

     

     

     

        

     

     

    转载于:https://www.cnblogs.com/xuanan/p/7411083.html

    你可能感兴趣的:(python)