一、首先需要了解的知识点是:
1、出于对效率和安全的考虑,django管理静态文件的功能仅限于在开发阶段的debug模式下使用,且需要在配置文件的INSTALLED_APPS中加入django.contrib.staticfiles(django工程创建后默认已经安装),网站正式部署上线后,静态文件是由Nginx等服务器管理。
二、接下来看下如何配置和引入静态文件
先把工程的目录结构展示出来,方便后文叙述
相关配置:
1、首先确保在配置文件的INSTALLED_APPS中加入了 django.contrib.staticfiles(默认已加入)
2、在配置文件中配置STATIC_URL,如:
STATIC_URL="/st/" # STATIC_URL的作用是用于拼接静态文件的存储路径。
3、在配置文件中配置STATICFILES_DIRS为静态静态文件的存储路径,比如:
STATICFILES_DIRS = [ os.path.join(BASE_DIR, "static") # 即静态文件存放在 BASE_DIR/static 下(和manage.py同级目录下),注意BASE_DIR指django工程的绝对路径 ]
配置完成之后就可以在模板中导入静态文件了
引入静态文件:
1、在模板文件中导入static模板标签,即在模板文件的开头处写上:{% load static %}
说明:static模板标签(即{% static "url" %}标签)并不是django内置的模板标签,而是属于自定义模板标签,所以我们不能直接使用,需要先导入该模板标签才行。
那么这个标签在哪里定义的呢?如果是pycharm,直接在{% load static %}中,把光标放在static上,按ctr+b定位到定义处,如下图:
根据注释,我们可以看出这个模板标签的作用就是传递一个静态文件的相对路径(即形参path),返回该静态文件的绝对路径。
2、使用{% static "url.."%}标签引入静态文件
第1步中我们已经导入了static模板标签,也了解了它的作用,下面就可以使用它引入静态文件了。先给个例子,方便解释,比如我们需要在模板中引入/static/css/下的bootstrap.css,那么就应该这么写:
<link rel="stylesheet" href="{% static 'css/bootstrap.css' %}">
至于为什么路径中的/static/没写在static标签处,我们等下再解释。
结合static函数的源码(即static标签定义),上面link标签中的static模板标签的含义就是,把bootstrap.css的相对路径'css/bootstrap.css'传给了static函数的path形参,所以它应该给我们返回一个该静态文件的绝对路径。由于我们在上文配置中配置了STATIC_URL="/st/",所以在浏览器端,查看该模板对应的HTML源码,可以发现django把上面这个标签渲染出来的结果是:
<link rel="stylesheet" href="/st/css/bootstrap.css">
"/st/css/bootstrap.css"就是static标签返回的绝对路径,那么为什么前面多个/st/?这是我们留下的第二个疑问,往后读就能找到答案。
现在解释上面留下的第一个疑问,为什么路径中的/static/没写在static标签处?这个又涉及到一个配置:
关于这个配置,不做深入探讨,我们只需要简单了解他的作用即可,具体信息考参考官网(https://docs.djangoproject.com/en/2.2/ref/settings/#std:setting-STATICFILES_FINDERS)
官网给出的说明就是,django在查找静态文件的时候,首先会在STATICFILES_DIRS指定的路径中寻找,找不到就会在各个app下的static文件夹下面找,由于我们在配置文件中已经指定了static文件夹,也就是说已经告诉了django,首先去static文件夹中找指定的静态文件,所以上面的static标签就会自动去static文件夹中去找css下的bootstrap.css这个静态文件,所以就没必要再把/static/写上了,否则就成了告诉django去static文件夹下的static/css/找bootstrap.css,这样就会找不到了。
至此,我们已经知道了如何引入static标签,以及使用static标签引入静态文件,顺带也把STATICFILES_DIRS配置的作用说明了,还有一个模糊的地方就是STATIC_URL配置是个什么鬼,为什么django会把上面static标签返回的绝对路径前面加一个/st/?
要说明STATIC_URL的作用,首先要捋一捋django处理http请求的过程:浏览器发送一个http请求,django的url解析器解析url,然后匹配到相应的视图函数处理请求。再看django最终把我们上面的标签渲染成如下:
<link rel="stylesheet" href="/st/css/bootstrap.css">
那么浏览器去请求这个静态文件的时候,其完整请求路径应该是http://localhost:8000/st/css/bootstrap.css,django是如何解析这个请求路径,然后找到相应的静态文件并返回的呢?
回忆一下我们开头讲的,要在django中管理静态文件,需要安装django.contrib.staticfiles这个APP,所以猜测,django处理这个请求都是在这个APP中完成的,进入到这个APP
发现这个APP结构和我们自定义的APP差不多,猜测django处理上述静态文件路径(解析路径,路由到视图函数处理请求等)就是在urls.py中完成的,点开:
看到上图中的urlpatterns = [],是不是熟悉的感觉?
在点开截图中椭圆形框出的static函数,看干了什么
看到re_path()是不是更熟悉的感觉?其实这个APP解析url和路由到指定视图函数跟我们自定义的APP逻辑是一样的。
很简单,就是把url中的前缀/st/提取出来,作为正则表达式的匹配字符串,也就是说,浏览器发出的http:8000/st/css/bootstrap.css的请求,由于该地址前缀是/st/,所以会被这个规则匹配到,从而路由到相应的视图函数进一步处理。
这样,我们就明白了STATIC_URL配置项的作用了,就是使用{% static "url.." %}时,把STATIC_URL配置的字符串拼接到静态文件的路径上作为其前缀,以便于在django.contrib.staticfiles这个APP解析出静态文件的真正路径,然后带着这个真正路径去STATICFILES_DIRS配置的路径下找,找不到就去每个APP下的static文件夹中找。
所以说,STATIC_URL配置的字符串只是个符号,你想写啥都行(当然要守规矩)。
另外的注意事项:
在我们配置的{% static 'css/bootstrap.css' %},中,如果写成{% static '/css/bootstrap.css' %}也就是css前面有个"/",那么django就会认为这是一个绝对路径,而不会把STATIC_URL配置项加到css前面,官网:https://docs.djangoproject.com/en/2.2/topics/forms/media/#form-asset-paths 中的Paths in asset definitions条目
还有STATIC_ROOT配置,参见:https://docs.djangoproject.com/en/2.2/ref/settings/#std:setting-STATICFILES_STORAGE