PythonWeb框架djiango第二章
文章目录
模版
在前面的案例中,我们都是通过HttpResponse对象来响应用户的请求,同时在响应时返回的是数据,并不是视图,在django中,我们可以定义模版,通过视图函数来为用户响应视图,视图默认定义在templates中,在settings.py中规定了默认查找视图的路径
EMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR / 'templates'] # 这里规定默认在项目的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',
],
},
},
]
方式1(推荐)
定义视图函数
def index(request):
# render的第一个参数必须是request,参数2为响应的视图
return render(request, "index.html")
定义路由
path("",user.userview.index)
定义模版
方式2
def index2(request):
# 通过模版引擎将指定的模版转为html
html = render_to_string("index.html")
# 通过response输出html
return HttpResponse(html)
注意:需要导入reder_to_string
from django.template.loader import render_to_string
render方法详解
def render(
request, template_name, context=None, content_type=None, status=None, using=None
):
"""
Return an HttpResponse whose content is filled with the result of calling
django.template.loader.render_to_string() with the passed arguments.
"""
content = loader.render_to_string(template_name, context, request, using=using)
return HttpResponse(content, content_type, status)
分析:
通过分析发现render方法是render_to_string的封装方式,当前在企业开发过程中采用render方法的比较多,推荐使用。
参数1: request
参数2: 模版名称,
参数3:context ,字典类型,是需要在模版中显示的数据
参数4: content_type可选参数。一个字符串,表示返回的HTTP响应的内容类型(MIME类型)。例如,
'text/html'
、'application/json'
等。如果未提供,Django会根据模板文件的扩展名来猜测内容类型(默认为'text/html'
)参数5: status可选参数。一个整数,表示HTTP响应的状态码。例如,200表示成功,404表示未找到等。如果未提供,Django将使用默认的200状态码。
参数6: using可选参数。一个字符串,表示用于加载模板的模板引擎的别名。如果未提供,Django将使用默认的模板引擎。
ef index(request):
# render的第一个参数必须是request,参数2为响应的视图
# 向作用域中存放id为100,在模版页中通过{{}}来获取数据
context = {"id": 100}
return render(request, "index.html",context = context)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>还原来到python世界</title>
</head>
<body>
<h1>欢迎来到python世界</h1>
<h2>{{ id }}</h2>
</body>
</html>
模版语法
{{contxt中字典的key}}
相等于vue中的文本插值的写法,可以在html任意位置使用
{%%}标签
标签用 {% %}
表示,用于执行一些逻辑操作,如循环、条件判断等
if elif else endif 条件选择
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>还原来到python世界</title>
</head>
<body>
<h1>欢迎来到python世界</h1>
<h2>{{ u_id }}</h2>
{% if u_id > 0 and u_id < 100 %}
<p>The number {{ u_id }} is between 0 and 100.</p>
{% elif u_id > 100 and u_id < 1000 %}
<p>The number {{ u_id }} is between 100 and 1000.</p>
{% else %}
<p>The number {{ u_id }} is not between 0 and 1000.</p>
{% endif %}
</body>
</html>
*注意: 判断时 > <等逻辑运算符要增加空格,否则报错
for
{% for %} 允许我们在一个序列上迭代。
与Python的 for 语句的情形类似,循环语法是 for X in Y ,Y是要迭代的序列而X是在每一个特定的循环中使用的变量名称。
每一次循环中,模板系统会渲染在 {% for %} 和 {% endfor %} 之间的所有内容
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>还原来到python世界</title>
</head>
<body>
<h1>欢迎来到python世界</h1>
<h2>{{ u_id }}</h2>
{% if u_id > 0 and u_id < 100 %}
<p>The number {{ u_id }} is between 0 and 100.</p>
{% elif u_id > 100 and u_id < 1000 %}
<p>The number {{ u_id }} is between 100 and 1000.</p>
{% else %}
<p>The number {{ u_id }} is not between 0 and 1000.</p>
{% endif %}
<br>
<h1>用户列表</h1>
<ul>
{% for user in user_list %}
<li>{{ user.name }}</li>
{% endfor %}
</ul>
<h1>用户列表反向</h1>
<!-- 增加reversed可以对列表进行反向迭代-->
<ul>
{% for user in user_list reversed %}
<li>{{ user.name }}</li>
{% endfor %}
</ul>
</body>
</html>
ef index(request):
# render的第一个参数必须是request,参数2为响应的视图
# 向作用域中存放id为100,在模版页中通过{{}}来获取数据
user_list = []
i = 0
for i in range(10):
user_list.append({"id": i+100, "name": 'admin'+str(i)})
ct = {"u_id": int(request.GET.get("id")), "user_list": user_list}
return render(request, "index.html", ct)
{##}
Django 注释使用 {# #}。
常用标签
- with 在页面中定义变量
- {{url 路由名称}} 一般用在href中 一般用于跳转
url为路由反转的结果
<a href="{%url 路由名称 1%}"> 1为参数
<a href="{%url 路由名称 book_id=1%}"> resful的请求参数
<a href="{%url 路由名称}?id=1==">
过滤器
- add
<h2>{{ u_id|add:10 }}</h2>
-
capfirst
: 将变量的第一个字母转换为大写。{{ value|capfirst }}
如果
value
是 “hello”,那么输出将是 “Hello”。 -
cut
: 从字符串中移除指定的字符。{{ value|cut:" " }}
如果
value
是 “hello world”,那么输出将是 “helloworld”(移除了空格)。 -
date
: 格式化日期/时间值。{{ value|date:"Y-m-d" }}
如果
value
是一个日期对象,那么输出将按照指定的格式显示。 -
length
: 返回字符串、列表等的长度。{{ value|length }}
如果
value
是['a', 'b', 'c']
,那么输出将是 3。 -
lower
: 将字符串转换为小写。{{ value|lower }}
如果
value
是 “HELLO”,那么输出将是 “hello”。 -
upper
: 将字符串转换为大写。{{ value|upper }}
模版结构
{%include “xxx.html”%}
{% include %} 标签允许在模板中包含其它的模板的内容。被引入的模版可以使用父模版中的变量
模版继承
模板可以用继承的方式来实现复用。
接下来我们先创建之前项目的 templates 目录中添加 base.html 文件,代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>这是父模版</h1>
<h2>模版继承测试</h2>
{% block main %}
<p>这是模版内容</p>
{% endblock %}
</body>
</html>
以上代码中,名为 main 的 block 标签是可以被继承者们替换掉的部分。
所有的 {% block %} 标签告诉模板引擎,子模板可以重载这些部分。
hello.html 中继承 base.html,并替换特定 block,hello.html 修改后的代码如下
{% extends 'base.html' %}
{% block main %}
我是来自父模版的 {{ block.super }}
<a href="base.html">百度</a>
{% endblock %}
静态文件
官网:https://docs.djangoproject.com/en/5.1/intro/tutorial06/
-
配置静态文件设置:
在settings.py
文件中,确保你已经配置了静态文件的设置。这包括STATIC_URL
和STATICFILES_DIRS
。# settings.py STATIC_URL = '/static/' # URL前缀,用于访问静态文件 STATICFILES_DIRS = [ BASE_DIR / "static", # 静态文件的目录,可以包含多个目录 ]
BASE_DIR
是Django自动生成的,指向你的项目根目录。 -
创建静态文件目录:
在你的项目根目录下创建一个名为static
的文件夹(如果你的配置与上述示例一致)。然后,你可以在这个文件夹下组织你的静态文件,比如CSS、JavaScript和图片等。 -
在模板中加载静态文件:
在你的Django模板中,使用{% load static %}
模板标签来加载静态文件。然后,使用{{ static 'path/to/your/file' }}
来获取静态文件的URL。
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="{% static 'css/index.css' %}">
</head>
<body>
<h1>这是父模版</h1>
<h2>模版继承测试</h2>
{% block main %}
<p>这是模版内容</p>
{% endblock %}
</body>
</html>
在settings.py中增加
"""
Django settings for djangoProject project.
Generated by 'django-admin startproject' using Django 4.2.16.
For more information on this file, see
https://docs.djangoproject.com/en/4.2/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/4.2/ref/settings/
"""
from pathlib import Path
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-@7y-i+smm-9vt#_h)1e5*r78(5@wfr6w!x_5+&17&3q&^xpq%w'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
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',
]
ROOT_URLCONF = 'djangoProject.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [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',
],
# 增加builtins可以在页面中去除`{%load static%}`
'builtins': ['django.templatetags.static']
},
},
]
WSGI_APPLICATION = 'djangoProject.wsgi.application'
# Database
# https://docs.djangoproject.com/en/4.2/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
# Password validation
# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/4.2/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.2/howto/static-files/
STATIC_URL = '/static/'
STATICFILES_DIRS = [
BASE_DIR / "static", # 静态文件的目录,可以包含多个目录
]
# Default primary key field type
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
模型
模型安装和配置
-
安装PyMySQL
(推荐用于Django项目,因为它是一个纯Python实现的MySQL客户端,兼容性好且易于安装):
-
你可以通过pip来安装PyMySQL:
pip install pymysql
-
-
在Django设置中使用PyMySQL:
-
安装完PyMySQL后,你需要在Django的设置文件中(通常是settings.py
)添加以下代码来告诉Django使用PyMySQL作为其数据库后端:
import pymysql pymysql.install_as_MySQLdb()
-
确保你的
DATABASES
配置指向你的MySQL数据库。
-
-
python manage.py startapp appname
创建app
- 修改settings中的数据源的配置
ATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'db_python',
'USER': 'root',
'HOST': '127.0.0.1',
'PASSWORD': 'xxx',
'PORT': '3306'
}
}
- 将app引入到模块中
NSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'dept'
]
- 创建模型
from django.db import models
# Create your models here.
class DeptModel(models.Model):
name = models.CharField(max_length=20)
sex = models.IntegerField(default=0)
class RoleModel(models.Model):
name = models.CharField(max_length=20)
flag = models.IntegerField(default=0)
python manage.py makemigrations dept
通知django模型有修改,执行完成后在migration文件夹下生成变更记录
python manage.py migrate dept
生成数据库中对应的表
单表crud
from django.shortcuts import render,HttpResponse
from .models import DeptModel
import json
# Create your views here.
# 创建DeptModel对象,默认包含了所有参数的构造方法,通过模型的save方法保持数据 相等于执行insert语句
def add_dept(request):
dept = DeptModel(name='部门1', sex=1)
dept.save()
return HttpResponse('保持成功')
# all()相等于执行select * from ,返回集合
def dept_query(request):
depts = DeptModel.objects.all();
print(type(depts))
for dept in depts:
print(dept.id, dept.name, dept.sex)
return HttpResponse('查询成功')
# 根据id查询单个对象,get返回对象
def dept_query_one(request):
# 获取单个对象,如果没有查询到对象,跑出异常,一般用户登录,通过try except来处理
dept = DeptModel.objects.get(id=1)
print(dept.id, dept.name, dept.sex)
# 获取到集合 ,集合长度为1
dept = DeptModel.objects.filter(id=1)
print(dept)
return HttpResponse('success')
# 更新
def dept_update(request):
dept = DeptModel.objects.get(id=1)
dept.name='helloWorld'
dept.save()
return HttpResponse('success')
# 删除
def dept_delete(request):
dept = DeptModel.objects.get(id=2)
dept.delete()
return HttpResponse('success')
Meta
用于配置模型的其他信息
table_name: 指定模型对应的数据的名称
Field API
字段类 | 默认小组件 | 说明 |
---|---|---|
AutoField | N/A | 根据 ID 自动递增的 IntegerField |
BigIntegerField | NumberInput | 64 位整数,与 IntegerField 很像,但取值范围是 -9223372036854775808 到 9223372036854775807 。 |
BinaryField | N/A | 存储原始二进制数据的字段。只支持 bytes 类型。注意,这个字段的功能有限。 |
BooleanField | CheckboxInput | 真假值字段。如果想接受 null 值,使用 NullBooleanField 。 |
CharField | TextInput | 字符串字段,针对长度较小的字符串。大量文本应该使用 TextField 。有个额外的必须参数:max_length ,即字段的最大长度(字符个数)。 |
DateField | DateInput | 日期,在 Python 中使用 datetime.date 实例表示。有两个额外的可选参数: auto_now ,每次保存对象时自动设为当前日期 auto_now_add ,创建对象时自动设为当前日期。 |
DateTimeField | DateTimeInput | 日期和时间,在 Python 中使用 datetime.datetime 实例表示。与 DateField 具有相同的额外参数。 |
DecimalField | TextInput | 固定精度的小数,在 Python 中使用 Decimal 实例表示。有两个必须的参数: max_digits 和 decimal_places 。 |
DurationField | TextInput | 存储时间跨度,在 Python 中使用 timedelta 表示。 |
EmailField | TextInput | 一种 CharField ,使用 EmailValidator 验证输入。max_length 的默认值为 254 。 |
FileField | ClearableFileInput | 文件上传字段。详情见下面。 |
FilePathField | Select | 一种 CharField ,限定只能在文件系统中的特定目录里选择文件。 |
FloatField | NumberInput | 浮点数,在 Python 中使用 float 实例表示。注意, field.localize 的值为 False 时,默认的小组件是 TextInput 。 |
ImageField | ClearableFileInput | 所有属性和方法都继承自 FileField ,此外验证上传的对象是不是有效的图像。增加了 height 和 width 两个属性。需要 Pillow 库支持。 |
字段选项
- 通过字段选项,可以实现对字段的约束
- 在字段对象时通过关键字参数指定
- null:如果为True,Django 将空值以NULL 存储到数据库中,默认值是 False
- blank:如果为True,则该字段允许为空白,默认值是 False
- 对比:null是数据库范畴的概念,blank是表单验证证范畴的
- db_column:字段的名称,如果未指定,则使用属性的名称
- db_index:若值为 True, 则在表中会为此字段创建索引
- default:默认值
- primary_key:若为 True, 则该字段会成为模型的主键字段
- unique:如果为 True, 这个字段在表中必须有唯一值
外键ForeignKey
参数1: 关联的外键对应的模型名称,如果是不同app下,需要appname.模型名称
参数2: on_delete 级连删除策略
参数3:related_name 反向调用的属性名,默认是小写的模型名_set.all()可以获取全部,也可以过滤
from django.db import models
# Create your models here.
class DeptModel(models.Model):
name = models.CharField(max_length=20)
sex = models.IntegerField(default=0)
class RoleModel(models.Model):
name = models.CharField(max_length=20)
flag = models.IntegerField(default=0)
class UserModel(models.Model):
name = models.CharField(max_length=200)
pwd = models.CharField(max_length=200)
real_name = models.CharField(max_length=200)
# 外键定义 可以实现以对多
dept = models.ForeignKey("DeptModel", on_delete=models.CASCADE)
# 喜能
def foreign_add(request):
dept = DeptModel(name='测试部门1', sex=1)
dept.save()
user = UserModel(name='user1', pwd='password1', real_name='用户1')
user.dept = dept
user.save()
return HttpResponse('success')
# 查询用户并关联显示部门
def query_user_dept(request):
user = UserModel.objects.get(id=1)
dept = user.dept
print(dept)
return HttpResponse('success')
# 反向关联查询
def query_dept_users(request):
dept = DeptModel.objects.get(id=6)
# print(dept.query)
# 写法一,users是related_name定义的值
# users = dept.users.all()
# 如果realted_namem没有定义值,可以使用默认的模型名首字母小写_set
# 注意这里模型不能大写 UserModel_set报错,必须是usermodel_set
users = dept.usermodel_set.all()
print(users)
for user in users:
print(user.id,user.name,user.real_name)
return HttpResponse('success')
一对一 OneToOneField
class UserDetailModel(models.Model):
address = models.CharField(max_length=200)
user = models.OneToOneField("UserModel",on_delete=models.CASCADE)
# 根据userid获取明细信息
def one_to_none_get(request):
user_detail = UserDetailModel.objects.get(id=1)
print(user_detail.user.name)
user = UserModel.objects.get(id=4)
detail = user.userdetailmodel
print(str(detail.address))
return HttpResponse('success')
多对多ManyToManyField
def many_to_many_get(request):
user = UserModel.objects.get(id=6)
roles = user.roles.all()
print(len(roles))
role = RoleModel.objects.get(id=12)
users = role.users.all()
print(len(users))
return HttpResponse('success')
# 保存多对多的数据
def one_to_noe_save(request):
dept = DeptModel(name='odept')
dept.save()
user = UserModel(name='oneToOne',pwd='oneTowo')
user.dept = dept
role = RoleModel(name='role111')
role.save()
roles =set()
roles.add(role)
role2 = RoleModel(name='role222')
role2.save()
roles.add(role2)
user.save()
# 必须先保存role和user
user.roles.add(role, role2)
return HttpResponse('success')