文章目录:
参考:
官方文档 Django 文档 | Django documentation | Django
菜鸟教程 Django 教程 | 菜鸟教程
哔哩哔哩
安装
直接pip install django
常用命令
创建项目:使用Pycharm Pro 或 django-admin startproject ProjectName
启动服务:python manage.py runserver 8000
创建应用:python manage.py startapp appName
创建管理员:python manage.py createsuperuser
生成迁移文件:python manage.py makemigrations
应用迁移:python manage.py migrate
简介
Django是一种Web开发框架,遵从MTV(Model-Template-View)原则。
Model负责与数据库交互,在model.py中可以配置数据的结构、类型、相关函数。
View为视图,用户访问URL时会被urls.py映射到对应的View中,View内部调用Model进行数据的处理、数据库操作等,可以将数据传递到模板当中。
Template为模板,一般使用HTML+CSS+JS+Django中特定的规则完成,接受View传递的数据,渲染为HTML,显示在前端。
项目结构
一般主项目需要修改的只有settings.py的简单配置,和urls.py里面的路由配置。
创建应用后,应用下的结构:
myapp/
│
├── migrations/
│ └── __init__.py
├── __init__.py
├── admin.py
├── apps.py
├── models.py
├── tests.py
├── urls.py
└── views.py
// From 菜鸟教程models.py定义数据模型,views.py处理业务逻辑,admin.py配置管理后台,有时候会把路由映射放到应用中处理,再创建一个urls.py。
模板
Django的模板有变量渲染、逻辑控制、模板继承、静态文件、自定义过滤器等功能。
需要先向Django说明模板文件的路径,将TEMPLATES中的 DIRS 为 [BASE_DIR / "templates"]。views.py中使用render函数作为响应,如:
from django.shortcuts import render
def runoob(request):
context = {}
context['hello'] = 'Hello World!'
return render(request, 'runoob.html', context)使用字典context作为参数,键值hello对应模板中变量{{ hello }}
变量
view:{"HTML变量名" : "值"}# 使用字典传输
HTML:{{变量名}}如上文可以使用<p>{{ hello }}</p>可以打印Hello World!。
列表
使用.索引下标可以取出对应列表中的元素。
如views.py:
from django.shortcuts import render
def runoob(request):
views_list = ["菜鸟教程1","菜鸟教程2","菜鸟教程3"]
return render(request, "runoob.html", {"views_list": views_list})templates/runoob.html:
<p>{{ views_list }}</p> # 取出整个列表
<p>{{ views_list.0 }}</p> # 取出列表的第一个元素字典
可以用 .键 取出对应的值。如:
from django.shortcuts import render
def runoob(request):
views_dict = {"name":"菜鸟教程"}
return render(request, "runoob.html", {"views_dict": views_dict})<p>{{ views_dict }}</p>
<p>{{ views_dict.name }}</p>过滤器
相当于一种非常便捷的库函数,可以用于处理字符串等数据。模板语法:
{{ 变量名 | 过滤器:可选参数 }}过滤器可以被套接,一个过滤器管道的输出可以作为下一个管道的输入。如:
{{ my_list|first|upper }}以下是一些常用的过滤器:
default
default 为变量提供一个默认值。
如果 views 传的变量的布尔值是false,则使用指定的默认值。以下值都是false:
0 0.0 False 0j "" [] () set() {} None实际应用如:
from django.shortcuts import render
def runoob(request):
name =0
return render(request, "runoob.html", {"name": name}){{ name|default:"菜鸟教程666" }}length
返回对象的长度,适用于字符串和列表。
字典返回的是键值对的数量,集合返回的是去重后的长度。
from django.shortcuts import render
def runoob(request):
name ="菜鸟教程"
return render(request, "runoob.html", {"name": name}){{ name|length}}filesizeformat
以更易读的方式显示文件的大小(即'13 KB', '4.1 MB', '102 bytes'等)。
字典返回的是键值对的数量,集合返回的是去重后的长度。
{{ num|filesizeformat}}date
根据给定格式对一个日期变量进行格式化。
格式Y-m-d H:i:s返回 年-月-日 小时:分钟:秒 的格式时间。
{{ time|date:"Y-m-d" }}truncatechars
如果字符串包含的字符总个数多于指定的字符数量,那么会被截断掉后面的部分。截断的字符串将以 ... 结尾。
{{ views_str|truncatechars:2}}标签
标签使用 {% %}的格式。
上面都是对数据进行处理,下面是一些逻辑的语句:
if/else 标签
基本语法格式:
{% if condition1 %}
... display 1
{% elif condition2 %}
... display 2
{% else %}
... display 3
{% endif %}根据条件判断是否输出。if/else 支持嵌套。
{% if %}标签接受 and , or 或者 not 关键字来对多个变量做判断 ,或者对变量取反(not)。
for标签
与 Python 的 for 语句的情形类似,循环语法是 for X in Y ,Y 是要迭代的序列而 X 是在每一个特定的循环中使用的变量名称。
每一次循环中,模板系统会渲染在{% for %}和 {% endfor %}之间的所有内容。
如遍历athlete_list:
<ul>
{% for athlete in athlete_list %}
<li>{{ athlete.name }}</li>
{% endfor %}
</ul>在标签中可以通过{{forloop.xxxx}}获取循环序号:
- forloop.counter: 顺序获取循环序号,从 1 开始计算
- forloop.counter0: 顺序获取循环序号,从 0 开始计算
- forloop.revcounter: 倒序获取循环序号,结尾序号为 1
- forloop.revcounter0: 倒序获取循环序号,结尾序号为 0
- forloop.first(一般配合if标签使用): 第一条数据返回 True,其他数据返回 False
- forloop.last(一般配合if标签使用): 最后一条数据返回 True,其他数据返回 False
{% empty %}:再循环为空时执行(即 in 后面的参数布尔值为 False )。如下所示:
from django.shortcuts import render
def runoob(request):
views_list = []
return render(request, "runoob.html", {"listvar": views_list}){% for i in listvar %}
{{ forloop.counter0 }}
{% empty %}
空空如也~
{% endfor %}配置静态文件
1、在项目根目录下创建 statics 目录。
2、在 settings 文件的最下方配置添加以下配置:
STATIC_URL = '/static/' # 别名
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "statics"),
]3、在 statics 目录下创建 css 目录,js 目录,images 目录,plugins 目录, 分别放 css文件,js文件,图片,插件。
4、把 bootstrap 框架放入插件目录 plugins。
5、在 HTML 文件的 head 标签中引入 bootstrap。
<link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7/dist/css/bootstrap.css">
此时需要使用别名,而不是真实路径statics,这样做方便修改外部访问路径而不需要修改真实位置,且对于真实路径也有保护。
在模板中使用需要加入 {% load static %} 代码,模板标签{% static '...' %},其中的点为相对于static目录的相对路径,以下实例我们从静态目录中引入图片。
from django.shortcuts import render
def runoob(request):
name ="菜鸟教程"
return render(request, "runoob.html", {"name": name}){% load static %}
{{name}}<img src="{% static 'images/runoob-logo.png' %}" alt="runoob-logo">模板继承
模板可以用继承的方式来实现复用,减少冗余内容。
网页的头部和尾部内容一般都是一致的,我们就可以通过模板继承来实现复用。
父模板用于放置可重复利用的内容,子模板继承父模板的内容,并放置自己的内容。
父模板
{% block 名称 %}
预留给子模板的区域,可以设置设置默认内容
{% endblock 名称 %}子模板
{% extends "父模板路径"%} ]
{ % block 名称 % }
内容
{% endblock 名称 %}如下面的示例:
base.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
</head>
<body>
<h1>Hello World!</h1>
<p>菜鸟教程 Django 测试。</p>
{% block mainbody %}
<p>original</p>
{% endblock %}
</body>
</html>index.html
{%extends "base.html" %}
{% block mainbody %}
<p>继承了 base.html 文件</p>
{% endblock %}模型
直接使用SQLite数据库。
模型配置
模型在Model/models.py中配置。
首先需要引入库 from django.db import models
定义表:
class Book(models.Model):
name = models.CharField(max_length=20)models.Model是统一继承的类,后面的CharField是变量类型,后面括号的max_length=为可选择的参数。
常用的变量类型和参数:
| 字段类型 | 描述 | 示例 |
|---|---|---|
AutoField | 自增整数主键,通常用于ID字段 | id = models.AutoField(primary_key=True) |
BigAutoField | 大整数自增主键,适用于需要很大id的表 | id = models.BigAutoField(primary_key=True) |
IntegerField | 普通整数 | age = models.IntegerField() |
BigIntegerField | 大整数 | big_num = models.BigIntegerField() |
PositiveIntegerField | 非负整数 | score = models.PositiveIntegerField() |
PositiveSmallIntegerField | 非负小整数 | small_num = models.PositiveSmallIntegerField() |
SmallIntegerField | 小整数 | small_num = models.SmallIntegerField() |
FloatField | 浮点数 | price = models.FloatField() |
DecimalField | 定点数(需要指定max_digits和decimal_places) | cost = models.DecimalField(max_digits=5, decimal_places=2) |
CharField | 字符串,需要指定max_length | name = models.CharField(max_length=100) |
TextField | 长文本,不限制长度 | description = models.TextField() |
BooleanField | 布尔值 | is_active = models.BooleanField(default=True) |
NullBooleanField(废弃) | 可空布尔值 Django3.1后移除 | 改用 BooleanField(null=True) |
DateField | 日期 | birthday = models.DateField() |
DateTimeField | 日期时间 | created_at = models.DateTimeField(auto_now_add=True) |
TimeField | 时间 | start_time = models.TimeField() |
DurationField | 时间间隔 | duration = models.DurationField() |
EmailField | 邮箱格式字符串 | email = models.EmailField() |
URLField | URL格式字符串 | website = models.URLField() |
FileField | 文件上传字段 | upload = models.FileField(upload_to='uploads/') |
ImageField | 图片上传字段,需要Pillow库 | photo = models.ImageField(upload_to='photos/') |
ForeignKey | 外键,关联另一模型 | author = models.ForeignKey(User, on_delete=models.CASCADE) |
OneToOneField | 一对一字段 | profile = models.OneToOneField(Profile, on_delete=models.CASCADE) |
ManyToManyField | 多对多字段 | tags = models.ManyToManyField(Tag) |
| 参数名 | 描述 | 示例 |
|---|---|---|
null | 是否允许在数据库存储NULL(不等同于空字符串) | null=True |
blank | 是否允许该字段在Django表单中留空(字段验证时是否必填) | blank=True |
default | 字段默认值 | default=0 |
primary_key | 是否为主键字段 | primary_key=True |
unique | 是否唯一(数据库层面唯一索引) | unique=True |
choices | 限制字段的可选值,传入tuple列表 | status = models.CharField(max_length=2, choices=STATUS_CHOICES) |
max_length | 最大长度,仅对CharField和TextField(部分字段)适用 | max_length=255 |
db_index | 是否建立数据库索引 | db_index=True |
editable | 是否在admin或modelform中编辑 | editable=False |
verbose_name | 字段的人类可读名称 | verbose_name='用户名' |
help_text | 字段帮助信息 | help_text='请输入用户名' |
auto_now | 设为True时自动设置当前时间戳(每次更新记录时) | auto_now=True |
auto_now_add | 设为True时自动设置创建时间戳(只在记录创建时设置) | auto_now_add=True |
upload_to | 文件/图片上传字段,指定文件存储目录 | upload_to='photos/%Y/%m/%d' |
on_delete | 外键关联对象被删除时的行为 | on_delete=models.CASCADE |
常用的外键on_delete选项:
| 选项 | 含义 |
|---|---|
models.CASCADE | 级联删除,关联对象删除了,当前对象也删除 |
models.PROTECT | 禁止删除关联对象,抛出异常 |
models.SET_NULL | 关联对象删除时,把外键字段置为 NULL |
models.SET_DEFAULT | 关联对象删除时,把外键字段设为默认值 |
models.SET(...) | 关联对象删除时,把外键字段设为指定的值 |
models.DO_NOTHING | 什么都不做,数据库会报错(不推荐) |
数据库操作
首先都需要从模型文件中引入类,如:from TestModel.models import Test
增
def adddb(request):
test1 = Test(name='nantong')
test1.save()删
def testdb(request):
# 删除id=1的数据
test1 = Test.objects.get(id=1)
test1.delete()
# 另外一种方式
Test.objects.filter(id=1).delete()
# 删除所有数据
Test.objects.all().delete()改
def testdb(request):
# 修改其中一个id=1的name字段,再save
test1 = Test.objects.get(id=1)
test1.name = 'Google'
test1.save()
# or
Test.objects.filter(id=1).update(name='Google')
# 修改所有的列
Test.objects.all().update(name='Google')查
def testdb(request):
# 初始化
response = ""
response1 = ""
# 通过objects这个模型管理器的all()获得所有数据行,相当于SQL中的SELECT * FROM
listTest = Test.objects.all()
# filter相当于SQL中的WHERE,可设置条件过滤结果
response2 = Test.objects.filter(id=1)
# 获取单个对象
response3 = Test.objects.get(id=1)
# 限制返回的数据 相当于 SQL 中的 OFFSET 0 LIMIT 2;
Test.objects.order_by('name')[0:2]
#数据排序
Test.objects.order_by("id")
# 上面的方法可以连锁使用
Test.objects.filter(name="runoob").order_by("id")所有常用的函数
.all()
返回所有记录的 QuerySet(类似列表,但是惰性查询,可链式调用)
resources = Resource.objects.all().filter(**kwargs)
过滤数据,返回满足条件的 QuerySet。kwargs 是字段名+条件,支持双下划线查询。
# 查找状态是 normal 的
qs = Resource.objects.filter(status="normal")
# 查找标题包含 "python" 的(不区分大小写)
qs = Resource.objects.filter(title__icontains="python")
# 过滤上传者为当前用户,且状态不是 removed
qs = Resource.objects.filter(uploader=request.user).exclude(status="removed")
# 多条件“且”关系,会默认 AND
qs = Resource.objects.filter(status="normal", file_type="pdf").exclude(**kwargs)
排除满足条件的记录,返回其余记录。
qs = Resource.objects.exclude(status="removed").get(**kwargs)
获取唯一一条符合条件的记录。如果没有或者多于一条,会抛出异常。
res = Resource.objects.get(pk=1)一般搭配 try...except 使用。
.order_by(*fields)
排序。字段名前加 - 表示倒序。
res = Resource.objects.all().order_by("-created_at") # 按创建时间倒序.values(*fields)和.values_list(*fields, flat=False)
只查询部分字段,用于优化性能。
names = Resource.objects.values_list("title", flat=True) # 只要标题列表
data = Resource.objects.values("id", "title") # 返回字典列表 [{id:1,title:"..."}, ...].first()和.last()
拿 QuerySet 的第一条/最后一条数据,方便快捷。可能返回 None。
res = Resource.objects.filter(status="normal").first().count()
统计符合条件的数据数量。
count = Resource.objects.filter(status="normal").count().exists()
判断符合条件的记录是否存在,效率高。
has_pdf = Resource.objects.filter(file_type="pdf").exists().update(**kwargs)
一次批量更新符合条件的记录,不会触发 save() 方法。
Resource.objects.filter(status="pending").update(status="removed").create(**kwargs)
创建并保存一条新记录,快捷写法。
Resource.objects.create(title="新资源", uploader=request.user, status="normal").update_or_create(defaults=None, **kwargs)
尝试查找满足条件的记录,有则更新,没有则创建。
obj, created = Resource.objects.update_or_create(
file_hash="xxx123",
defaults={"title": "新标题", "status": "normal"},
).get_or_create(defaults=None, **kwargs)
查找是否存在满足条件的对象,没有则创建,返回对象和是否创建标志。
obj, created = Resource.objects.get_or_create(title="Unique title",
defaults={"status": "normal"}).aggregate()和.annotate()
用于聚合查询,比如计数、求和、最大值等。需要导入 django.db.models 中的聚合函数。
from django.db.models import Count, Sum
# 统计所有资源的总下载次数
total_downloads = Resource.objects.aggregate(total=Sum("downloads"))["total"]
# 给每个上传者统计上传资源数
users = User.objects.annotate(resource_count=Count("resource"))- 复杂查询 - 使用
Q()对象
实现 “或” 逻辑或复杂逻辑。
from django.db.models import Q
qs = Resource.objects.filter(Q(title__icontains="python") | Q(summary__icontains="python"))表单
Django的表单功能通过django.forms提供,可以渲染HTML表单,自动生成网页上的表单数据;验证用户的输入是否符合要求;获取清洗后的数据,将用户输入转化为Python数据类型;关联数据类型,把表单和数据库模型相关联。
HTTP请求
GET:请求服务器数据,请求数据附加在URL后面
POST:提交数据在请求体中
基本用法
创建一个表单类:一般在forms.py中,比如下面这个联系人表单类
from django import forms
class ContactForm(forms.Form):
name = forms.CharField(label='你的名字', max_length=100)
email = forms.EmailField(label='邮箱')
message = forms.CharField(label='留言', widget=forms.Textarea)视图中显示表单:views.py
from django.shortcuts import render
from .forms import ContactForm
def contact_view(request):
if request.method == 'POST':
form = ContactForm(request.POST) # 带数据实例化表单,准备验证
if form.is_valid(): # 验证表单数据
# 获取表单清洗后的数据
name = form.cleaned_data['name']
email = form.cleaned_data['email']
message = form.cleaned_data['message']
# TODO: 处理数据,如保存或发送邮件
return render(request, 'thanks.html', {'name': name})
else:
form = ContactForm() # 空表单实例
return render(request, 'contact.html', {'form': form})
模板中渲染表单:contact.html
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">提交</button>
</form>- 使用
{{ form.as_p }}简便地渲染整个表单(每个字段占用一个<p>标签)。 {% csrf_token %}是Django防跨站请求伪造的安全措施,必须添加。
ModelForm
如果已经定义好了模型,那么可以使用ModelForm简化模型相关表单。
假设你有一个models.py:
from django.db import models
class Article(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()创建对应的表单:
# forms.py
from django.forms import ModelForm
from .models import Article
class ArticleForm(ModelForm):
class Meta:
model = Article
fields = ['title', 'content'] # 指定需要包含的字段Meta类是写在ModelForm内部的用来配置表单行为的类。model:指定对应的模型。- 字段
fields:指定哪些模型字段需要包含进表单,可以用fields = '__all__'表示全部字段,也可以用exclude = ['price']排除字段,但二者不能同时出现。 字段
labels:指定变量对应的标签,如labels = { 'title': '书名', 'author': '作者', }字段
help_texts:在输入栏里面的提示help_texts = { 'published_date': '格式:YYYY-MM-DD', }字段
error_messages:出错时对应的提示error_messages = { 'price': { 'required': '请填写价格', 'invalid': '请输入有效数字', }, }- 同时也可以在
class Meta外自定义表单字段,如果出现同名则会覆盖模型中的同名字段。 Django的Form字段都会默认选择HTML控件,但我们常需要自定义控件和样式。如:
from django import forms class BookForm(ModelForm): class Meta: model = Book fields = '__all__' widgets = { 'published_date': forms.DateInput(attrs={'type': 'date'}), 'price': forms.NumberInput(attrs={'step': '0.01'}), }这段代码给
published_date使用HTML5的type="date"控件,price控制小数步长。控件名称 描述 生成的HTML标签 forms.TextInput单行文本输入框 <input type="text">forms.PasswordInput密码输入框(输入时显示点) <input type="password">forms.EmailInput邮箱输入框(浏览器会简单验证格式) <input type="email">forms.NumberInput数字输入框 <input type="number">forms.DateInput日期输入框 <input type="date">(现代浏览器支持日期选择器)forms.Textarea多行文本输入框 <textarea></textarea>forms.Select下拉选择框 <select></select>forms.CheckboxInput复选框 <input type="checkbox">forms.ClearableFileInput文件上传控件 <input type="file">其中的
attrs参数用于给HTML标签添加属性,常用属性:class: 给元素指定CSS样式类名,便于页面样式美化placeholder: 输入框内的灰色提示文字(用户输入前显示)type: HTML5用来指定控件类型,比如type="date"表示日期选择器rows,cols: 针对多行输入框的行数和宽度readonly: 只读属性,用户不可修改style: 也可以直接写CSS样式,比如style="width:300px;"
然后在视图中使用:
def create_article(request):
if request.method == 'POST':
form = ArticleForm(request.POST)
if form.is_valid():
form.save() # 直接保存到数据库
return redirect('article_list')
else:
form = ArticleForm()
return render(request, 'article_form.html', {'form': form})表单验证中可以使用其他高级方法。
单独字段验证
比如对于某个单独字段进行额外验证,可以在ModelForm中定义一个cleam_<fieldname>方法,如下:
class BookForm(ModelForm):
class Meta:
model = Book
fields = '__all__'
def clean_price(self):
price = self.cleaned_data.get('price')
if price <= 0:
raise forms.ValidationError('价格必须大于0')
return priceclean_price方法会自动被调用,验证price字段。
表单整体验证
如果需要基于多个字段一起验证,可以重写clean方法:
def clean(self):
cleaned_data = super().clean() # 因为重写了,所以先调用父类原有的clean()方法
title = cleaned_data.get('title')
author = cleaned_data.get('author')
if title == author:
raise forms.ValidationError('书名和作者不能相同')路由
路由是根据用户请求的 URL 链接来判断对应的处理程序,并返回处理结果,也就是 URL 与 Django 的视图建立映射关系。路由在urls.py中配置。
from django.urls import path
urlpatterns = [
path('admin/', admin.site.urls),
path('index/', views.index),
]路由分发
路由分发是把路由的分配分发到每个app目录当中,使用的是include,比如:
from django.contrib import admin
from django.urls import path,include # 需引入include
urlpatterns = [
path('admin/', admin.site.urls),
path("app01/", include("app01.urls")),
path("app02/", include("app02.urls")),
]反向解析
随着功能的增加,路由层的 url 发生变化,就需要去更改对应的视图层和模板层的 url,非常麻烦,不便维护。
可以利用反向解析,当路由层 url 发生改变,在视图层和模板层动态反向解析出更改后的 url,免去修改的操作。
反向解析一般用在模板中的超链接及视图中的重定向。
这时候在路由中添加字段 name='BieMing',
path('login1/', views.login, name='login')在views.py中可以引入reverse进行反向解析:
return redirect(reverse('login'))路径转换器
用来捕获URL路径中的某部分,并将其转换成特定类型变量,可以从 URL 中提取参数并传递给视图。比如:
path('article/<int:id>/', views.article_detail)这里 <int:id> 是一个路径转换器,表示从 URL 中匹配一个整数,并把它命名为 id,传给视图函数。
而在views.py中,可以用第二个变量接受这个值:
def index(request, id:int):
...| 转换器类型 | 匹配说明 | 传给视图的变量类型 |
|---|---|---|
str | 匹配非斜杠(/)的任意字符序列 | 字符串(str) |
int | 匹配正整数(由数字组成) | 整数(int) |
slug | 匹配字母、数字、连字符和下划线 | 字符串(str) |
uuid | 匹配UUID格式的字符串 | UUID 对象 |
path | 匹配任意字符(包含斜杠 /) | 字符串(str) |
Admin管理工具
需要先注册数据模型到 admin。比如,先在 TestModel 中创建了模型 Test 。
修改 TestModel/admin.py:
from django.contrib import admin
from TestModel.models import Test
# Register your models here.
admin.site.register(Test)也可以一次导入多个模型:
admin.site.register([Test, Contact, Tag])还有其他的管理方法,不过小学期任务展示下前端就行了,管理后台没必要做的很完善()
视图
请求对象:HttpRequest
1. GET
数据类型是 QueryDict,一个类似于字典的对象,包含HTTP GET的所有参数。这些参数就是URL最后的/?name=北航&year=2024
如果有相同的键,就把所有的值放到对应的列表里,取值格式:对象.方法,request即请求的对象。
可以使用和模型一样的方法,都在GET下,如get()返回最后一个匹配的字符串。
def index(request):
name = request.GET.get("name")
return HttpResponse('姓名: {}'.format(name))如果存在第二个参数,则表示不存在时的默认值(避免报错)。
2. POST
也是一种HTTP请求方式,请求参数放在请求体(body)中,不显示在URL中。数据类型同样是 QueryDict。
使用方法和GET几乎一模一样。
def index(request):
name = request.POST.get("name")
return HttpResponse('姓名: {}'.format(name))3. path
用来获取URL中的路径部分,数据类型是字符串。
def index(request):
name = request.path
print(name)
...响应对象:HttpResponse
响应对象主要有三种形式:HttpResponse()、render()、redirect()。
1. HttpResponse()
返回文本,参数为字符串,字符串中写文本内容。如果参数为字符串里含有 html 标签,也可以渲染。
def index(request):
return HttpResponse("<a href='https://lixu.cc'>点击访问</a>")2. render()
返回文本,第一个参数是 request,第二个参数为字符串(页面名称),第三个参数为字典(可选参数,向页面传递的参数:键为页面参数名,值为views参数名)。
def index(request):
name = "LX的博客"
return render(request, "index.html", {"name": name})3. redirect()
用于重定向,跳转新页面。参数为字符串,字符串中填写页面路径。一般用于 form 表单提交后,跳转到新页面。可以传入 URL 名称(反向解析)或路径。
举例:redirect("detail", pk=1) 会跳转到名为 detail 的路由,参数 pk=1。
其他函数
1. get_object_or_404(Model, **kwargs)
从数据库中去获取指定条件的对象(比如 Resource 表中的一条记录)。如果找不到,则直接返回 404 页面,避免程序继续执行和报错。
例:get_object_or_404(Resource, pk=pk):查找主键为 pk 的资源。
2. messages
Django 的内置消息框架,用于控制器(视图)向模板传递状态信息(如“操作成功”、“错误提示”等)。
messages.success(request, "成功消息")、messages.error(request, "错误消息") 等,都可以给前端发送提示。
3. @login_required
装饰器,保证访问此视图的用户已登录。未登录则跳转至登录页。
使用它能方便地保护一些只能登录用户使用的操作,如上传、评分、举报等。
4. Q 对象
Django ORM 的高级查询工具,可以用来组合复杂的查询条件,实现“或”、“且”等关系。
示例:Q(title__icontains=q) | Q(summary__icontains=q) 意思是:标题或摘要包含关键词 q。

