Django 的路由系统
1、django 处理一个请求的流程
- django 使用一个 URLconf 模块,默认为 urls.py 文件,可以通过 setting.py 配置文件修改
ROOT_URLCONF = "Day15.urls" # 默认值
- django 加载 URLconf 模块并寻找 urlpatterns( django.conf.url.url() 实例的列表)
- django 依次匹配每一个 url 条目,直到请求的 URL 与第一个条目匹配
- 一旦一个正则表达式匹配上,Django 将导入并调用给出的视图(一个 python 函数或者是一个基于类的视图)
- 如果没有匹配到正则表达式,或者如果过程中抛出了一个异常,Django 将调用一个适当的错误处理视图
默认的 urls.py 文件内容如下:
from django.conf.urls import url from django.contrib import admin urlpatterns = [ url(r'^admin/', admin.site.urls), ]
2、url() 方法
url(regex, view, kwargs=None, name=None) # regex:正则表达式 # view:当正则表达式匹配到后执行的 python 函数或者基于类的视图 # kwargs:任意数量的关键字参数可以作为一个字典传递给目标视图 # name:对 URL 进行命名,可以在 django 的任意地方,尤其是模板中进行显式的引用它
3、基本的 urls 对应
urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^hello/', views.hello), ]
4、动态路由对应
将 URL 内容的一部分作为参数传递给函数,如分页,当页面有很多的时候,可以使用动态路由对应,不需要写重复的路由对应.
编辑 Day15 目录下的 urls.py 文件
urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^hello/', views.hello), # 基于位置传递参数,可传递多个 url(r'^page/(d+)/', views.page), # 基于名称传递参数,可传递多个 url(r'^manage/(?P<name>w*)/(?P<nid>d*)/', views.manage), # 为路由添加额外的参数 url(r'^manage1/(?P<name>w*)/', views.manage1, {'nid': 444}), ]
编辑 Day15 目录下的 views.py 文件
from django.shortcuts import HttpResponse def hello(request): return HttpResponse("Hello World") def page(request, p): # urls 中 d+ 匹配的值会传递给 p return HttpResponse("page: {}".format(p)) def manage(request, name, nid): # urls 中 name 和 nid 匹配到的值会分别传递给 name 和 nid return HttpResponse("name: {}<p>id: {}".format(name, nid)) def manage1(request, name, nid): # urls 中匹配到的 name 值传递给 name, 而 nid 是始终是固定值 444 return HttpResponse("name: {}<p>id: {}".format(name, nid))
5、基于 app 的路由映射
首先在项目的 urls.py 中配置:
from django.conf.urls import url, include urlpatterns = [ # 通过 app 对路由进行分发,必须在 settings 的 INSTALLED_APPS 中添加 app 名称 url(r'app01/', include('app01.urls')), ]
编辑 settings.py
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app01', # 添加 app01 ]
然后在 app01 中创建 urls.py 文件
from django.conf.urls import url from app01.views import index urlpatterns = [ url('^index/', index), ]
最后编辑 views.py 文件
def index(request): return HttpResponse("<h3>index web page.</h3>")
访问测试: http://127.0.0.1:8000/app01/index ,正常显示内容为 index web page。
模板
模板其实就是一些嵌套着固定语法的文本,然后将获取到的数据根据语法插入到模板中,最终将信息返回给客户端
在 settings 中指定模板文件的位置
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', # 指定模板的路径, BASE_DIR 为项目的根目录 'DIRS': [os.path.join(BASE_DIR, 'templates'), ], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ]
常用方法
{{ item }} {% for item in item_list %} {{ item }} {% endfor %} {{ forloop.counter }} // item 的序号(从1开始) {{ forloop.counter0 }} // item 的序号(从0开始) {{ forloop.first }} // item 是否为 list 的第一个元素 {{ forloop.last }} // item 是否为 list 的最后一个元素 {{ forloop.revcounter }} // item 的序号(反序) {% if ordered_warranty %} {% else %} {% endif %} 母板:{% block title %}{% endblock %} 子板:{% extends "base.html" %} {% block title %}{% endblock %}
导入:{% include "public.html" %} 帮助方法: {{ item.event_start|date:"Y-m-d H:i:s"}} {{ bio|truncatewords:"30" }} {{ my_list|first|upper }} {{ name|lower }}
自定义方法:
filter // 只能传递一个参数,可以作为模板语言的 if 条件
simple_tag // 支持多个参数,不能作为模板语言的 if
实例1 [取值]:
修改 views.py 中的 index 函数
from django.shortcuts import render def index(request): return render(request, # 必须参数 "index.html", # 模板文件 { "k1": "v1", "k2": [1, 2, 3, 4], "k3": {"name": "wenchong", "age": 10} } # 给模板传递的值 )
在 templates 目录中创建 index.html
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> </head> <body> <h1>单独获取</h1> 获取 k1 对应的值: {{ k1 }} <br /> 获取 k2 对应的列表中的第二个元素: {{ k2.1 }} <br /> 获取 k2 对应的列表中的第三个元素: {{ k2.2 }} <br /> 获取 k3 对应的字典中 name 和 age 的值: {{ k3.name }} {{ k3.age }} <p> <h1>循环获取 k2 中的每一个元素: </h1> <table border="1"> <tr> <th>列表元素</th> <th>从1开始的序号</th> <th>从0开始的序号</th> <th>是否为第一个元素</th> <th>是否为最后一个元素</th> <th>从1开始的序号【反序】</th> <th>从0开始的序号【反序】</th> </tr> {% for item in k2 %} <tr> <td> {{ item }} </td> <td> {{ forloop.counter }} </td> {# item 的序号(从1开始) #} <td> {{ forloop.counter0 }} </td> {# item 的序号(从0开始) #} <td> {{ forloop.first }} </td> {# item 是否为第一个元素 #} <td> {{ forloop.last }} </td> {# item 是否为最后一个元素 #} <td> {{ forloop.revcounter }} </td> {# item 的序号(从1开始,反序) #} <td> {{ forloop.revcounter0 }} </td> {# item 的序号(从0开始,反序) #} </tr> {% endfor %} </table> <h1>if 判断:</h1> {% if k1 == "v1" %} <h3>v1</h3> {% elif k1 == "v2" %} <h3>v2</h3> {% else %} <h3>v3</h3> {% endif %} </body> </html>
访问页面:
实例2 [母版和子版]
创建母版 base.html
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>测试页面V1</title> <style> * { margin: 0; padding: 0; } .page-header { background-color: blue; height: 50px; text-align: center; line-height: 50px; } .page-content { } .page-content .left-menu { background-color: aqua; height: 500px; width: 200px; float: left; } .page-content .left-menu ul li { list-style-type: none; width:100%; height:50px; background-color: aqua; border-bottom: 1px solid ; line-height: 50px; } .page-content .right-content { float: left; } </style> </head> <body> <div class="page-header"> <h1>这里是不变化的开头部分</h1> </div> <div class="page-content"> <div class="left-menu"> <ul> <li><a href="/app01/index"> 首页</a></li> <li><a href="/app01/menu1"> 菜单一</a></li> <li><a href="/app01/menu2"> 菜单二</a></li> <li><a href="/app01/menu3"> 菜单三</a></li> <li><a href="/app01/menu4"> 菜单四</a></li> </ul> </div> <div class="right-content"> {% block content %}{% endblock %} </div> </div> </body> </html>
创建子版:
# 分别创建下面 5 个 html 文件 ### index.html {% extends "base.html" %} {% block content %} <h1>这里是首页</h1> {% endblock %} ### page1.html {% extends "base.html" %} {% block content %} 这个是菜单二的页面 {% endblock %} ### page2.html {% extends "base.html" %} {% block content %} 这个是菜单三的页面 {% endblock %} ### page3.html {% extends "base.html" %} {% block content %} 这个是菜单四的页面 {% endblock %} ### page4.html {% extends "base.html" %} {% block content %} 这个是菜单一的页面 {% endblock %}
编辑 app01/views.py:
def index(request): return render(request, "index.html") def menu(request, id): return render(request, "page{}.html".format(id))
编辑 app01/urls.py:
from django.conf.urls import url from app01.views import index, menu urlpatterns = [ url('^index/', index), url('^menu(d)+/', menu), ]
访问页面:
http://127.0.0.1:8000/app01/index,并点击菜单,会发现只有内容部分变化,其他部分均不发生变化。
实例3 [导入公共标签]
当一段代码需要在多个页面中重复利用时,可以使用导入 include 导入
创建公共代码 public.html:
<h1>这是公共代码块</h1>
修改 index.html 页面
{% extends "base.html" %} {% block content %} <h1>这里是首页</h1> {#导入 public.html 的内容#} {% include "public.html" %} {% endblock %}
访问页面 http://127.0.0.1:8000/app01/index
实例4 [自定义 simple_tag 和 filter]
1、在 app01 目录下创建 templatetags 目录
** 目录名称必须为 templatetags,app01 在 settings 中已经添加。
2、在 templatetags 下创建 custom.py 文件,名称可自定义
# /user/bin/env python __author__ = 'wenchong' from django import template # 变量名必须为 register register = template.Library() @register.simple_tag def my_simple_tag(v1, v2, v3): return v1+v2+v3 # 无参数的 filter @register.filter def my_filter(num): return int(num) + 100 # 有参数的 filter @register.filter def filter_add(value, arg): return int(value) + int(arg)
3、修改 views.py
def tags(request): return render(request, "tags.html")
4、创建 tags.html
{#加载自定义方法#} {% load custom %} {#直接调用 filter#} 调用无参数的filter: {{ 1|my_filter }} <br /> 调用带参数的filter: {{ 1|filter_add:100 }} <br /> 调用 my_simple_tag: {% my_simple_tag 1 2 3 %} <br /> {% if 1|my_filter == 101 %} 原始数字为 1 {% endif %}
5、访问页面
http://127.0.0.1:8000/app01/tags
静态文件
web 请求时会有很多的静态文件,需要放在指定的目录中供下载,比如 js,css,imgs 文件
1、在项目目录下创建 statics 目录,目录名可自定义
2、在 settings 中配置静态文件路径
# 页面调用静态文件的前缀 STATIC_URL = '/static/' # 静态文件存放路径 STATICFILES_DIRS = ( os.path.join(BASE_DIR, 'statics'), )
AJAX
AJAX = 异步 JavaScript 和 XML。
AJAX 是一种用于创建快速动态网页的技术。
通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
传统的网页(不使用 AJAX)如果需要更新内容,必需重载整个网页面。
通常使用 AJAX 的场景:
- 用户注册时,通过 AJAX 检查用户名是否存在
- 用户登录时,检查用户名密码是否正确
- 删除数据时,通过 AJAX 把 ID 发送给后端服务器,后端服务器在数据库中删除,前段页面通过 JS 删除,页面不用重新加载
实现步骤:
1、配置静态文件目录
2、在静态文件目录 statics 中上传 jquery 文件
3、创建 login.html 文件
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> </head> <body> <div> <div id="message" style="color: red"></div> 用户名:<input type="text" id="username" /> <br /> 密码:<input type="password" id="password" /> <br /> <input type="button" value="登陆" onclick="login()"> </div> <script type="application/javascript" src="/static/jquery-1.7.1.min.js"></script> <script> function login(){ $.ajax({ url: "/app01/login/", {# ajax 请求的 URL #} type: "POST", {# 指定 ajax 请求的访问为 post #} dataType: "json", {# 指定 ajax 返回的数据为 json 格式,默认为 str #} {# data 为 ajax 向 URL 发送的数据 #} data: {"username": $("#username").val(), "password": $("#password").val()}, success: function(data){ {# 当用户名密码正确时,跳转到 https://www.baidu.com, 否则提示消息 #} if(data.status) { location.href = "https://www.baidu.com"; } else{ $("#message").text(data.msg) } } }) } </script> </body> </html>
编辑 views.py
import json def login(request): result = {"status": False, "msg": None} if request.method == "POST": username = request.POST.get("username", None) password = request.POST.get("password", None) if username == "wenchong" and password == "123": result["status"] = True else: result["msg"] = "用户名或密码错误!" return HttpResponse(json.dumps(result)) return render(request, "login.html")
编辑 urls.py
from app01.views import login urlpatterns = [ url('^login/', login), ]
访问页面
http://127.0.0.1:8000/app01/login
Model 的简单使用
1、在 settings 中 INSTALLED_APPS 添加 app01
2、创建数据库表
from django.db import models class UserInfo(models.Model): # 创建数据库表 UserInfo,表中有 username 和 password 两列 username = models.CharField(max_length=64) password = models.CharField(max_length=64)
3、同步数据库
python3.5 manage.py makemigrations python3.5 manage.py migrate # 创建超级用户 python3.5 manage.py createsuperuser
4、在 admin 中注册 UserInfo 表,编辑 admin.py
from django.contrib import admin from app01 import models # 将 UserInfo 表的管理添加到后台 admin admin.site.register(models.UserInfo)
5、访问页面添加用户名
6、修改 views 中的 login 函数
import json # 导入 UserInfo from app01.models import UserInfo def login(request): result = {"status": False, "msg": None} if request.method == "POST": username = request.POST.get("username", None) password = request.POST.get("password", None) # 调用数据库检查用户名和密码是否正确 if UserInfo.objects.filter(username=username, password=password): # if username == "wenchong" and password == "123": result["status"] = True else: result["msg"] = "用户名或密码错误!" return HttpResponse(json.dumps(result)) return render(request, "login.html")