Django 之基础续
分类:
IT文章
•
2024-07-16 22:56:49
1.路由系统之动态路由
前言:还记得之前的分页效果,这个如何实现呢?答案就是动态路由。
url(r'^detail/(d+)/$', views.detail),
url(r'^detail2/(d+)/(d+)/$', views.detail2),
url(r'^detail3/(?P<p1>d+)/(?P<x2>d+)/', views.detail3),#设定后端对应处理的函数分别为p1,x2
通过正则表达式,匹配包含数字的URL,交给views中的函数处理,对应的函数要传送匹配的参数,具体如下:
def detail(request, nid):
print(nid)
return HttpResponse('OK')
# detail2(1,2)
def detail2(request, xid, nnid):
print(xid,nnid)
return HttpResponse('OK')
# detail3(x2=234,p1=123)
def detail3(request, p1, x2):
print(p1,x2)
return HttpResponse('OK')
那么分页是怎么实现的呢,代码如下:
##url
url(r'^index/(d+)/', views.index),
##view
#生成一个包含字典的列表
USER_LIST = []
for item in range(94):
temp = {"id": item, 'username':'jason'+str(item), 'email': 'email' + str(item)}
USER_LIST.append(temp)
def index1(request, page):
print(page)
# 1,0-9
# 2,10-19
# 3,20-29
page = int(page)
start = (page - 1) * 10
end = page * 10
user_list = USER_LIST[start:end]#设定每页取值的范围
# return HttpResponse('OK')
return render(request, 'index1.html', {'user_list': user_list})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<table>
<tr>
<td>ID</td>
<td>用户名</td>
<td>详细</td>
</tr>
{% for item in user_list %}
<tr>
<td>{{ item.id }}</td>
<td>{{ item.username }}</td>
<td>
<a href="/cmdb/detail/{{ item.id }}">查看详细</a>
</td>
</tr>
{% endfor %}
</table>
</body>
</html>
index1.html
效果如下:


2.自定义标签方法
自定义标签目录名必须为templatetags, 否则django无法识别,分两步实现:
1、创建指定文件,名称不能改 templatetags
2、创建任意 .py 文件,如:mytag.py
# 必须不变
register = template.Library()
# 创建函数
@register.filter
def f1(value):
value + "666"
3、在html模版的头部执行
{% load mytag %}
4、html代码
k1 = 'VVV'
{{k1}} => vvv
{{k1|f1}} => vvv666 ##将k1通过管道传给f1函数
5、 settings.py 中注册app
如下图:

from django import template
from django.utils.safestring import mark_safe
from django.template.base import Node,TemplateSyntaxError
register = template.Library()
@register.filter
def f1(value,arg):
##filter只能传一个参数,可以使用html中的if语句
return value + "666" + arg
@register.simple_tag
def f2(s1,s2,s3,s4):
#simplet tag 不支持html中的if语句
return s1 + s2 + s3 + s4
@register.filter
def f3(value):
##filter支持if语句
if value == 'VVV':
return True
return False
mytag
def template(request):
return render(request,
'template.html',
{'k1':'vvvv','k2':[11,22,33],'k3':{'nid':12,'name':'Jason'}}
Views.py
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
{% load mytag %}
</head>
<body>
{{ k1 }}
{{ k1.1 }}
{{ k1.name }}
{% for item in k2 %}
<p>{{ item }},{{ forloop.counter }},{{ forloop.counter0 }},{{ forloop.revcounter }},{{ forloop.first }},{{ forloop.last }}</p>
{% endfor %}
{% if k1 == 'vvvv' %}
<h1>V1</h1>
{% elif k1 == 'v2' %}
<h1>V2</h1>
{% else %}
<h1>7777</h1>
{% endif %}
{% if k1|f3 %}
<h1>True</h1>
{% else %}
<h1>False</h1>
{% endif %}
{{ k1 }}
{{ k1|lower }}
{{ k1|f1:"jason"}}
<br>
{% f2 1 2 3 4 %}
</body>
</html>
template.html
需要注意的tip:
1.filter
限制:传参
支持:模版语言的 if 条件
2.simple_tag
不支持:模版语言的 if 条件
3.模板的继承
首先了解下模板是什么概念?首先已博客园为例:
看下面的图片,在点击首页、精华、候选、新闻、管住、我评、我赞的时候 上面、左侧的红色框体都没有变,变得是中间的内容是怎么实现的呢?就是通过母版来实现的

我们创建一个母版 - 子版去继承母版就可以了,子版里是变化的内容即可。
详见下面的例子
1.母版:layout.html
提别提醒:母版最多允许出现一个母版(可以写多个,但是建议不要写多个)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet" href="..." />
<style>
.pg-header{
height: 48px;
background-color: cadetblue;
}
.pg-body{
min-height: 500px;
}
.pg-body .body-menu{
20%;
float: left;
}
.pg-body .body-content{
80%;
float: left;
}
.pg-footer{
height: 100px;
background-color: brown;
}
.active{
background-color: aquamarine;
color: white;
}
</style>
{% block css %}{% endblock %}#子模板替换的部分
</head>
<body>
<div class="pg-header">
后台系统V1
</div>
<div class="pg-body">
<div class="body-menu">
<ul>
<li><a >用户管理</a></li>
<li><a >资产管理</a></li>
</ul>
</div>
<div class="body-content">
{% block body %}{% endblock %} #此处为子模板替换的部分
</div>
</div>
<div class="pg-footer"></div>
<script src="xxx"></script>
{% block js %}{% endblock %}
</body>
</html>
2.子模板
需要在HTML头部以如下的方式导入母版,有点类似Python导入模块的方式,extends 集成那个模板 ,在加一个block content 来书写变化的内容。
{% extends '母板html文件名' %}
{% block 名称 %}
具体子页面的内容...
{% endblock %}
实例如下:
{% extends 'layout.html' %}
{% block css %}
<style></style>
{% endblock %}
{% block body %}
<ul>
{% for item in user_list %}
<li>{{ item.username }},{{ item.salary }}</li>
{% endfor %}
</ul>
{% endblock %}
{% block js %}
<script>
document.getElementById('userinfo').className = 'active';
</script>
{% endblock %}
3.导入标签
如何在html中导入我们想导入的别人的或定制的标签呢,答案是include方法;

son.html:
<form>
<input />
<input />
<input />
<input />
</form>
include.htm:
{% extends 'master/layout.html' %}
{% block body %}
<table>
{% for item in assets_list %}
<tr>
<td>{{ item.hostname }}</td>
<td>{{ item.port }}</td>
</tr>
{% endfor %}
</table>
{% include 'include/son.html' %}
{% include 'include/son.html' %}
{% include 'include/son.html' %}
{% include 'include/son.html' %}
{% include 'include/son.html' %}
{% include 'include/son.html' %}
<h3></h3>
{% endblock %}
{% block js %}
<script>
document.getElementById('assets').className = 'active';
</script>
{% endblock %}
效果如下:

以后比如某些公共的模块可以使用include的方式导入!很方便
4.Django静态文件配置
把所有的静态都放在static目录下,比如:css、js、imgs、等
配置引入static目录,在settings里,否则无法使用static目录下的静态文件,因为他找不到路径!的需要告诉django
STATIC_URL = '/ff/' #可以自己制定,html引用时要加入此前缀
STATICFILES_DIRS = (
os.path.join(BASE_DIR,'statics'),
)
静态文件目录如下:

html引用方式如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/ff/style/style.css">
{# 然后在模板里,我们也会写一个block,如果子版里有需要使用自己的css样式可以自己定义#}
{% block css %} {% endblock %}
</head>
<body>
<div class="header"><h1>LOGO</h1></div>
<div class="body">
<div class="menu">左侧菜单</div>
<div class="content">
{#可变的子版内容,这个content和class content无关#}
{% block content %} {% endblock %}
</div>
</div>
{# 公共的js写到母版中,如果某一个模板里使用自己的js,在写一个block即可#}
{% block js %} {% endblock %}
</body>
</html>
注:在模板里引入了相应的css和js之后,子版里是默认继承的。如果某个子版想独立使用它自己的js,我们可以通过:{% block css %} {% endblock %} || {% block js %} {% endblock %}来定义!
登录注册实例
1.url
在mysite 这个project下的urls定义路由如下

url(r'^app01/',include('app01.urls')),
在cmdb这个app中urls定义路由如下:
from django.conf.urls import url
from django.contrib import admin
from cmdb import views
urlpatterns = [
url(r'^register/', views.register),
url(r'^login/',views.login),
]
views函数定义如下:
def login(request):
return render(request,'login.html')
html中form表单如何提交的呢?
<form class="form-horizontal" action="/login/" method="post">
提交到在form表单中的action里定义:这里的/login/是URL,当咱们访问URL的时候回给执行咱们定义的函数,前面和后面都要有/ 并且使用方法为post
咱们访问的时候是使用的GET方式,当咱们提交的时候使用的是post请求!我们就可以判断!
def login(request):
#如果是GET请求
#如果是POST,检查用户输入
#print request.method 来查看用户是通过什么方式请求的
#还有个问题:当你POST的时候,会出现问题,现在临时解决方法是:在seetings里注释掉
'''
MIDDLEWARE_CLASSES = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
#'django.middleware.csrf.CsrfViewMiddleware', 注释掉这一行
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
'''
if request.method == 'POST':
input_email = request.POST['email']
input_pwd = request.POST['pwd']
if input_email == 'jason' and input_pwd == '123':
#当登录成功后给它跳转,这里需要一个模块from django.shortcuts import redirect
#成功后跳转到指定网址
return redirect('http://www.baidu.com')
else:
#如果没有成功,需要在页面告诉用户用户名和密码错误.
return render(request,'login.html',{'status':'用户名或密码错误'})
#通过模板语言,来在login.html中添加一个status的替换告诉用户<span>{{ status }}</span>
return render(request,'login.html')
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录</title>
<!--指定告诉ID用高版本的解析-->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<!-- Bootstrap -->
<!-- 新 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="/static/plugins/bootstrap-3.3.4-dist/css/bootstrap.min.css">
</head>
<body>
<div style=" 200px;">
<form class="form-horizontal" action="/login/" method="post">
<div class="form-group">
<label for="inputEmail3" class="col-sm-2 control-label">Email</label>
<div class="col-sm-10">
<input type="email" class="form-control" name="email" placeholder="Email">
</div>
</div>
<div class="form-group">
<label for="inputPassword3" class="col-sm-2 control-label">Password</label>
<div class="col-sm-10">
<input type="password" class="form-control" name="pwd" placeholder="Password">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default">Sign in</button>
<span style="color: red;">{{ status }}</span>
</div>
</div>
</form>
</div>
<!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
<script src="/static/js/jquery-2.2.1.min.js"></script>
<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
<script src="/static/plugins/bootstrap-3.3.4-dist/js/bootstrap.min.js"></script>
</body>
</html>
login.html
$.ajax({
url: '/index/',
type: 'POST',
data: {'username': 'alex','password': '123'},
success: function(data){
// 当后台return之后,该函数自动执行
// data就是后台返回的数据
}
})