Python之django基础
文章目录
一、django必会三板斧
在views.py文件中有这样一行代码
from django.shortcuts import render
1、render方法
- 除request参数外还接受一个待渲染的模板文件和一个保存具体数据的字典参数,将数据填充进模板文件,最后把结果返回给浏览器。
from django.shortcuts import render
def index(request): # 在这里一定要加request参数
print('success')
return render(request,'form.html')
2、HttpResponse方法
- 内部传入一个字符串参数,返回给浏览器。
# HttpResponse方法是返回字符串的方法
from django.shortcuts import render,HttpResponse
def index(request):
print('success')
return HttpResponse('你好 世界!')
3、redirect方法
- 接受一个URL参数,表示跳转到指定的URL
# redirect方法是重定向方法
from django.shortcuts import render,HttpResponse,redirect
def index(requrest):
print('sueecss')
return redirect('http://www.baidu.com') # 也可以跳转至自己编写的方法里 return redirect('/home/')
二、静态文件配置
1、静态文件配置引导
我们将html文件全部都放在templates文件夹下,
将网站所使用的“静态文件”全部都放在static文件夹下
静态文件:前端写好的,能够直接调用使用的文件都可以称之为静态文件
eg:网站写好的js文件,css文件,图片文件及前端框架······
django不会帮我们创建static文件夹,需要我们自己创建(一般来说文件夹名字是叫static)
将bootstrap下载至css文件夹中,并且引入到html文件内。如下代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
{# <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.0.2/css/bootstrap.min.css" rel="stylesheet">#}
{# <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>#}
{# <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.0.2/js/bootstrap.min.js"></script>#}
<link rel="stylesheet" href="../static/css/bootstrap-grid.min.css">
<script src="../static/jquery/jquery.min.js"></script>
<script src="../static/js/bootstrap.min.js"></script>
</head>
<body>
<h1 class="text-center">
登录
</h1>
</body>
</html>
在浏览器中输入url能偶看到对应的资源是因为后端提前开设了该资源的接口
如果访问不到资源 说明后端没有开设该资源的接口
由此可以看出这三个文件均没有被找到,所以就应了上面的那句话,后端就没有开设此资源的接口,那么就扯到配置文件的问题了
2、静态文件配置
# 在django的settings配置文件内进行如下配置
STATIC_URL = '/static/' # 这个static类似于静态文件的令牌
"""
/static/css/bootstrap.min.css
/static/就是STATIC_URL令牌
而css/bootstrap.min.css就是下面代码STATICFILES_DIRS里的static
STATICFILES_DIRS里的是一个列表也就意味着前端文件可以多个
"""
"""如果你想访问静态文件,就必须以static开头,否则就会报错"""
# 添加如下代码
# 静态文件配置 将static文件夹的路径拼接起来
STATICFILES_DIRS = [
os.path.join(BASE_DIR,'static')
]
将上面html文件内的三个网址里的内容下载下来保存到static文件夹的css,js,jquery中,再加上上面的配置代码我们可以得出如下的html文件(为何要下载下来,因为如果说有一天别人的这个cdn网站挂了,那么你不下载下来你的网站也会挂掉)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/static/css/bootstrap.min.css">
<script src="/static/jquery/jquery.min.js"></script>
<script src="/static/js/bootstrap.min.js"></script>
</head>
<body>
<h1 class="text-center" style="color: cyan">
登录
</h1>
</body>
</html>
那么我们思考一下,如果你的templates文件夹里有上千个html文件,这时候产品经理过来了,说:小张啊,我们路由后缀不要加static了
换成666吧,你难道要一个个改?,改一千个???(由此便引出下面的更简洁的代码)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
{% load static %}
<link rel="stylesheet" href="{% static 'css/bootstrap.min.css'%}">
<script src="{% static 'jquery/jquery.min.js' %}"></script>
<script src="{% static 'js/bootstrap.min.js' %}"></script>
</head>
<body>
<h1 class="text-center" style="color: cyan">
登录
</h1>
</body>
</html>
在前端中写上以上代码,便无敌了。以后随便你改STATIC_URL的值,前端后缀都会变成你改过后的
这便是静态文件配置动态解析
三、request对象参数(method,POST,GET)
1、method
print(request.method) # 返回请求方式 并且是全大写的
# 可以根据不同的请求方式来执行不同的代码
eg:
if request.method == 'GET':
# 代码块
print(*****)
return ········
# 代码块
return ···········
2、POST请求
- from.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
{% load static %}
<link rel="stylesheet" href="{% static 'css/bootstrap.min.css'%}">
<script src="{% static 'jquery/jquery.min.js' %}"></script>
<script src="{% static 'js/bootstrap.min.js' %}"></script>
</head>
<body>
<h1 class="text-center" style="color: cyan">
登录
</h1>
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<form action="/index/" method="post">
<p>username:<input type="text" type="text" name="username" class="form-control"></p>
<p>password:<input type="text" type="password" name="password" class="form-control"></p>
<p>
<input type="checkbox" name="hobby" value="1">篮球
<input type="checkbox" name="hobby" value="2">足球
<input type="checkbox" name="hobby" value="3">羽毛球
</p>
<input type="submit" class="btn btn-success ">
</form>
</div>
</div>
</div>
</body>
</html>
- views.py
from django.shortcuts import render,HttpResponse,redirect
# Create your views here.
def index(request):
username = request.POST.get('username')
password = request.POST.get('password')
# hobby = request.method('hobby') # 如果要取的对象是一个列表或字典,元组形式时 get方法不会把全部取出来,只会最后一个
hobby = request.POST.getlist('hobby') # getlist方法会把列表中的所有元素取出来
print(username,type(username)) # xiaozhang <class 'str'>
print(password,type(password)) # 123 <class 'str'>
# print(hobby,type(hobby)) # 3 <class 'str'>
print(hobby,type(hobby)) # ['1', '2', '3'] <class 'list'>
return render(request,'form.html')
3、GET请求
- from.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
{% load static %}
<link rel="stylesheet" href="{% static 'css/bootstrap.min.css'%}">
<script src="{% static 'jquery/jquery.min.js' %}"></script>
<script src="{% static 'js/bootstrap.min.js' %}"></script>
</head>
<body>
<h1 class="text-center" style="color: cyan">
登录
</h1>
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<form action="/index/" method="get">
<p>username:<input type="text" type="text" name="username" class="form-control"></p>
<p>password:<input type="text" type="password" name="password" class="form-control"></p>
<p>
<input type="checkbox" name="hobby" value="1">篮球
<input type="checkbox" name="hobby" value="2">足球
<input type="checkbox" name="hobby" value="3">羽毛球
</p>
<input type="submit" class="btn btn-success ">
</form>
</div>
</div>
</div>
</body>
</html>
- views.py
from django.shortcuts import render,HttpResponse,redirect
# Create your views here.
前端页面展示:http://127.0.0.1:8000/index/?username=zhangbin&password=123&hobby=1&hobby=2&hobby=3
def index(request):
username = request.GET.get('username')
password = request.GET.get('password')
# hobby = request.method('hobby') # 如果要取的对象是一个列表或字典,元组形式时 get方法不会把全部取出来,只会最后一个
hobby = request.GET.getlist('hobby') # getlist方法会把列表中的所有元素取出来
print(username,type(username)) # xiaozhang <class 'str'>
print(password,type(password)) # 123 <class 'str'>
# print(hobby,type(hobby)) # 3 <class 'str'>
print(hobby,type(hobby)) # ['1', '2', '3'] <class 'list'>
return render(request,'form.html')
4、总结
# method方法
request.method # 返回请求方式 并且是全大写的 可以用作判断不同的请求执行不同的代码
# POST请求
request.POST.get() # 获取POST请求中指定参数的值
request.POST.getlist() # 获取POST请求中指定参数列表的值
# GET请求
request.GET.get() # 获取GET请求中指定参数的值
request.GET.getlist() # 获取GET请求中指定参数列表的值
四、Django连接MySQL
当我们创建好django项目后我们会发现在manage.py文件有一个db.splite3 文件,这个文件时django默认自带数据库。由于前期已经装上MySQL 所以我们就链接MySQL数据
其settings原始文件连接数据库内容如下
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
# 这是连接到sqllite3的
将其改为连接MySQL的
1、配置文件中配置
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'zb',
'USER': 'root',
'PASSWORD': '786017877',
'HOST':'127.0.0.1',
'PORT':3306,
'CHARSET': 'utf8',
}
}
2、代码中声明
"""
如果你的django在MySQL数据库设置完成后 再次启动报错那么就是
django默认使用的是mysqldb模块链接MySQL
但是该模块兼容性不好,容易引起版本错乱的问题
需要手动将mysqldb换为pymysql
在项目名目录下__init__.py或者任意应用名下的__init__.py文件下书写以下代码
"""
import pymysql
pymysql.install_as_MySQLdb()
五、django中的ORM
ORM:对象关系映射
将“类”映射为“表”
将”对象“映射为“记录”
将“对象获取属性方法”映射为“记录某个字段对应的值”
操作应用下的models.py 书写如下代码
1、models.py 书写格式
from django.db import models
# Create your models here.
class User(models.Model):
# 创建一个名为id的主键,且是自增的
# id int primary_key auto_increment 等价于这句话
id = models.AutoField(primary_key=True,verbose_name='用户名')
"""
CharFiled方法参数必须指定max_length的值
verbose_name是这个字段名的含义(解释)
"""
# username varchar(64)
username= models.CharField(max_length=64)
# password int
password = models.IntegerField()
2、数据库迁移命令
python manage.py makemigrations # 此命令是将操作记录记录上migrations文件夹中
"""
Migrations for 'app01':
app01\migrations\0001_initial.py
- Create model User
"""
python manage.py migrate # 此命令是将建表数据真正刷到数据库中 会有以下结果
"""
Operations to perform:
Apply all migrations: admin, app01, auth, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying app01.0001_initial... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying sessions.0001_initial... OK
"""
# 这些都是django默认创建的表
只要你修改了model.py中跟数据库相关的代码,就必须重新执行上述代码,没有捷径
3、orm其他操作
- 由于一张表中必须要有一个主键字段,并且一般情况下叫id字段
- 所以在orm中当你不定义主键的时候,orm会帮你自动创建一个名为id的主键字段
- 也就意味着,后续我们在创建模型表的时候如果主键字段名没有额外的叫法 ,那么主键字段可以省略不写
from django.db import models
# Create your models here.
class User(models.Model):
# 创建一个名为id的主键,且是自增的
# id int primary_key auto_increment 等价于这句话
id = models.AutoField(primary_key=True)
# username varchar(64)
username= models.CharField(max_length=64)
# password int
password = models.IntegerField()
class Hobby(models.Model): # 新创建的并没有主键id字段
# username varchar(64)
username = models.CharField(max_length=64)
# hobby varchar(32)
password = models.CharField(max_length=32)
这里也需要重新执行 python manage.py makemigrations 和 python manage.py migrate 这两条命令
此时数据库内增加了一张app01_hobby的表
并且为我们添加了主键id字段
4、字段的增删改查
在操作models.py文件是一定要细心,注意千万不要注释一些字段,检查完毕后再执行数据库迁移命令
# 字段的增加
1、当表中已经存在数据,可以在终端中直接给出默认值
2、在models.py文件中添加字段时可以直接给出null=True
# 该字段可以为空
eg:info = models.CharFiled(max_length=32,verbose_name='个人简介',null=True)
3、给出该字段默认值
eg:hobby = models.CharFiled(max_length=32,verbose_name='兴趣爱好',defult='study')
# 字段的修改
在models.py中找到你要改的类名(表)和属性(字段)直接修改即可,无论是类型和名字都一样。直接修改
注意修改完成后一定要执行迁移数据库的 python manage.py makemigrations 和 python manage.py migrate 两条命令
# 字段的删除
想要删除字段,直接把类里对应的属性(字段)注释掉,在执行数据库迁移两条命令即可。非常简单
但是你删除字段后字段下的所有数据也没了
当你离开你的计算机的时候,一定要锁屏!!!
5、记录的增删改查
- 首先应先创建表与字段
- models.py
from django.db import models
# Create your models here.
class User(models.Model):
"""
User表中的username字段、password字段、register_time字段、is_delete字段
"""
username = models.CharField(max_length=32,verbose_name='用户姓名')
password = models.IntegerField(verbose_name='用户密码')
# DateTimeField(auto_now=True) 默认使用当前时间
register_time = models.DateTimeField(auto_now=True)
is_delete = models.BooleanField(default=False)
def __str__(self):
return self.username
- views.py
from django.shortcuts import render,HttpResponse,redirect
from app01 import models
# Create your views here.
# 登录界面
def init(request):
return render(request,'login.html')
# 注册页面的接口
def register(request):
username = request.POST.get('username')
password = request.POST.get('password')
crete_user_obj= models.User.objects.create(username=username,password=int(password))
if crete_user_obj:
crete_user_obj.save()
# return redirect('/login/')
return render(request,'login.html')
# 登录的页面逻辑判断
def login(request):
username = request.POST.get('username')
password = request.POST.get('password')
int_password = int(password)
login_user_obj = models.User.objects.filter(username=username).first()
print(login_user_obj,type(login_user_obj))
if login_user_obj:
if login_user_obj.password != int_password:
return HttpResponse('登录失败')
return redirect('/user_list/')
return HttpResponse('查无此人')
# 查询所有用户的接口
def user_list(request):
user_list_obj = models.User.objects.all().filter(is_delete='False')
# print(user_list_obj)
# if user_list_obj.is_delete == 'false':
return render(request,'userlist.html',locals())
# 用户修改接口
def edit_user(request):
edit_user_id = request.GET.get('id')
edit_user_obj = models.User.objects.filter(id=edit_user_id).first()
if request.method == 'POST':
edit_username = request.POST.get('username')
edit_password = request.POST.get('password')
obj = models.User.objects.filter(id=edit_user_id).update(username=edit_username,password=edit_password)
return redirect('/user_list/')
return render(request,'edit_user.html',locals())
# 用户删除接口
def delete_user(request):
delete_user_id = request.GET.get('id')
"""
删除的两种方式
"""
# 1、物理删除
# models.User.objects.filter(id=delete_user_id).delete()
# return redirect('/user_list/')
# 2、软删除
models.User.objects.filter(id=delete_user_id).update(is_delete=True)
return redirect('/user_list/')
总结
username = request.POST.get('username')
password = request.POST.get('password')
# 增加数据
# 第一种方法
obj = models.User.objects.create(username=username,password=password)
# 第二种方法
obj = models.User(username=username,password=password)
obj.save()
# 删除数据
# 第一种方法 物理删除
obj = models.User.objects.filter(username=username).delete()
# 第二种方法 软删除
obj = models.User.objects.filter(username=username).update(is_delete=True)
# 修改数据
obj = models.User.objects.filter(username=username).update(age=age)
# 查找数据
# 查找单个
obj = models.User.objects.filter(username=username).all()
# 查找全部
obj = models.User.objects.all()
6、orm多表操作
# 在数据库中多表操作中,表与表存在一对一,一对多,多对多的关系
# 同理在ORM中也有上述操作
"""
此处以“书”,“作者”,“作者详情”及“出版社” 为示例
"""
class book(models.Model):
"""
书和作者是多对多的关系
"""
name = models.CharField(max_length=32,verbose_name='书名')
title = models.CharField(max_length=32,verbose_name='书标题')
# 出版者和书是多对一的关系,可以用外键来代替
pulish = models.ForeignKey(to='pulish')
# 书和作者多对多关系
author = models.ManyToManyField(to='author')
class author(models.Model):
"""
作者
"""
author_name = models.CharField(max_length=32,verbose_name='作者姓名')
# 作者与作者详情是一对一的关系
author_entro = models.OneToOneField(to='author_entros')
class pulish(models.Model):
"""
出版社
"""
pulish_name = models.CharField(max_length=32,verbose_name='出版社名称')
pulish_addr = models.CharField(max_length=32,verbose_name='出版社地址')
pulish_phone = models.CharField(max_length=32,verbose_name='出版社电话')
class author_entros(models.Model):
"""
作者详情
"""
phone = models.BigIntegerField(verbose_name='作者联系方式')
addr = models.CharField(max_length=32,verbose_name='作者住址')
六、django的生命周期图
七、路由层详解
1、有名无名分组
无名分组
"""
分组:分组就是将一段正则表达式用小括号括起来,这便是分组
"""
url(r'^test/(\d+)',views.test)
def test(request,xxx)
print(xxx)
return render(request,'test.html')
# 无名分组就是将括号内的正则表达式,当作位置参数传递给后面的视图函数
有名分组
"""
可以给正则表达式起一个别名
"""
url(r'^testadd/(?P<year>\d+)',views.testadd),
# 有名分组
def testadd(request,year):
print(year)
return HttpResponse('有名分组')
# 有名分组就是将括号内的正则表达式进行命名,并当作关键字参数传递给后面的视图函数
无名分组与有名分组绝对不可以混用
单个分组可以使用多次无论是有名还是无名
2、反向解析
# 通过一些方法得到一个结果 该结果可以直接访问对应url视图函数
# 先给路由与视图函数起别名
url(r'^home/',views.home),
url(r'^func_k/',views.func,name='ooo'),
# 前端做动态绑定
<a href="{% url 'ooo' %}">111</a>
# 后端做动态绑定
from django.shortcuts import render,HttpResponse,redirect,reverse
reverse('ooo')
3、无名有名分组的反向解析
无名分组反向解析
# 路由层
url(r'^home/',views.home),
url(r'^func_k/(\d+)/(\d+)',views.func,name='ooo'), # 给路由起个别名
# 视图层
def index(request):
# 后端的无名分组反向解析必须为args传一个路由层里与正则相符的值,这个值一般是数据的主键值
print(reverse('ooo',args=(123,456, )))
return redirect(request,'333.html')
# 如果说多个无名分组的话参数需要用到*args,单个的是就写args
def home(request,*args):
return HttpResponse('哈哈')
# 模板层
# 同理在前端的无名分组解析里也同样要为大括号里传与正则相符的值,传的值与其他参数以空格隔开,这个值一般是数据的主键值
<a href="{% url 'ooo' 123 456 %}">111</a>
有名分组反向解析
# 路由层
url(r'^home/',views.home),
url(r'^func_k/(?P<year>\d+)/(?P<month>\d+)',views.func,name='ooo'), # 给路由起名
# 视图层
def home(request):
# 后端的有名分组反向解析必须为args传一个路由层里与正则相符的值,这个值一般是数据的主键值
url = reverse('ooo', kwargs={'year':2021,'month':8},) # 最规范的写法
# url = reverse('ooo', args=(2021,8),) # 最便捷的写法
print(url)
return render(request,'222.html')
# 如果说多个有名分组的话参数需要用到**kwargs,单个的是就写分组名字
def func(request,**kwargs):
return HttpResponse('哈哈')
# 模板层
# 同理在前端的有名分组解析里也同样要为大括号里传与正则相符的值,传的值与其他参数以空格隔开,这个值一般是数据的主键值
<a href="{% url 'ooo' year=2021 month=8 %}">111</a> # 最规范的写法
<a href="{% url 'ooo' 2021 8 %}">222</a> # 最便捷的写法
4、路由分发
通常在开发项目中应用经常会很多,各应用路由名称很有可能重复,那么如何区分各应用下面的路由呢
在项目中会有一个urls.py的文件,俗称总路由。在这个文件里书写存放每个应用对应的urls.py
总路由urls.py配置
from django.conf.urls import includ
urlpatterns=[
url(r'^app01/',include('app01.urls')),
url(r'^blog/',include('blog.urls')),
]
在不一样的路由中配置urls.py
# 在app01中,urls.py
url(r'booklist$',views.booklist)
# 在blog中,urls.py
url(r'userlist$',views.userlist)
八、JsonResponse对象
"""
json格式的数据有什么用:
前后端数据交互需要使用json作为过渡,从而实现跨语言传输
"""
# 不用JsonResponse对象向前端返回json格式的数据,如何实现
import json
from django.shortcuts import render,HttpResponse
def json_d(request):
res = {'name':'zb好帅','age':18} # 字典格式
json_res = json.dumps(res,ensure_ascii=False)) # 使用json.dunps转为json格式。并将ensure_ascii改为False,因为有汉字
return HttpResponse(json_res) # 在前端显示出来
# 使用JsonResponse对象向前端返回json格式的数据
from django.http import JsonResponse
def json_j(request):
res = {'name':'zb好帅','age':18} # 字典格式
# return JsonResponse(res) # {"name": "zb\u771f\u5e05", "age": 18} 需要解决unicode码问题
return JsonResponse(res,json_dumps_params={'ensure_ascii':False}) # {"name": "zb真帅", "age": 18} 解决
# 列表能否被序列化(可以)
def list_j(request):
l = [1, 2, 3, 4]
# return JsonResponse(l) # In order to allow non-dict objects to be serialized set the safe parameter to False.
# 为了允许序列化非dict对象,将安全参数设置为False
return JsonResponse(l,safe=False) # [1, 2, 3, 4] 成功
前端的序列化
JSON.stringify()----------------json.dumps()
JSON.parse()--------------------json.loads()
九、request对象的用法(部分)
request.method # 请求方法
request.GET # GET请求方法
request.POST # POST请求方法
request.FILES # 当传输的数据有文件是可以使用request.FILES接受文件数据
request.path # 一个字符串,表示请求的路径组件(不含域名)。 例如:"/music/bands/the_beatles/"
request.path_info # 返回用户访问url,不包括域名
request.get_full_path() # 返回用户访问url,包括域名
request.body # 请求体,byte类型 request.POST的数据就是从body里面提取到的
十、CBV和FBV
# FBV:
def index(request):
pass
# CBV: 根据请求方式区别的
# 前提:继承View
from django.views import View
class Student(View):
http_methods_name = ['get', 'post']
def get(self, request):
pass
def post(self, request):
pass
# 路由
url(r'login/', views.Student.as_view())
url(r'reg/', views.Student.as_view())
十一、模板语法
1、模板传值
{{}}:变量名相关
{% %}:逻辑相关
# views.py
def home(request):
a = {'year':2021,'name':'zb','age':18}
b = 123
c = 13.14
d = True
e = [1,3,2,3]
f = (1,2)
g = 'cvbas'
h = {'哈啊哈','呵呵'}
def func():
return '123'
class Myclass(object):
def get_off(self):
return '111'
@staticmethod
def func():
return '222'
@classmethod
def index(cls):
return '333'
obj = Myclass()
return render(request,'home.html',locals())
# home.html
<p>{{ a }}</p>
<p>{{ b }}</p>
<p>{{ c }}</p>
<p>{{ d }}</p>
<p>{{ e }}</p>
<p>{{ f }}</p>
<p>{{ g }}</p>
<p>{{ h }}</p>
<p>{{ func }}</p> # 传递函数名自动加括号调用,但是模板语法不支持给函数传额外的函数
<p>{{ Myclass }}</p> # 传类名的时候也会自动加括号调用(实例化)
<p>{{ obj }}</p>
<p>{{ obj.get_off }}</p>
<p>{{ obj.func }}</p>
<p>{{ obj.index }}</p>
"""
{'year': 2021, 'name': 'zb', 'age': 18}
123
13.14
True
[1, 3, 2]
(1, 2)
cvbas
{'哈啊哈', '呵呵'}
123
<app01.views.home.<locals>.Myclass object at 0x0000027330E08080>
<app01.views.home.<locals>.Myclass object at 0x0000027330D86FD0>
111
222
333
"""
# django的模板语法取值,有固定的格式只能以“句点符”来取值 .
# home.html
<p>{{ a.keys }}</p> # dict_keys(['year', 'name', 'age'])
<p>{{ a.values }}</p> # dict_values([2021, 'zb', 18])
<p>{{ a.items }}</p> # dict_items([('year', 2021), ('name', 'zb'), ('age', 18)])
a = {'year':2021,'name':'zb','age':18,'hobby':[1,2,3,{'info':4}]}
<p>{{ a.hobby.3.info }}</p> # 4
<p>{{ e.0 }}</p> # 4
# 既可以点键也可以点索引,可以混用
2、模板语法之过滤器
# 过滤器就类似于是模板语法内置的内置方法
# 基本语法
{{ 变量名|过滤器:参数}}
# 常用过滤器
1、length(统计长度过滤器)
{{ g|length }} # 5
2、defult(默认值,如果变量名有值就返回值,没有值就返回default指定的)
{{ d|default:什么}} # True
3、filesizeformat(会把前面的值与1024进行比较计算,从而得出文件大小)
file_size = 12324123
文件大小:{{file_size|filesizeformat}} # 11.8 MB
4、日期格式化
import datetime
time_now = datatimr.datatime.now()
{{time_now}} # 2021年8月13日 19:34 (因为我把TIME_ZONE = 'Asia/Shanghai' LANGUAGE_CODE = 'zh-hans',设置为东八区了所以会显示这种)
{{ time_now|date:'Y-m-d H:i:s' }} # 2021-08-13 19:36:46
5、切片操作(同样支持步长)
{{g|slice:"2:-1"}} # ba
6、safe(可以将带有js或者html格式的字段进行转义)
aa = '<a href="">点我</a>'
{{aa}} # <a href="">点我</a>
{{aa|safe}} # 点我
有些情况下我们不需要转义,例如:当XSS攻击(恶意攻击者在web页面中会插入一些恶意的script代码。)我们的save一遇到便会转义,这不是我们所期望的,所以在使用的时候视情况而定
# 后端的转义
from django.utils.safestring import make_safe
res = make_safe(aa)
7、truncatechars
# 如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾。 参数:截断的字符数
{{ g|truncatechars:4 }} # c...
8、cut (移除value中所有的与给出的变量相同的字符串)
{{ e|cut:'3' }} # [1, , 2]
9、join (拼接)
{{e|join:'$'}} # 1$3$2
10、加法运算(拼接)
{{n|add:10}} # 133
# 字符串也可以拼接
s = 'whd'
{{g|add:s}} # cvbaswhd
3、模板语法之标签
for循环
{% for foo in a %}
{# <p>{{ forloop}}</p>#}
<p>{{ foo }}</p> # 一个个元素
{% empty%}
<p>for循环的可迭代对象内部美哦与元素,根本没法循环,执行此行代码</p>
{% endfor %}
if判断
{% if d %}
<p>haha</p>
{% elif d%}
<p>lolo</p>
{% else %}
<p>xixi</p>
{% endif %}
with语法
# 在with语法内就可以通过as后面的别名快速的使用到前面非常复杂获取数据的方式
{% with a.hobby.3.info as nb %}
<p>{{ nb }}</p>
<p>{{ a.hobby.3.info }}</p>
{% endwith %}
4、模板语法自定义过滤器,标签,inclusion_tag
"""
先三步走
1.在应用下创建一个名字“必须”叫templatetags
2.在该文件夹内创建“任意”名称的py文件 eg:mytag.py
3。在改py文件内“必须”先书写下面两句话
from django import template
register = template.Library()
"""
# templatetags/mytag.py
from django import template
register = template.Library()
# 自定义过滤器(过滤器最多只能给两个参数)
@register.filter(name='qiuhe')
def sum(v1,v2):
return v1+v2
# homl.html
{% load mytag %}
<p>{{ b|qiuhe:90 }}</p> # 213
# 自定义标签
@register.simple_tag(name='bianqian')
def func(a,b,c,d):
return '%s-%s-%s-%s'%(a,b,c,d)
# homl.html
# 标签多个参数彼此之间空格隔开
<p>{% biaoqian '2021' '8' '13' '22'%}</p> # 2021-8-13-22
# 自定义inclusion_tag
"""
内部原理:
先定义一个方法
在X页面上调用该方法,并且可以传值
该方法会生成一些数据然后传递给Y页面
最后将渲染好的Y页面返回到X页面中调用该方法的位置
""" @register.inclusion_tag('left_menu.html')
def index(n):
data = ['这是第{}项'.format(i) for i in n]
return locals()
# left_menu.html
<ul>
{% for foo in data %}
<li>{{ foo }}</li>
{% endfor %}
</ul>
# home.html
{% index a %}
"""
总结:当html页面某一个地方的页面需要传参数才能够动态的渲染出来,并且在多个页面都需要使用到该局部 那么就考虑将该剧页面做成inclusion_tag形式
"""
十二、模板的继承
"""
模板的继承:需要先选好一个你想要继承的文件
"""
{% extends 'xxx.html'%}
"""
继承之后子页面跟模板页面长得一摸一样 你需要在模版页面上提前划定好可以被修改的区域
"""
{% block content %} # content是这块代码的名字,自己可以随便取
模板内容
{% endblock %}
"""
子页面就可以声明想要修改的哪块划定的区域
"""
{% block content %}
子页面内容
{% endblock %}
# 类似于python面向对象的继承,子类继承父类并且子类重写父类中的某一方法
# 一般情况下模板页面上至少可以有三块可以被修改的区域
1、css区域
2、html区域
3、js区域
{% block css %}
{% endblock %}
{% block content %}
{% endblock %}
{% block js %}
{% endblock %}
每个子页面都有自己独立的css代码,html代码,js代码
"""
一般情况下 模板页面上划定的区域越多,那么该模板的扩展性就越高
但是如果太多还不如自己直接写
"""
十三、模板的导入
"""
将页面的摸某一个局部当成模块的形式
哪个地方需要就可以直接导入使用即可
"""
{% inclede 'xxx.html' %}