django学习(2)加载静态html模板网站

[toc]

新建应用,访问index

如何在 Windows 上安装 Django并创建应用 -无聊才读书 [1]

创建新的项目

django-admin.py startproject GameProject
cd GameProject

在项目目录创建templates目录,将模板网站资源(html、css、js、img)放入templates目录,确保有一个入口文件index.html。然后返回项目目录。

创建新的应用

python manage.py startapp game

修改game/views.py

from django.http import HttpResponse
from django.shortcuts import render
def index(request):
    #return HttpResponse("Hello, world. You're at the polls index.")
    return render(request,"index.html")
#返回要在网页上显示的信息

HttpResponse函数用来直接返回文本信息;
render函数专门用来加载网页模板,第一个参数位置写request参数,第二个写模板文件名。

有官方推荐的方式,和简单的方式
django官方文档[2]
有关urls的知识在下一节有介绍。

应用目录中创建urls.py文件:

vi urls.py

urls.py内容写入:

from django.urls import path
from . import views
urlpatterns = [
    path('', views.index, name='index'),

修改GameProject/urls.py文件

from django.contrib import admin
from django.urls import include, path
urlpatterns = [
    path('game/', include('game.urls')),
    path('admin/', admin.site.urls),

urlpartterns添加path('game/',include('game.urls')),
注意import include。
include的用途:

函数允许引用其他 URLconfs。 无论 Django 遇到什么 include(),它都会删除与该点匹配的 URL 的任何部分,并将剩余的字符串发送到包含的 URLconf 处进行进一步处理。[1]

当您包含其他 URL 模式时,您应该始终使用 include ()。 admin.site.urls 是唯一的例外。

修改GameProject/urls.py文件

from django.contrib import admin
from django.urls import path
from game import views
urlpatterns = [
    path('game/', views.index),
    path('admin/', admin.site.urls),

这就取消了应用目录内的二级路由,也不需要include(),直接由总路由控制url该访问视图中的哪个方法。

修改GameProject/settings.py

'DIRS'代表整个工程的模板文件目录的路径。
'APP_DIRS'表示是否启用应用内模板目录,默认状态就是使用应用目录内的templates文件夹。
如果将'DIRS'省略,则需要将网页模板文件放在应用目录下的templates目录下,当'APP_DIRS'为True可正常使用。
在本例中,这里写成DIRS:[os.path.join(BASE_DIR,"templates")],
或者DIRS: [BASE_DIR+'/templates'],
让项目知道我们自定义的工程模板文件目录的位置。两种写法的区别在于前者不需要斜杠,跨操作系统的适应性更好。

启动服务器,外网可访问,使用80端口(默认只能内部访问,使用8000端口)。需要保证当前端口未占用

python manage.py runserver 0:80

内网使用localhost,外网可以使用ip/域名网址+/game来访问刚刚配置好的静态网页,例如:http://62.234.114.108/game

通过urls访问多个模板网页

目前,通过“index/”这个Url可以访问到“game”应用中的“index.html”文件。如果想通过url访问多个html文件,就需要多个url路由。有关urls的知识在下一节有介绍。

一级路由方案

有一种可行的简单的方法如下,在工程目录的urls.py中这样写:

from django.contrib import admin
from django.urls import path
from helapp import views
urlpatterns = [
    path('admin/', admin.site.urls),
    path('index/', views.index),
    path('input/', views.input),

在应用的views.py中这样写:

from django.shortcuts import render
def index(request):
    return render(request,"index.html")
def input(request):
    return render(request,"input.html")

这样,只要index能正常访问,input在index的同目录下,那么它就也能访问。
这样偷了个懒,不需要使用“include()”也不需要使用应用里的“urls.py”。这不是官方推荐的方案,但可以用。

多级路由方案

官方建议的方案,对于多应用的大中型项目更有利。总路由把url直接传递给匹配的分路由,再由分路由指定views。这样的话,一个一级url只能对应一个应用,想在同一个应用里访问到多个网页,可以对url做多次路由。
在工程目录的urls.py中,把input的路由去掉:

urlpatterns = [
    path('admin/', admin.site.urls),
    # path('input/', include('helapp.urls')),
    path('index/', include('helapp.urls')),

"include()"的使用,使得前面匹配完成的字段抹消掉,路由目的地"helapp.urls"只会收到"index/"后面的字段。
在应用的urls.py中:

from django.urls import path
from . import views
urlpatterns = [
    path('', views.index),
    path('input', views.input),

这两个"path"就分别对应"localhost/index"和"localhost/index/input"两个url。使得调用views.py中调用不同的方法,从而返回不同的页面。
在应用的views.py中:

from django.shortcuts import render
def index(request):
    return render(request,"index.html")
def input(request):
    return render(request,"input.html")

使用django上线完整静态网站

上面的方法只能展示单独的html文件,若此文件有静态css、js、img文件的链接,因为没有写对应的路由,所以无法直接调用,网站会显示不正常。
官方给出的方法是静态资源与模板文件存放在不同的路径,通常是在应用目录下有templates和static文件夹(也可以自定义指定其他路径)。模板文件表示可以进行动态传参,而静态文件只能是模板文件的附属,只能让模板文件调用,后端不可操作其内容。

官方正常操作

欲使用静态文件目录,先打开工程同名目录下的“settings.py”,将最末尾改为如下示例:

STATIC_URL = '/static/'

之后将准备好的与html文件相匹配的css文件放入应用目录下的static目录。(实测,修改好了上面的示例后,静态文件放在工程目录下的static也可以)
要链接这个css文件,则要在html文件中设置以下代码:[2]

{% load static %}<link rel="stylesheet" type="text/css" href="{% static 'style.css' %}">

这里{% load static %}代表这里提示需要一个静态文件,{% static 'style.css' %}代表从规定的静态文件目录中找这个路径。

如果事先写好的静态网站有许多静态文件的调用,则修改会很繁琐。但如果是静态文件互相调用,则可以简单很多,比如在css文件中使用图片:

body {background: white url("images/background.gif") no-repeat;}

但如果html文件中有许多<img>图片需要用src链接,只能一个一个改。以至于我想偷个懒——

偷懒简单操作

如果把网站中的index.html文件也看作静态资源,即可用最少的修改完成完整静态网站的上线。以下是步骤:

  • app目录下创建static文件夹,将现有的整个网站模板放入。注意,刚才的templates是在工程总目录下创建。
  • 打开工程同名目录下的“settings.py”,将最末尾改为如下示例:
  • STATIC_URL = '/static/'
    
  • 修改templates目录下的index.html文件,可使用链接、跳转等形式。跳转的方法网上有很多,这里举出几个例子:
  • <head>  {% load static %}
        <meta http-equiv="refresh" content="0;url= {% static 'index.html' %} ">
    </head>  <!-- meta跳转 -->
    
    <script language="javascript" type="text/javascript">
    {% load static %} window.location.href='{% static 'index.html' %}';
    </script><!-- script跳转 -->
    
    {% load static %}  <!-- 链接跳转 -->
    <a href="{% static 'index.html' %}">跳转连接</a>
    

    如此,应该能正常显示整个模板网站了。其实这是基于static目录可以直接访问。但实际使用不推荐这样做,因为首先静态html无法传递动态参数,其次使网站资源都可以通过url无脑地进行静态访问并不是一种很好的习惯。

    通过请求views加载静态资源

    如果不想一个一个修改网页内的url,也不想纯静态访问,其实可以让后端处理每个url访问请求。虽然不同的url很多,但是格式都有规律。使用正则表达式解析url, 可以找到需要的静态文件并返回。正则表达式的详细使用见下一节
    在urls文件中,导入re_path,并使用正则匹配变量,并交给views的方法:

    from django.urls import path, re_path
    from . import views
    urlpatterns = [  # 第一个参数是路径,第二个参数是视图,第三个是参数
        re_path(r'(?P<fl_name>\w+)\.html$', views.pt_htm),
        re_path(r'(?P<kind>\w+)/(?P<fl_name>.*)\.(?P<fmt_name>\w+)$', views.pt_stc),
        path('', views.index),
    

    在views中这样写(注意导包):

    from django.shortcuts import render
    from django.http import HttpResponse
    import os
    from hello import settings
    # Create your views here.
    def index(request):
        return render(request, "index.html")
    def pt_htm(request, fl_name):
        return render(request, fl_name + '.html')
    def pt_stc(request, kind, fl_name, fmt_name):
        path = os.path.join(settings.BASE_DIR,
        "helapp/static/" + kind + "/{}".format(fl_name + '.' + fmt_name))  # 路径
        with open(path, 'rb') as s:
            data = s.read()
        if fmt_name == 'jpg':
            return HttpResponse(data, content_type="image/jpg")
        elif fmt_name == 'png':
            return HttpResponse(data, content_type="image/png")
        # elif fmt_name == 'css':
        #   return HttpResponse('', content_type="text/css")
        elif fmt_name == 'js':
            return HttpResponse(data, content_type="application/x-javascript")
    

    注意,关于css的请求我注释掉了,因为我找的这个网站模板还使用了静态资源字体文件,调用字体文件时有url参数,不好解析,所以css的调用还是在html中用{%load static%}为好(详情见前文)。
    在static/css中新建一个index.css文件,用于收集其他css文件。只要在这里引用了其他所有的css文件,网页只要链接这一个css就可以了。index.css内写法举例如下:

    @import "style.css";
    @import "style1.css";
    

    在每个html文件中合适的位置加入:

    {%load static%}
    <link href="{%static 'css/index.css'%}" rel="stylesheet" type="text/css" media="all" />
    

    应该是要删掉其他的css link的,因为views里没有对应的处理那些url的代码,不删会报错。如果不想费事在html里一个一个删的话,把上面views注释的部分解注释,让其返回的是空字符串而不是data,浏览器就不会报错了。这样做也不会影响到load static的css。