Django基础---Web框架、URL路由、视图函数、模板系统

Django基础

Django基础—Web框架

MVC和MTV框架

MVC

把Web应用分为模型(M)、视图(V)、控制器(C)三层,他们之间以一种插件式的,松耦合的方式联系在一起。模型负责业务对象与数据库的映射(ORM),视图负责与用户的交互(页面),控制器接收用户的输入调用模型和视图完成用户的请求。

image-20201110110214121

MTV

Django的MTV模式本质上和MVC是一样的,也是为了各组件间保持松耦合关系,只是定义上有些许不同,Django的MTV分别是值:

  • M 代表模型(Model): 负责业务对象和数据库的关系映射(ORM)。
  • T 代表模板 (Template):负责如何把页面展示给用户(html)。
  • V 代表视图(View): 负责业务逻辑,并在适当时候调用Model和Template。

除了以上三层之外,还需要一个URL分发器,它的作用是将一个个URL的页面请求分发给不同的View处理,View再调用相应的Model和Template,MTV的响应模式如下所示:

img

一般是用户通过浏览器向我们的服务器发起一个请求(request),这个请求回去访问视图函数,(如果不涉及到数据调用,那么这个时候视图函数返回一个模板也就是一个网页给用户),视图函数调用模型,模型去数据库查找数据,然后逐级返回,视图函数把返回的数据填充到模板中空格中,最后返回网页给用户。

Django下载与安装

  1. 下载
pip3 install django==1.11.9
  1. 创建一个django project
1. 创建项目
	django_projects>django-admin startproject first_project 
2. 启动
	python manage.py runserver 127.0.0.1:8080
C:\Users\libo>d:

D:\>cd django_projects

D:\django_projects>dir
 驱动器 D 中的卷是 DATADRIVE1
 卷的序列号是 C0DB-27ED

 D:\django_projects 的目录

2020/11/10  11:16    <DIR>          .
2020/11/10  11:16    <DIR>          ..
               0 个文件              0 字节
               2 个目录 967,474,065,408 可用字节

D:\django_projects>django-admin startproject first_project

D:\django_projects>dir
 驱动器 D 中的卷是 DATADRIVE1
 卷的序列号是 C0DB-27ED

 D:\django_projects 的目录

2020/11/10  11:18    <DIR>          .
2020/11/10  11:18    <DIR>          ..
2020/11/10  11:18    <DIR>          first_project
               0 个文件              0 字节
               3 个目录 967,474,053,120 可用字节

D:\django_projects>cd first_project

D:\django_projects\first_project>dir
 驱动器 D 中的卷是 DATADRIVE1
 卷的序列号是 C0DB-27ED

 D:\django_projects\first_project 的目录

2020/11/10  11:18    <DIR>          .
2020/11/10  11:18    <DIR>          ..
2020/11/10  11:18    <DIR>          first_project
2020/11/10  11:18               833 manage.py
               1 个文件            833 字节
               3 个目录 967,474,053,120 可用字节

D:\django_projects\first_project>python manage.py runserver 127.0.0.1:8080
Performing system checks...

System check identified no issues (0 silenced).

You have 13 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
November 10, 2020 - 11:23:03
Django version 1.11.9, using settings 'first_project.settings'
Starting development server at http://127.0.0.1:8080/
Quit the server with CTRL-BREAK.
[10/Nov/2020 11:23:32] "GET / HTTP/1.1" 200 1716
Not Found: /favicon.ico
[10/Nov/2020 11:23:32] "GET /favicon.ico HTTP/1.1" 404 1969

image-20201110112542922

  1. 创建应用
D:\django_projects\first_project>python manage.py startapp app01
在first_project下的settings里的INSTALLED_APPS例表里添加你的应用
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01',
]
  1. 在pycharm中创建django项目

image-20201110164616139

基于Django实现一个简单的示例

  1. url控制器(第一步就找它)
#找对应的函数,是哪个app里面的函数
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls), #这个先不用管,后面会学
    path('index/',views.index),
]
  1. 在templates里创建login.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
    <title>Bootstrap 101 Template</title>

    <!-- Bootstrap -->
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">

    <!-- HTML5 shim 和 Respond.js 是为了让 IE8 支持 HTML5 元素和媒体查询(media queries)功能 -->
    <!-- 警告:通过 file:// 协议(就是直接将 html 页面拖拽到浏览器中)访问页面时 Respond.js 不起作用 -->
    <!--[if lt IE 9]>
      <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/html5shiv.min.js"></script>
      <script src="https://cdn.jsdelivr.net/npm/[email protected]/dest/respond.min.js"></script>
    <![endif]-->
</head>
<body>
<h1>欢迎来到登录页面!</h1>
<form action="">
    用户名:<input type="text" name="username">
    密码:<input type="text" name="password">
    <input type="submit">
</form>

<!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js"></script>
<!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js"></script>
</body>
</html>
  1. views视图
# Create your views here.


def index(request):
    return render(request, 'login.html')
  1. 启动后,在浏览器输入localhost/index即可访问

get请求获取数据

# print(request.GET)  # <QueryDict: {'username': ['laowang'], 'password': ['123']}>
username = request.GET.get('username')
password = request.GET.get('password')
if username == 'laowang' and password == '123':
    return HttpResponse('登录成功!')
else:
    return HttpResponse('登录失败!')

post请求获取数据

先关掉一个认证机制,settings配置文件中

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    # 'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
if request.method == 'GET':
    return render(request, 'login.html')
else:
    username = request.POST.get('username')
    password = request.GET.get('password')
    if username == 'laowang' and password == '123':
        return HttpResponse('登录成功!')
    else:
        return HttpResponse('登录失败!')

写项目

1. 创建项目  first_project
2. 创建app  app01
做一个登录页面的Web项目,浏览器输入一个网址得到一个Web页面

用户: http:127.0.0.1:8000/login/
1. urls.py
    urlpatterns = [
        # url(r'^admin/', admin.site.urls),
        url(r'^index/', views.index),  # 配置路径
    ]
2. 写逻辑视图views.py
    def index(request):  # HttpRequest
        # # print(request.GET)  # <QueryDict: {'username': ['laowang'], 'password': ['123']}>
        # username = request.GET.get('username')
        # password = request.GET.get('password')
        # if username == 'laowang' and password == '123':
        #     return HttpResponse('登录成功!')
        # else:
        #     return HttpResponse('登录失败!')
        # request.method  GET POST
        if request.method == 'GET':
            return render(request, 'login.html')
        else:
            username = request.POST.get('username')
            password = request.GET.get('password')
            if username == 'laowang' and password == '123':
                return HttpResponse('登录成功!')
            else:
                return HttpResponse('登录失败!')
3. 创建html文件
	在templates文件架中创建一个login.html文件
	<!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
        <title>Bootstrap 101 Template</title>

        <!-- Bootstrap -->
        <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">

        <!-- HTML5 shim 和 Respond.js 是为了让 IE8 支持 HTML5 元素和媒体查询(media queries)功能 -->
        <!-- 警告:通过 file:// 协议(就是直接将 html 页面拖拽到浏览器中)访问页面时 Respond.js 不起作用 -->
        <!--[if lt IE 9]>
          <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/html5shiv.min.js"></script>
          <script src="https://cdn.jsdelivr.net/npm/[email protected]/dest/respond.min.js"></script>
        <![endif]-->
    </head>
    <body>
    <h1>欢迎来到登录页面!</h1>
    <form action="/index/" method="post">
        用户名:<input type="text" name="username">
        密码:<input type="text" name="password">
        <input type="submit">
    </form>

    <!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) -->
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js"></script>
    <!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 -->
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js"></script>
    </body>
    </html>

Django基础—URL路由

无名分组

# urls.py
from app01 import views

urlpatterns = [
    # url(r'^admin/', admin.site.urls),
    url(r'^index/', views.index),
    url(r'^books/(\d{4})/(\d{1,2})/', views.books),# 匹配年月份
]
# views.py
def books(request, year, month): # 接收正则匹配到的数据
    # return render(request, 'books.html')
    print(year, month)
    return HttpResponse(year+month)

有名分组

from app01 import views

urlpatterns = [
    # url(r'^admin/', admin.site.urls),
    url(r'^index/', views.index),
    # url(r'^books/(\d{4})/(\d{1,2})/', views.books),# 匹配年月份
    url(r'^books/(?P<year>\d{4})/(?P<month>\d{1,2})/', views.books),# 匹配年月份
    # {'yera':'2001', 'month':'12'}
]
# views.py
def books(request, year, month): # 接收正则匹配到的数据,名字一定要和url中的分组名一样,位置可以改变
    # return render(request, 'books.html')
    print(year, month)
    return HttpResponse(year+month)

视图函数指定默认值

# urls.py中

from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^blog/$', views.page),
    url(r'^blog/page(?P<num>[0-9]+)/$', views.page),
]

# views.py中,可以为num指定默认值

def page(request, num="1"):
    pass

url路由分发之include

# second_project/urls.py
urlpatterns = [
    # url(r'^admin/', admin.site.urls),
    url(r'^app01/', include('app01.urls')),
    url(r'^app02/', include('app02.urls')),
]
# app01/urls.py
from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    # url(r'^admin/', admin.site.urls),
    url(r'^index/', views.index),

]
# app02/urls.py
from django.conf.urls import url
from django.contrib import admin
from app02 import views

urlpatterns = [
    # url(r'^admin/', admin.site.urls),
    url(r'^home/', views.home),

]

设置首页

访问路径为域名即可
url(r'^$', views.base),

Django基础—视图函数

request对象

官方文档

请求相关的常用值

  • path_info 返回用户访问url,不包括域名

  • method 请求中使用的HTTP方法的字符串表示,全大写表示。

  • GET 包含所有HTTP GET参数的类字典对象

  • POST 包含所有HTTP POST参数的类字典对象

  • body 请求体,byte类型 request.POST的数据就是从body里面提取到的

def base(request):  # http相关请求信息---封装----HTTP Request对象
    print(request.method)
    print(request.path)
    print(request.GET)
    print(request.POST)

response对象

HttpResonse  ---  回复字符串的时候来使用
render  ---  回复一个html文件
redirect  --- 重定向

redirect重定向

from django.shortcuts import render, HttpResponse, redirect
def login(request):
    if request.method == 'GET':
        return render(request, 'login.html')
    else:
        username = request.POST.get('username')
        password = request.POST.get('password')
        if username == 'laowang' and password == '123':
            # return render(request, 'home.html')
            return redirect('/home/')
        else:
            return HttpResponse('滚犊子,快去充钱!')

def home(request):
    return render(request, 'home.html')

# urls.py
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^$', views.base),
    url(r'^login/', views.login),
    url(r'^home/', views.home),
]

重定向状态码

1)301和302的区别。

  301和302状态码都表示重定向,就是说浏览器在拿到服务器返回的这个状态码后会自动跳转到一个新的URL地址,这个地址可以从响应的Location首部中获取
  (用户看到的效果就是他输入的地址A瞬间变成了另一个地址B)——这是它们的共同点。

  他们的不同在于。301表示旧地址A的资源已经被永久地移除了(这个资源不可访问了),搜索引擎在抓取新内容的同时也将旧的网址交换为重定向之后的网址;

  302表示旧地址A的资源还在(仍然可以访问),这个重定向只是临时地从旧地址A跳转到地址B,搜索引擎会抓取新的内容而保存旧的网址。 SEO302好于301

 

2)重定向原因:
(1)网站调整(如改变网页目录结构);
(2)网页被移到一个新地址;
(3)网页扩展名改变(如应用需要把.php改成.Html或.shtml)。
        这种情况下,如果不做重定向,则用户收藏夹或搜索引擎数据库中旧地址只能让访问客户得到一个404页面错误信息,访问流量白白丧失;再者某些注册了多个域名的
    网站,也需要通过重定向让访问这些域名的用户自动跳转到主站点等。

CBV和FBV

FBV(function base views) 就是在视图里使用函数处理请求。

之前都是FBV模式写的代码,所以就不写例子了。

CBV(class base views) 就是在视图里使用类处理请求。

Python是一个面向对象的编程语言,如果只用函数来开发,有很多面向对象的优点就错失了(继承、封装、多态)。所以Django在后来加入了Class-Based-View。可以让我们用类写View。这样做的优点主要下面两种:

  1. 提高了代码的复用性,可以使用面向对象的技术,比如Mixin(多继承)
  2. 可以用不同的函数针对不同的HTTP方法处理,而不是通过很多if判断,提高代码可读性
# CBV
# views.py
from django.shortcuts import render, HttpResponse, redirect
from django.views import View
class LoginView(View):
    def dispatch(self, request, *args, **kwargs):
        print('请求来了')
        ret = super().dispatch(request, *args, **kwargs)
        print('请求处理完走了')
        return ret

    # GET 通过反射找的
    def get(self, request):
        print('get方法执行了')
        return render(request, 'login2.html')

    def post(self, request):
        username = request.POST.get('username')
        password = request.POST.get('password')
        print(username, password)
        return HttpResponse('登录成功!')
# urls.py
from app01 import views

urlpatterns = [
    url(r'^login2/', views.LoginView.as_view()),
    
]

加装饰器

# FBV
# 装饰器
def wrapper(f):
    def inner(*args, **kwargs):
        print("添加额外的功能:执行被装饰函数之前的操作")
        ret = f(*args, **kwargs)
        print("添加额外的功能:执行被装饰函数之后的操作")
        return ret
    return inner
@wrapper
def home(request):
   
    return render(request, 'home.html')


# CBV
from django.shortcuts import render, HttpResponse, redirect
from django.views import View
from django.utils.decorators import method_decorator
# 装饰器
def wrapper(f):
    def inner(*args, **kwargs):
        print("添加额外的功能:执行被装饰函数之前的操作")
        ret = f(*args, **kwargs)
        print("添加额外的功能:执行被装饰函数之后的操作")
        return ret
    return inner
@method_decorator(wrapper, name='get')  # 方式3 给只当函数加装饰器
class LoginView(View):
    # @method_decorator(wrapper)  # 方式2 给所有的方法加
    def dispatch(self, request, *args, **kwargs):
        print('请求来了')
        ret = super().dispatch(request, *args, **kwargs)
        print('请求处理完走了')
        return ret

    # GET 通过反射找的
    # @method_decorator(wrapper)  # 方式1给单独的一个方法加
    def get(self, request):
        print('get方法执行了')
        return render(request, 'login2.html')

    def post(self, request):
        username = request.POST.get('username')
        password = request.POST.get('password')
        print(username, password)
        return HttpResponse('登录成功!')

Django基础—模板系统

语法

模板渲染的官方文档

  关于模板渲染你只需要记两种特殊符号(语法):

  {
   
   { }}和 {% %}

  变量相关的用{
   
   {}},逻辑相关的用{%%}。

变量

# views.py
def home(request):
    num = 100
    name = '老王'
    name_list = ['SoberLee', 'Jony_J', 'HotDog']
    d1 = {
    
    'HotDog':'Male','陆燃':'female'}

    class Animal:
        def __init__(self):
            self.kind = 'dog'

        def eat(self):
            return 'shi'

    a = Animal()

    return render(request, 'home.html', {
    
    'num':num, 'name':name, 'namelist':name_list, 'd1':d1,'a':a})
# home.html
<body>
<h1>欢迎来到老王带你学栏目!</h1>
<p>{
    
    {
    
     num }}</p>
<p>{
    
    {
    
     name }}</p>
<p>{
    
    {
    
     namelist.2 }}</p>
<p>{
    
    {
    
     d1.HotDog }}</p>
<p>{
    
    {
    
     a.eat }}</p>
</body>

过滤器

过滤器的语法: { { value|filter_name:参数 }}

使用管道符"|"来应用过滤器。

# home.html
{
    
    #过滤器#}
{
    
    #获取数据长度#}
<p>{
    
    {
    
     namelist|length }}</p>
{
    
    #默认值,有值的话,输出值,无值输出默认值#}
<p>{
    
    {
    
     xx|default:"nothing"}}</p>
{
    
    #将值格式化为一个 “人类可读的” 文件尺寸 (例如 '13 KB', '4.1 MB', '102 bytes', 等等)。例如:1.2 MB#}
<p>{
    
    {
    
     movesize|filesizeformat}}</p>
{
    
    #切片,如果 value="hello world",还有其他可切片的数据类型  odnasodnas#}
<p>{
    
    {
    
    name|slice:"2:-1"}}</p>
{
    
    #格式化,如果 value=datetime.datetime.now()   2020-11-12 16:23:50#}
<p>{
    
    {
    
     now|date:"Y-m-d H:i:s"}}</p>
{
    
    #如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾。I love...#}
<p>{
    
    {
    
     words|truncatechars:'9' }}</p>
{
    
    #单词截断 I love you ...#}
<p>{
    
    {
    
     words|truncatewords:3}}</p>
# views.py
def home(request):
    num = 100
    name = 'niodnasodnaso'
    name_list = ['SoberLee', 'Jony_J', 'HotDog']
    d1 = {
    
    'HotDog':'Male','陆燃':'female'}

    class Animal:
        def __init__(self):
            self.kind = 'dog'

        def eat(self):
            return 'shi'

    a = Animal()

    movesize = 1231234

    now = datetime.datetime.now()

    words = 'I love you girl!'


    # return render(request, 'home.html', {'num':num, 'name':name, 'namelist':name_list, 'd1':d1,'a':a})
    return render(request, 'home.html', locals())

csrf_token认证

我们以post方式提交表单的时候,会报错,还记得我们在settings里面的中间件配置里面把一个csrf的防御机制给注销了啊,本身不应该注销的,而是应该学会怎么使用它,并且不让自己的操作被forbiden,通过这个东西就能搞定。

这个标签用于跨站请求伪造保护,

在页面的form表单里面(注意是在form表单里面)任何位置写上{% csrf_token %},这个东西模板渲染的时候替换成了,隐藏的,这个标签的值是个随机字符串,提交的时候,这个东西也被提交了,首先这个东西是我们后端渲染的时候给页面加上的,那么当你通过我给你的form表单提交数据的时候,你带着这个内容我就认识你,不带着,我就禁止你,因为后台我们django也存着这个东西,和你这个值相同的一个值,可以做对应验证是不是我给你的token,存储这个值的东西我们后面再学,你先知道一下就行了,就像一个我们后台给这个用户的一个通行证,如果你用户没有按照我给你的这个正常的页面来post提交表单数据,或者说你没有先去请求我这个登陆页面,而是直接模拟请求来提交数据,那么我就能知道,你这个请求是非法的,反爬虫或者恶意攻击我的网站,以后将中间件的时候我们在细说这个东西,但是现在你要明白怎么回事,明白为什么django会加这一套防御。

# 'django.middleware.csrf.CsrfViewMiddleware' 这条语句不要注释了
# views.py
def login(request):
    if request.method == 'GET':
        return render(request, 'login.html')
    else:
        username = request.POST.get('username')
        password = request.POST.get('password')
        if username == 'laowang' and password == '123':
            # return render(request, 'home.html')
            return redirect('/home/')
        else:
            return HttpResponse('滚犊子,快去充钱!')
       
# html页面在form表单里加上{% csrf_token %}
<form action="" method="post">
    {
    
    % csrf_token %}
    用户名:<input type="text" name="username">
    密码:<input type="text" name="password">
    <button>提交</button>
</form>

模板继承

Django模版引擎中最强大也是最复杂的部分就是模版继承了。模版继承可以让您创建一个基本的“骨架”模版,它包含您站点中的全部元素,并且可以定义能够被子模版覆盖的 blocks 。

# muban,html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
    <title>Bootstrap 101 Template</title>

    <!-- Bootstrap -->
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
    <style>
        body{
    
    
            margin: 0;
            padding: 0;
        }
        .nav{
    
    
            background-color: red;
            height: 40px;
        }
        .left-menu{
    
    
            background-color: darkslateblue;
            color: pink;
            width: 20%;
            height: 400px;
            float: left;
        }
        ul{
    
    
            margin: 0;
        }
        .content{
    
    
            width: 80%;
            float: right;
        }
        .clearfix{
    
    
            content: "";
            display: block;
            clear: both;
        }
        {
    
    % block css %}

        {
    
    % endblock %}
    </style>
    <!-- HTML5 shim 和 Respond.js 是为了让 IE8 支持 HTML5 元素和媒体查询(media queries)功能 -->
    <!-- 警告:通过 file:// 协议(就是直接将 html 页面拖拽到浏览器中)访问页面时 Respond.js 不起作用 -->
    <!--[if lt IE 9]>
      <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/html5shiv.min.js"></script>
      <script src="https://cdn.jsdelivr.net/npm/[email protected]/dest/respond.min.js"></script>
    <![endif]-->
</head>
<body>
<div class="nav">
    <a href="">盖伦</a>
    <a href="">卡萨丁</a>
    <a href="">虚空恐惧</a>
    <a href="">虚空之眼</a>
    <a href="">厄运小姐</a>
    <a href="">卡特琳娜</a>
    <input type="text"><button>搜索</button>
</div>
<div class="clearfix">
    <div class="left-menu">
        <ul>
            <li><a href="/menu1/">菜单1</a></li>
            <li><a href="/menu2/">菜单2</a></li>
            <li><a href="/menu3/">菜单3</a></li>
        </ul>
    </div>
    <div class="content">
        {
    
    % block content %}
            模板页面
        {
    
    % endblock %}
    </div>
</div>
{
    
    % block js %}

{
    
    % endblock %}
<!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js"></script>
<!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js"></script>
</body>
</html>



# base.html
{
    
    % extends 'muban.html' %}
{
    
    % block css %}
        .nav{
    
    
            background-color: blue;
        }
{
    
    % endblock css %}


{
    
    % block content %}
{
    
    #    留着模板的内容#}
    {
    
    {
    
     block.super }}
    <i>首页</i>
    <b>首页</b>
{
    
    % endblock content %}


{
    
    % block js %}

{
    
    % endblock js %}
    
    
    
# menu1.html
{
    
    % extends 'muban.html' %}

{
    
    % block content %}
    菜单一
{
    
    % endblock %}
    
    
    
# menu2.html
{
    
    % extends 'muban.html' %}

{
    
    % block content %}
    菜单二
{
    
    % endblock %}
    
    
    
# urls.py
from app01 import views

urlpatterns = [
    # url(r'^admin/', admin.site.urls),
    url(r'^$', views.base),
    url(r'^menu1/', views.menu1),
    url(r'^menu2/', views.menu2),
    # url(r'^menu3/', views.menu3),
]
    
    
# views.py
def base(request):  # http相关请求信息---封装----HTTP Request对象
    return render(request, 'base.html')
def menu1(request):
    return render(request, 'menu1.html')

def menu2(request):
    return render(request, 'menu2.html')

组件

可以将常用的页面内容如导航条,页尾信息等组件保存在单独的文件中,然后在需要使用的地方,文件的任意位置按如下语法导入即可。

{% include 'navbar.html' %}
# nav.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .c1{
    
    
            background-color: red;
            height: 40px;
        }
    </style>
</head>
<body>

<div class="c1">
    <div>
        <a href="">xx</a>
        <a href="">dd</a>
    </div>
</div>

</body>
</html>


# test.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
{
    
    % include 'nav.html' %}
<h1>xxxxxxxxxx</h1>
</body>
</html>


# urls.py
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^$', views.base),
    url(r'^login/', views.login),
    url(r'^home/', views.home),
    url(r'^menu1/', views.menu1),
    url(r'^menu2/', views.menu2),
    # url(r'^menu3/', views.menu3),
    url(r'^test/', views.test),

    url(r'^login2/', views.LoginView.as_view()),
]

自定义标签和控制器

自定义过滤器
1. app应用文文件夹中创建templatetags文件夹,必须是这个名字;
2. templatetags文件夹中创建一个xx.py文件,名字可以随便起。
3. 创建自定义过滤器
	from django import template

    register = template.Library()  # register固定的名字

    @register.filter
    def test(v1, v2):
        # 带参数
        s = v1 + v2
        return s

    @register.filter
    def xxoo(v1):
        # 不带参数
        s = v1 + 'xxoo'
        return s
4. 使用 html文件中的 {
    
    %  load 文件名  %}
    {
    
    % load te %}
    {
    
    #不带参数#}
    {
    
    {
    
     s1|xxoo  }}
    {
    
    #带参数#}
    {
    
    {
    
     s1|test:'幸福的生活在一起!' }}
5. 注意:参数最多两个。
        
自定义标签
1. app应用文文件夹中创建templatetags文件夹,必须是这个名字;
2. templatetags文件夹中创建一个xx.py文件,名字可以随便起。    
3. 创建自定义过滤器
	from django import template

    register = template.Library()  # register固定的名字
    @register.simple_tag
    def mytag(v1):
        s = v1 + '男枪'
        return s

    @register.simple_tag
    def mytag2(v1, v2, v3):
        s = v1 + v2 + v3
        return s
4. 使用 html文件中的 {
    
    %  load 文件名  %}
    {
    
    % load te %}
    <h>
        {
    
    % mytag s1 %}
        {
    
    % mytag2 s1 '寒冰' '卡特' %}
    </h> 
5. 注意:参数可以有多个。        

inclusion_tag

xx.py
from django import template

register = template.Library()  # register固定的名字
@register.inclusion_tag('includetag.html')
def func():
    return {
    
    'data':['人马','提莫','龙龟']}
test.html
<ul>
    {
    
    % for d in data %}
      <li>{
    
    {
    
     d }}</li>
    {
    
    % endfor %}
</ul>
作为一个组件在xxoo.html中使用
{
    
    % load te %}
{
    
    % func %}

静态文件配置

  1. 在项目文件夹下建立一个文件夹存放静态文件,比如叫jingtaiwenjian

  2. 在jingtaiwenjian文件夹下再建立一个css文件夹

  3. 在css文件夹下建立一个test.css文件

    h1{
          
          
        background-color: orange;
    }
    
  4. 在settings.py文件下写入

    STATIC_URL = '/static/' # 别名,一般都起static
    STATICFILES_DIRS = [
        os.path.join(BASE_DIR, 'jingtaiwenjian'),
    ]
    
  5. index.html

    {% load static %}
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta charset="utf-8">
        <link rel="stylesheet" href="{% static "css/test.css" %}">
        <title>Bootstrap 101 Template</title>
    
    
    </head>
    <body>
    <h1>你好,世界!</h1>
    
    <img src="{% static 'images/111.jpg' %}">
    </body>
    </html>
    

猜你喜欢

转载自blog.csdn.net/qq_31910669/article/details/109603700