在 Django 中,模板(Template)是用于生成动态 HTML(或其他格式的文档)的文件,它允许你将数据与 HTML 结构分离,从而实现更好的代码组织和可维护性。
要在django框架中使用模板引擎把视图中的数据更好的展示给客户端,需要完成3个步骤:
配置模板目录:在当前项目根目录下创建了模板目录templates. 然后在settings.py, 模板相关配置,找到TEMPLATES配置项,填写DIRS设置模板目录。
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'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',
],
},
},
]
模板文件:模板文件是包含 HTML 结构和嵌入模板标签的文件。这些模板标签被 Django 解释器识别,并用于插入动态内容和逻辑。通常,模板文件以 .html 扩展名保存,但也可以使用其他扩展名。
模板语言:Django 使用自己的模板语言,其中包含了一系列模板标签和过滤器,用于处理数据、控制流程和生成动态内容。模板语言允许你在模板中插入变量、执行条件判断和循环等操作。
加载模板:在视图函数中,你可以使用 render() 函数来加载和渲染模板。这个函数接受一个请求对象、模板文件的路径和一个上下文字典作为参数,然后将模板渲染为 HTML,并返回一个包含渲染结果的 HttpResponse 对象。
from django.shortcuts import render
def my_view(request):
data = {'name': 'John'}
return render(request, 'my_template.html', context=data)
模板标签:模板标签是以 {% … %} 包围的代码块,用于在模板中执行逻辑控制和循环操作。常见的模板标签包括:
{% for … %} … {% endfor %}:用于循环遍历列表或查询结果。
{% if … %} … {% elif … %} … {% else %} … {% endif %}:用于条件判断。
{% block … %} … {% endblock %}:用于定义和重写块内容。
{% include … %}:用于在模板中包含其他模板。
模板变量:模板变量是以 {{ … }} 包围的代码块,用于插入动态数据到模板中。你可以在模板中使用上下文中的变量,如 {{ name }},以显示用户的名称。
模板过滤器:模板过滤器是可用于修改变量的方法。你可以在变量后面使用管道符 | 来应用过滤器。例如,{{ value|filter_name }}。Django 提供了许多内置过滤器,如 date、truncatechars、lower 等。
模板继承:Django 允许你创建模板的基础布局,并在子模板中继承和扩展它。这可以通过 {% extends … %} 和 {% block … %} 标签来实现。模板继承使你可以重用通用布局,并在不同页面中插入不同的内容。
模板标记:除了模板标签和变量外,你还可以在模板中使用模板标记(Template Tags),这是自定义的模板标签和过滤器。你可以编写自定义模板标记来执行复杂的逻辑操作或呈现特定的内容。
创建文件夹 templatetags (view.py 同级目录,必须是这个名称)
templatetags目录下创建分别创建__init__.py 和 custom_filter.py(可以自定义)
在custom_filter.py 写入如下模板
from django import template
register = template.Library()
# 我这里以自定义电话过滤器举例
@register.filter
def phone_num_filter(value):
# 18720359678 > 187 **** 9678
return f"{value[:3]} **** {value[7:]}"
编写模板文件
开头导入 {% load custom_filter %}
{% load custom_filter %}
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>电话薄title>
head>
<body>
<table border="0" align="center" width="300px;">
<tr>
<th>姓名th>
<th>性别th>
<th>联系方式th>
tr>
{% for p in person_list%}
<tr>
<td>{{ p.name }}td>
<td>{{ p.phone_num | phone_num_filter }}td>
<td>{{ p.sex }}td>
tr>
{% endfor%}
table>
body>
html>
Django 中的中间件是一种机制,用于在请求和响应之间执行额外的处理操作。中间件可以在 Django 处理请求的不同阶段介入,允许你对请求和响应进行修改、记录、验证等操作。
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',
]
中间件可以定义的四个方法,分别是
process_request(self, request)
process_view(self, request, view_func, view_args, view_kwargs)
process_exception(self, request, exception)
process_response(self, request, response)
Django 的 ORM(Object-Relational Mapping)是一个强大的工具,用于将 Python 对象映射到数据库表,允许你使用 Python 代码来执行数据库操作,而不必直接编写 SQL 查询语句。
在 Django 中,数据库表的结构和字段都是通过 Python 类来定义的,这些 Python 类通常称为模型类(Model)。
通过继承 django.db.models.Model 类来创建模型类,并在类中定义表的字段,字段的类型以及其他选项。
需求:通过模型类,生成一个用户表。
字段有:账号、密码、状态、电话、邮箱、创建时间、性别。
from django.db import models
# Create your models here.
class User(models.Model):
STATUS_CHOICES = ((0, '正常'),
(1, '封号'))
GENDER_CHOICES = ((0, '女'),
(1, '男'))
username = models.CharField(max_length=30, null=True)
password = models.CharField(max_length=30, null=True)
status = models.CharField(max_length=1, choices=STATUS_CHOICES, default=0)
gender = models.CharField(max_length=1, choices=GENDER_CHOICES, default=0)
phone = models.CharField(max_length=11)
email = models.EmailField()
created_time = models.DateTimeField(auto_now=True)
class Meta:
db_table = "django_user"
一旦定义了模型类,你可以使用 Django 的 makemigrations 和 migrate 命令来创建和更新数据库表。
python manage.py makemigrations
python manage.py migrate
一旦模型类和数据库表创建好,你可以使用模型类来进行数据库操作,如插入、查询、更新和删除记录。
创建book的模型类,数据迁移生成数据表。
from django.db import models
class Book(models.Model):
id = models.AutoField(primary_key=True, verbose_name="book_id")
title = models.CharField(max_length=32, verbose_name="书名")
author = models.CharField(max_length=10, verbose_name="作者", null=True)
state = models.BooleanField(verbose_name="状态")
published_date = models.DateField(verbose_name="出版时间")
price = models.DecimalField(max_digits=8, decimal_places=2, verbose_name="价格")
publishers = models.CharField(max_length=32, verbose_name="出版商")
class Meta:
db_table = "django_book"
python manage.py makemigrations
python manage.py migrate
这里利用Django中单元测试来说明,生成的数据都是测试数据,不会写入数据库。
在manage.py 文件终端下 运行 python manage.py test app.tests
# -*- coding: utf-8 -*-
from django.test import TestCase
from .models import Book
class BookTestcase(TestCase):
def setUp(self) -> None:
# 添加书籍
# 方式一
book_obj1 = Book.objects.create(
title="雪山大地",
author="杨志军",
state=1,
published_date="2023-02-01",
price=78,
publishers="作家出版社"
)
# 方式二
book_obj2 = Book(
title="寻觅意义",
author="王德峰",
state=1,
published_date="2022-10-01",
price=49.80,
publishers="山东文艺出版社")
book_obj2.save()
def test_book_query(self):
book_result1 = Book.objects.filter(title="雪山大地")
self.assertEqual("杨志军", book_result1.first().author)
book_result2 = Book.objects.filter(title="寻觅意义")
self.assertEqual('王德峰', book_result2.first().author)
# -*- coding: utf-8 -*-
from django.test import TestCase
from .models import Book
class BookTestcase(TestCase):
def setUp(self) -> None:
# 添加书籍
book_data_info = [
{
"title": "寻觅意义",
"author": "王德峰",
"state": 1,
"published_date": "2022-10-01",
"price": 49.80,
"publishers": "山东文艺出版社"
},
{
"title": "国画",
"author": "王跃文",
"state": 1,
"published_date": "2023-06-01",
"price": 69.80,
"publishers": "湖南文艺出版社"
},
{
"title": "鳄鱼",
"author": "莫言",
"state": 1,
"published_date": "2023-06-01",
"price": 99.80,
"publishers": "浙江文艺出版社"
},
{
"title": "长安的荔枝",
"author": "马伯庸",
"state": 1,
"published_date": "2022-10-01",
"price": 66.66,
"publishers": "湖南文艺出版社"
},
]
# 通过解包的方式传入
for book_data in book_data_info:
Book.objects.create(**book_data)
def test_book_query(self):
# 基本查询
book_result1 = Book.objects.filter(title="长安的荔枝")
self.assertEqual("马伯庸", book_result1.first().author)
book_result2 = Book.objects.filter(title="寻觅意义")
self.assertEqual('王德峰', book_result2.first().author)
def test_book_fuzzy_query(self):
# 下划线模糊查询
# 查询价格大于50的书的名称
fuzzy_query_obj1 = Book.objects.filter(price__gt=50)
book_list = []
for f in fuzzy_query_obj1.values():
book_list.append(f.get("title"))
# 验证超过50的数为3本
self.assertEqual(3, len(book_list))
# 查询湖南开头的出版社的数量,验证为2
fuzzy_query_obj2 = Book.objects.filter(publishers__startswith="湖南")
self.assertEqual(2, fuzzy_query_obj2.count())
# -*- coding: utf-8 -*-
from django.test import TestCase
from .models import Book
class BookTestcase(TestCase):
def setUp(self) -> None:
# 添加书籍
book_data_info = [
{
"title": "寻觅意义",
"author": "王德峰",
"state": 1,
"published_date": "2022-10-01",
"price": 49.80,
"publishers": "山东文艺出版社"
},
{
"title": "国画",
"author": "王跃文",
"state": 1,
"published_date": "2023-06-01",
"price": 69.80,
"publishers": "湖南文艺出版社"
},
{
"title": "鳄鱼",
"author": "莫言",
"state": 1,
"published_date": "2023-06-01",
"price": 99.80,
"publishers": "浙江文艺出版社"
},
{
"title": "长安的荔枝",
"author": "马伯庸",
"state": 1,
"published_date": "2022-10-01",
"price": 66.66,
"publishers": "湖南文艺出版社"
},
]
# 通过解包的方式传入
for book_data in book_data_info:
Book.objects.create(**book_data)
def test_book_update(self):
# 更新
# 将鳄鱼这边书的出版时间改为2023-08-01
update_time = "2023-08-01"
Book.objects.filter(title="鳄鱼").update(published_date=update_time)
# 查询是否更新成功
book_publisher_date = Book.objects.filter(title="鳄鱼").first().published_date
self.assertEqual(update_time, str(book_publisher_date))
# -*- coding: utf-8 -*-
from django.test import TestCase
from .models import Book
class BookTestcase(TestCase):
def setUp(self) -> None:
# 添加书籍
book_data_info = [
{
"title": "寻觅意义",
"author": "王德峰",
"state": 1,
"published_date": "2022-10-01",
"price": 49.80,
"publishers": "山东文艺出版社"
},
{
"title": "国画",
"author": "王跃文",
"state": 1,
"published_date": "2023-06-01",
"price": 69.80,
"publishers": "湖南文艺出版社"
},
{
"title": "鳄鱼",
"author": "莫言",
"state": 1,
"published_date": "2023-06-01",
"price": 99.80,
"publishers": "浙江文艺出版社"
},
{
"title": "长安的荔枝",
"author": "马伯庸",
"state": 1,
"published_date": "2022-10-01",
"price": 66.66,
"publishers": "湖南文艺出版社"
},
]
# 通过解包的方式传入
for book_data in book_data_info:
Book.objects.create(**book_data)
def test_book_delete(self):
# 删除
Book.objects.filter(title="长安的荔枝").delete()
# 查询
count = Book.objects.filter(title="长安的荔枝").count()
self.assertEqual(0, count)