Django 之 路由URL,视图,模板,ORM操作
1、后台管理的左侧菜单,默认只有第一个页签下面的选项是显示的,点了别的页签再显示别的页签下面的选项,问题是:点了任何菜单的选项后,左侧菜单又成了第一个页签的选项显示,别的页签隐藏,也就是左侧的菜单刷新了一遍。
2、登录页面,用户输入了用户名和密码,点了登录,如果输入的是错误的,则当前页面会刷新一遍(提交后就会刷新),用户已经输入的内容就全没有了;这需要用到ajax实现静默提交。
3、登录网址是login.html,后台管理网址是index.html,如果用户不进入login.html而直接进入index.html的话,事实上用户就不用登录即可访问后台了;这需要用会话保持做限制(cookie、session),如果没有保存登录信息,输入index.html会自动跳转到login.html。
1.路由系统
1.1 简单描述
django的每个url都对应一个python方法,
,比如用户输入的网址是127.0.0.1:8000/login,则django会默认从urls.py里配置的url,从上到下匹配,有匹配成功的,就执行对应方法,下面的就不匹配了;没有匹配的,就返回404。
1.2 使用正则表达式配置url
,这些数字页签,每一个都对应一个url,比如有1000页,是不是也要在urls.py里写一千个路由记录?并不是,而是用正则表达式,见下,
urls.py,
- # 使用正则表达式
- url(r'^detail/(\d+)/' ,views.detail)
views.py,
- # 如果urls.py里的url是两个值,比如/detail/123/那么对应的函数必须接收两个参数,如下,一个request,一个nid,不然会报错。
- def detail(request,nid):
- print(nid)
- return render(request,'back.html')
根据取到的这个nid,就可以去数据库里取数据了,比如第一页取前十条数据,第二页取11条-20条数据。
1.3 url设置关键参数
urls.py,

- urlpatterns = [
- #url(r'^admin/', admin.site.urls),
- url(r'^index/$', views.index),
- url(r'^back/$', views.back),
- url(r'^check/$', views.check),
- url(r'^detail/(\d+)/' ,views.detail),
- #设置关键参数,“?P<n1>”
- url(r'^detail1/(?P<n1>\d+)/(?P<n2>\d+)' ,views.detail1),
- ]

views.py,
- #n1、n2是取的关键参数
- def detail1(request,n1,n2):
- print(n1,n2)
- return render(request,'back.html')
2.实现分页展示和查看详情
urls.py,
- urlpatterns = [
- url(r'^pageTest/(\d+)/$', views.pageTest),
- url(r'^details/(\d+)/$', views.details),
- ]
views.py,

- from django.shortcuts import render
- from django.shortcuts import redirect
- from django.shortcuts import HttpResponse
- from cmdb import models
- # Create your views here.
- user_list1 = []
- for item in range(99):
- temp = {'id':str(item),'username':'zsc' + str(item),'email':'email' + str(item)}
- user_list1.append(temp)
- def pageTest(request,page):
- #1,0-9
- #2,10-19
- #3,20-29
- page = int(page)
- startpoint = (page - 1) * 10
- endpoint = page * 10
- user_list = user_list1[startpoint:endpoint]
- return render(request,'page.html',{'user_list':user_list})
- def details(request,nid):
- nid = int(nid)
- current_details = user_list1[nid]
- return render(request,'details.html',{'current_details':current_details})

details.html,

- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- </head>
- <body>
- <ul>
- <li>{{ current_details.id }}</li>
- <li>{{ current_details.username }}</li>
- <li>{{ current_details.email }}</li>
- </ul>
- </body>
- </html>

page.html,

- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- </head>
- <body>
- <table>
- <tr>
- <td>id</td>
- <td>username</td>
- <td>details</td>
- </tr>
- {% for item in user_list %}
- <tr>
- <td>
- {{ item.id }}
- </td>
- <td>
- {{ item.username }}
- </td>
- <td>
- <a href="/details/{{ item.id }}" target="_blank">see the details</a>
- </td>
- </tr>
- {% endfor %}
- </table>
- </body>
- </html>

3.路由系统根据app分流
一个项目有很多个app,比如web是主站,manger是后台,那urls.py怎么配置更合理呢?答案是根据app来实现url分流处理,见下以web为例配置的urls.py,
项目里的urls.py,

- from django.conf.urls import url,include
- urlpatterns = [
- #以web开头的所有访问都抛给web这个app下面的urls.py
- url(r'^web/',include('web.urls.py')),
- ]

在web这个app下面新建一个urls.py,

- from web import views
- urlpatterns = [
- url(r'^pageTest/(\d+)/$', views.pageTest),
- url(r'^details/(\d+)/$', views.details),
- ]

这样配置好后,比如访问127.0.0.1:8000/web/pageTest/1,就会将这个url抛给web下面的urls.py里对应的函数处理。
这样,monitor的url交给monitor处理,manager的url交给manger处理,更清晰。
4.模版语言之基本操作和filter
,如左面两个图所示,模板渲染的过程,其实就是把html转化为python方法的过程,在python方法里新建一个列表,然后把常量值都append进去,遇到变量值的话,再获取变量值然后append到列表里,最后将这些解析好的代码拼接成一个html页面,再return给用户。
http://www.cnblogs.com/wupeiqi/articles/5237704.html
4.1 基本操作
urls.py,
- urlpatterns = [
- url(r'^templateTest/$', views.templateTest),
- ]
templateTest.html,

- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- </head>
- <body>
- <p>{{ k1 }}</p>
- <p>{{ k2 }}</p>
- #根据下标取列表的值时,不能用“[]”,必须用“.”
- <p>{{ k2.0 }}</p>
- {% for item in d1 %}
- # forloop.counter,从1开始依次输出;
- # forloop.counter0,从0开始依次输出;
- # forloop.first,判断是否是第一个值,如果是就返回true
- <p>{{ item }},{{ forloop.counter }},{{ forloop.counter0 }},{{ forloop.first }},{{ forloop.last }},{{ forloop.revcounter }}</p>
- {% endfor %}
- {% if k1 == 'v1' %}
- <h1>v1</h1>
- {% elif k1 == 'v2' %}
- <h1>v2</h1>
- {% else %}
- <h1>77777</h1>
- {% endif %}
- </body>
- </html>

views.py,
- def templateTest(request):
- return render(request,'templateTest.html',{'k1':'v2','k2':[11,22,33],'d1':{'kk1':'vv1','kk2':'vv2','kk3':'vv3'}})
4.2 模板内置方法
{{ item.event_start|date:"Y-m-d H:i:s"}},将时间格式化输出
{{ bio|truncatewords:"30" }}
{{ my_list|first|upper }},将列表的第一个元素大写
{{ name|lower }},将name的值小写。
4.3 模板里自定义filter方法
模板里内置的方法略显死板,所以还是有必要自己建模板方法的,步骤见下:
1、在app(这里说的app意思是小程序,并不是名字叫app)目录下新建一个目录“templatetags”,目录名必须是这个,定死的;
2、在templatetags目录下新建一个.py文件,比如说是tempTest.py,内容见下,

- #下面两行是必须导入的
- from django import template
- from django.utils.safestring import mark_safe
- #这里的register、template.Library()都是固定的,不能改名!!!
- register = template.Library()
- #加上下面这个装饰器后,这个python方法就变成了模板方法。
- #这个filter装饰器最多接收两个参数,第一个参数必须有,第二个参数可有可无;后面讲的simple_tag的装饰器支持多个参数。
- #如果想用filter处理多个参数怎么办?可以将多个字符串当成一个值传给函数,然后再做切片处理,如{{ k1 | f1:"zsc,aqq" }}
- @register.filter()
- def f1(v1,arg):
- return v1 + "666" + arg

3、在html中引入模板方法,

- {% load tempTest %}
- #我们一般在第一行引入模板方法
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- </head>
- <body>
- #调用模板方法并传参数
- {{ k1|f1:"zsc" }}
- </body>
- </html>

4、使用模板方法
- {{ k1|f1 }}
- #f1是tempTest.py里的方法
5、在settings中配置当前app,不然django无法找到自定义的simple_tag

- INSTALLED_APPS = (
- 'django.contrib.admin',
- 'django.contrib.auth',
- 'django.contrib.contenttypes',
- 'django.contrib.sessions',
- 'django.contrib.messages',
- 'django.contrib.staticfiles',
- #此处app的名称是app01
- 'app01',
- )

5.模版语言之simple_tag
5.1 创建simple_tag模板语言

- from django import template
- from django.utils.safestring import mark_safe
- register = template.Library()
- @register.simple_tag
- def f2(s1,s2,s3,s4):
- return s1 + s2 + s3 + s4

- 在html里调用方式:
- {% f2 "zsc" "1" "anqingqing" "xiaoxixi" %}
5.2 filter和simple_tag对比
filter:
限制参数个数;
支持作为模板语言if判断的条件,也就是可以用{% if k1|filterfunc %}这种形式,如果funcone返回true,就为真,返回false就为假。
simple_tag:
不限制参数个数;
不支持作为模板语言if判断的条件,也就是不能用{% if simple_tag_func arg1 %}这种形式,不论simple_tag_func返回true或false都没作用。
下例为html中的模板语言将filter作为if判断条件的例子:

- testTemp.py:
- from django import template
- from django.utils.safestring import mark_safe
- register = template.Library()
- @register.filter
- def f3(v1):
- if v1 == 'vvv':
- return True
- else:
- return False
- templateTest.py:
- {% if k1|f3 %}
- <h1>true</h1>
- {% else %}
- <h1>false</h1>
- {% endif %}

6.模版语言之母板
网站后台的格局一般是header、body、footer,body的左边是menu,右边是content,一般header和footer都是不变化的,点击menu里的选项后,比如点击“用户管理”,“用户管理”变成被选中的样式,同时右边的content区域出来用户的管理信息,点击“服务器管理”,“服务器管理”变成被选中的样式,同时右边的content区域出来服务器的管理信息。这其实是在“用户管理”和“服务器管理”上分别加了不同的url,跳转到不同的页面。这时候有个问题,跳转到不同的url,这俩html页面的header、footer都是不变化的,那用户管.html和服务器管理.html都要重新写一遍header和footer的内容吗?答案是否定的。这时候就要用到母板,创建一个母板,然后子html页面引用母板即可,就像导入python模块似的,见下例,
urls.py,

- urlpatterns = [
- url(r'^motherModel/$', views.motherModel),
- url(r'^userinfo/$', views.userinfo),
- url(r'^serverinfo/$', views.serverinfo),
- ]

views.py,

- def motherModel(request):
- return render(request,'motherModel.html')
- def userinfo(request):
- return render(request, 'userinfo.html', {'user_list': user_list1})
- def serverinfo(request):
- return render(request, 'serverinfo.html')

motherModel.html,

- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- <style>
- .page-header{
- width:100%;
- height:100px;
- background-color:red;
- }
- .page-body{
- min-height:400px;
- }
- .page-footer{
- width:100%;
- height:50px;
- background-color:green;
- }
- .menu{
- width:20%;
- float:left;
- }
- .content{
- width:80%;
- float:left;
- }
- </style>
- </head>
- <body>
- <div class="page-header">
- </div>
- <div class="page-body">
- <div class="menu">
- <ul>
- <li><a href="/userinfo/">userManage</a></li>
- <li><a href="/serverinfo/">serverManage</a></li>
- </ul>
- </div>
- <div class="content">
- #可以定义多个block,content是当前block的名称
- {% block content%}{%endblock%}
- </div>
- </div>
- <div class="page-footer">
- </div>
- </body>
- </html>

userinfo.html,

- #导入母板html
- {% extends "motherModel.html" %}
- #这里也要写上{% block content %},与母板里的block对应
- {% block content %}
- <table>
- {% for item in user_list %}
- <li>{{ item.id }},{{ item.username }} ,{{ item.email }}</li>
- {% endfor %}
- </table>
- {% endblock %}

serverinfo.html,

- {% extends "motherModel.html" %}
- {% block content %}
- <table>
- i am is a server,hello.
- </table>
- {% endblock %}

7.模板导入js
在上面的基础上,加了一个点击菜单后给菜单添加背景色效果。
templateModel.html,

- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- <style>
- .page-header{
- width:100%;
- height:100px;
- background-color:red;
- }
- .page-body{
- min-height:400px;
- }
- .page-footer{
- width:100%;
- height:50px;
- background-color:green;
- }
- .menu{
- width:20%;
- float:left;
- }
- .content{
- width:80%;
- float:left;
- }
- .activego{
- background-color:green;
- }
- </style>
- </head>
- <body>
- <div class="page-header">
- </div>
- <div class="page-body">
- <div class="menu">
- <ul>
- <li><a id="userinfo" href="/userinfo/" class="usermanage">userManage</a></li>
- <li><a id="serverinfo" href="/serverinfo/">serverManage</a></li>
- </ul>
- </div>
- <div class="content">
- {% block content %}{% endblock %}
- </div>
- </div>
- <div class="page-footer">
- </div>
- #此处导入一个js,使左侧菜单点击后添加背景
- {% block js %} {% endblock %}
- </body>
- </html>

userinfo.html,

- {% extends "motherModel.html" %}
- {% block content %}
- <table>
- {% for item in user_list %}
- <li>{{ item.id }},{{ item.username }} ,{{ item.email }}</li>
- {% endfor %}
- </table>
- {% endblock %}
- {% block js %}
- <script src="http://cdn.bootcss.com/jquery/1.11.1/jquery.min.js"></script>
- <script>
- $("#userinfo").addClass("activego")
- </script>
- {% endblock %}

serverinfo.html,

- {% extends "motherModel.html" %}
- {% block content %}
- <table>
- i am is a server,hello.
- </table>
- {% endblock %}
- {% block js %}
- <script src="http://cdn.bootcss.com/jquery/1.11.1/jquery.min.js"></script>
- <script>
- $("#serverinfo").addClass("activego")
- </script>
- {% endblock %}

8.include小组件
html页面有很多输入框、展示框,可以用引入的方式避免代码重复编写,见下,
- <body>
- <form>
- <input />
- <input />
- <input />
- </form>
- </body>
- 等同于下面,
- <body>
- {% include 'x.html' %}
- {% include 'x.html' %}
- {% include 'x.html' %}
- </body>
- x.html,
- <form>
- <input />
- <input />
- <input />
- </form>
9.inclusion_tag
inclusion_tag()
原型: django.template.Library.inclusion_tag()
主要作用:通过渲染一个模板来显示一些数据。
例如,Django的Admin界面使用自定义模板标签显示"添加/更改"表单页面底部的按钮。这些按钮看起来总是相同,但链接的目标却是根据正在编辑的对象而变化的。
这种类型的标签被称为"Inclusion 标签",属于自定义标签的一种。
项目实例:
在我的一个blog项目中,一个博主的主页面的左侧栏和查看博主某篇文章的页面的左栅栏的一样的。为了不用重复写同样的代码。且提高页面的扩展性。我的bbs的左侧栏就用了inclusion_tag来实现。
1.目录结构
在项目blog这个app下面创建一个 templatetags 文夹。这个文件夹的名字必须是 templatetags 来命名的。然后在此文件夹下自定义一个 mytag.py 文件。
2. mytag.py:
这一个就是来处理不同数据的函数,返回的结果一致。
- from django import template
- from django.db.models import Count
- from blog import models
- register = template.Library()
- @register.inclusion_tag('menu.html')
- def get_menu_style(username):
- site_name = models.Blog.objects.filter(userinfo__username=username).values_list("site_name")[0][0]
- # 查询站点下各分类对应的文章数量
- blog_category_list = models.Category.objects.filter(blog__site_name=site_name).values("pk").annotate(
- c=Count("article")).values_list("title", "c")
- # 查询站点下各标签对应的文章数量
- blog_tag_list = models.Tag.objects.filter(blog__site_name=site_name).values("pk").annotate(
- c=Count("article")).values_list("title", "c")
- # 查询站点下各年月对应的文章数量
- blog_date_list = models.Article.objects.filter(user__blog__site_name=site_name).extra(
- select={"y_m_date": "DATE_FORMAT(blog_article.create_time,'%%Y-%%m')"}).values("y_m_date").annotate(
- c=Count("nid")).values_list("y_m_date", "c")
- return {"site_name": site_name, "blog_category_list": blog_category_list, "blog_tag_list": blog_tag_list,
- "blog_date_list": blog_date_list}
3. menu.html:
用来渲染mytag.py所返回的数据
- <div class="panel panel-default">
- <div class="panel-heading">文章分类</div>
- {% for category in blog_category_list %}
- {% if forloop.last %}
- <div class="panel-body">
- <a href="/{{ site_name }}/category/{{ category.0 }}">{{ category.0 }}({{ category.1 }})</a>
- </div>
- {% else %}
- <div class="panel-body xuxian">
- <a href="/{{ site_name }}/category/{{ category.0 }}">{{ category.0 }}({{ category.1 }})</a>
- </div>
- {% endif %}
- {% endfor %}
- </div>
- <div class="panel panel-warning">
- <div class="panel-heading">
- <h3 class="panel-title">标签分类</h3>
- </div>
- {% for tag in blog_tag_list %}
- {% if forloop.last %}
- <div class="panel-body">
- <a href="/{{ site_name }}/tag/{{ tag.0 }}">{{ tag.0 }}({{ tag.1 }})</a>
- </div>
- {% else %}
- <div class="panel-body xuxian">
- <a href="/{{ site_name }}/tag/{{ tag.0 }}">{{ tag.0 }}({{ tag.1 }})</a>
- </div>
- {% endif %}
- {% endfor %}
- </div>
- <div class="panel panel-danger">
- <div class="panel-heading">
- <h3 class="panel-title">日期分类</h3>
- </div>
- {% for date in blog_date_list %}
- {% if forloop.last %}
- <div class="panel-body">
- <a href="/{{ site_name }}/archive/{{ date.0 }}">{{ date.0 }}({{ date.1 }})</a>
- </div>
- {% else %}
- <div class="panel-body xuxian">
- <a href="/{{ site_name }}/archive/{{ date.0 }}">{{ date.0 }}({{ date.1 }})</a>
- </div>
- {% endif %}
- {% endfor %}
- </div>
4. homebase.html:
这里我需要在 homebase.html 中引用上面渲染后的 menu.html ,只需要在合适的地方加入以下两行代码:
- <div class="row">
<div class="col-md-3 menu">
{% load mytags %}
{% get_menu_style request.user %}
</div>
<div class="col-md-9 article-content">
{% block cotent %}
{% endblock %}
</div>
上面的代码中 request.user 是一个参数。
Django 之 路由URL,视图,模板,ORM操作的更多相关文章
- Django学习---路由url,视图,模板,orm操作
Django请求周期 url -> 路由系统 ->函数或者类 -> 返回字符串 或者 模板语言 Form表单提交: 点击提交 -> 进入url系统 -> 执行函数 ...
- Django 的路由层 视图层 模板层
--------------------------------------------------------------通过苦难,走向欢乐.——贝多芬 Django-2的路由层(URLconf) ...
- Day18 Django之路由系统、模板语言、Ajax、Model
一.路由系统 1.创建Django项目 django-admin startproject day18 cd day18 python3 manage.py startapp app01 2.app0 ...
- Django学习笔记之Models与ORM操作
一.ORM增加 from django.db import models class Publisher(models.Model): name = models.CharField(max_leng ...
- django上课笔记1-目录介绍-路由系统-ORM操作
一.Django目录介绍 django-admin startproject mysite # 创建名为mysite的项目 cd mysite # 切换到该目录下 python manage.py s ...
- Django(十一)视图详解:基本使用、登录实例、HttpReqeust对象、HttpResponse对象
一.视图(基于类的视图) [参考]https://docs.djangoproject.com/zh-hans/3.0/topics/class-based-views/intro/ 1)视图的功能 ...
- 在pycharm中进行ORM操作
打开manage.py, 复制 import..... if.......os..... 导入django,开启django, 导入app中的models orm操作 import os if _ ...
- python第一百零五天 ---Django 基础 路由系统 URL 模板语言 ORM 操作
一 路由系统 URL 1 url(r'^index/',views.index) url(r'^home/', views.Home.as_view()) 2 url(r'^detail-(\d+). ...
- 2016/5/6 thinkphp ①框架 ② 框架项目部署 ③MVC模式 ④控制器访问及路由解析 ⑤开发和生产模式 ⑥控制器和对应方法创建 ⑦视图模板文件创建 ⑧url地址大小写设置 ⑨空操作空控制器 ⑩项目分组
真实项目开发步骤: 多人同时开发项目,协作开发项目.分工合理.效率有提高(代码风格不一样.分工不好) 测试阶段 上线运行 对项目进行维护.修改.升级(单个人维护项目,十分困难,代码风格不一样) 项目稳 ...
随机推荐
- [Java]list集合为空或为null的区别
判断的是list这个集合的问题,当前需要判断list内值的问题. 简述判断一个list集合是否为空,我们的惯性思维是判断list是否等于null即可,但是在Java中,list集合为空还是为null, ...
- 关于空想X
只是一个ID而已,我才不会告诉你这是一艘法国驱逐舰 想去打CTF,但是什么也不会. 博主人很懒,估计也不会更几篇博客,嘿嘿嘿. 最近在学PYTHON,欢迎交流.
- 树莓派3B+(一)
第一步:安装raspbian系统 介绍:Raspbian是为树莓派设计,基于Debian的操作系统,由一个小团队开发.其不隶属于树莓派基金会,但被列为官方支持的操作系统. 下载地址:https://w ...
- jquery 设置 transform/translate 获取 transform/translate 的值
//获取 transform 值 var reg=/matrix.(((-)?([0-9]+.)?\d+([, ]+)?){6})./g; var str= progressUI.css(" ...
- python学习日记(面向对象——组合)
组合指的是,在一个类中以另外一个类的对象作为数据属性,称为类的组合 圆环是由两个圆组成的,圆环的面积是外面圆的面积减去内部圆的面积.圆环的周长是内部圆的周长加上外部圆的周长.这个时候,我们就首先实现一 ...
- 构建一个maven聚合类型的横向可扩展项目
那个时候初入java这个大家庭,学习的方向很乱.毕业后,在公司磨练了一年,总想着是该交一份答卷了,可能成绩不会很好,但求及格!那么考试题目呢,我计划搭建一个横向可扩展的项目,可以在平台自扩展各种子项目 ...
- windows类似grep的命令——findstr
windows类似grep的命令——findstr 使用Chrome发现访问google总是向香港那边跳转,估计配置文件中google网站映射的地址是www.google.com.hk,便想着改配 ...
- Vue学习笔记五:事件修饰符
目录 什么是事件修饰符 没有事件修饰符的问题 HTML 运行 使用事件修饰符 .stop阻止冒泡 .prevent 阻止默认事件 .capture 添加事件侦听器时使用事件捕获模式 .self 只当事 ...
- 网络协议 HTTP入门学习
概述 Web 的诞生,源于三大技术的诞生,它们都是当年 Web 之父 Tim Berners-Lee 自己 开发的,世界上第一个网站诞生的时间是 1991 年,三大技术的诞生也就是在此之前的不久: 1 ...
- JS通用模块模式 UMD
历史 JS诞生之初面向简单页面开发, 没有模块的概念. 后来页面逐渐复杂, 人类构造到 IIFE 立即执行函数来模拟 模块: 之前也有雅虎的实践,使用命名空间 作为模块名. 最后衍生出 面向各种使用场 ...