Django View 详解(一)

Django View 详解(一)

URL 分发机制(URLconf)

path() 基础使用

  • path("路由/", 视图函数, name="命名")
  • 支持静态和动态参数(如 <int:id>

示例:

blog/urls.py

from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name='index'),  # 主页
    path('post/<int:id>/', views.post_detail, name='post_detail'),  # 动态路径参数
]

在 Django 的 URL 配置中,name='post_detail' 是为 URL 模式命名的,这个命名在 Django 中的作用是 1、解耦 URL 路径和代码逻辑,避免硬编码。2、方便动态生成 URL,提高代码可维护性。常用在:
1、URL 反向解析(Reverse URL Lookup)

允许你在模板或 Python 代码中动态生成 URL,而不用硬编码 URL 路径。

<!-- html 文件,在模板中使用 -->
<a href="{% url 'post_detail' id=post.id %}">查看详情</a>

# 在 Python 代码中使用
from django.urls import reverse
url = reverse('post_detail', kwargs={'id': 1})  # 返回类似 '/post/1/'

如果以后 URL 模式改变(比如从 post/<int:id>/ 改成 articles/<int:id>/),你只需要修改 urls.py,而不用修改所有模板和视图中的硬编码 URL。

2、在重定向(Redirect)中使用

在视图函数中可以使用命名的 URL 进行重定向:

from django.shortcuts import redirect
return redirect('post_detail', id=5)  # 重定向到 '/post/5/'

views.py

from django.http import HttpResponse

def index(request):
    return HttpResponse("欢迎来到博客首页")

def post_detail(request, id):
    return HttpResponse(f"您正在查看第 {id} 篇文章")

结果展示:

Django View 详解(一)
Django View 详解(一)

re_path()(旧版叫 url())正则表达式路由

  • 更灵活的路径匹配(例如:年份、slug)

示例:

urls.py

from django.urls import re_path
from . import views

urlpatterns += [
    re_path(r'^archive/(?P<year>[0-9]{4})/$', views.archive_by_year, name='archive_by_year'),
]

views.py

def archive_by_year(request, year):
    return HttpResponse(f"{year} 年的归档")
r'^archive/(?P<year>[0-9]{4})/$' 匹配讲解:
  • r 表示这是一个原始字符串(raw string),避免 Python 对反斜杠的特殊处理
  • ^ 表示匹配字符串的开始
  • archive/ 是字面匹配,必须精确匹配这部分
  • (?P<year>[0-9]{4}) 是命名捕获组:
    • ?P<year> 表示将捕获的内容命名为 "year",这会要求views.py中必须接受传入的“year”参数
    • [0-9]{4} 表示匹配恰好 4 个数字字符(0-9)
  • / 是字面匹配的斜杠
  • $ 表示匹配字符串的结束
Django View 详解(一)

include() 模块化拆分

主项目调用子 app 的 urls.py

项目根目录的 urls.py:

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('blog/', include('blog.urls')),  # 引入 blog 子应用的路由
]

命名路由 + 反向解析

什么是命名路由(name 参数)

Django 中的路由是通过 path() 来注册的,比如:

from django.urls import path
from . import views

urlpatterns = [
    path('posts/<int:id>/', views.post_detail, name='post_detail'),  # 👈 这里的 name 参数就是“命名路由”
]

这段代码的意思是:

  • 访问 URL /posts/3/ 会执行 views.post_detail(request, id=3)
  • 并且这个路由有个别名叫做 'post_detail'

有了这个 name,我们就可以用名字反向生成 URL 地址,这叫做“反向解析”。

什么是反向解析(reverse 和 {% url %})

1、在视图函数里:用 reverse()

比如你想在视图函数中跳转到帖子详情页(比如 /posts/3/):

from django.urls import reverse
from django.shortcuts import redirect

def go_to_post(request):
    url = reverse('post_detail', kwargs={'id': 3})  # 👈 根据路由名称和参数,反向生成 URL
    return redirect(url)
  • 'post_detail' 是路由名称
  • kwargs={'id': 3} 表示这个 URL 中的 <int:id> 是 3
  • reverse() 返回的就是 /posts/3/
  • 然后 redirect() 会跳转过去

2、在模板中:用 {% url %} 标签

如果你想在页面中放一个跳转链接:

<a href="{% url 'post_detail' id=3 %}">查看第三篇文章</a>

这段模板代码会被渲染成:

<a href="/posts/3/">查看第三篇文章</a>

方便之处:不需要自己拼接 URL,只要写清楚名字和参数就好

实战 demo:

blog/urls.py

from django.urls import path
from . import views

urlpatterns = [
    path('posts/<int:id>/', views.post_detail, name='post_detail'),  # 命名路由
    path('go/', views.go_to_post),  # 跳转用的视图
    path('', views.post_list, name='post_list'),  # 首页文章列表
]

blog/views.py

from django.shortcuts import render, redirect
from django.urls import reverse
from django.http import HttpResponse

def post_detail(request, id):
    return HttpResponse(f"你正在查看第 {id} 篇文章")

def go_to_post(request):
    # 模拟跳转到第 3 篇文章
    url = reverse('post_detail', kwargs={'id': 3})
    return redirect(url)

def post_list(request):
    return render(request, 'blog/post_list.html')

templates/blog/post_list.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>文章列表</title>
</head>
<body>
    <h1>博客文章列表</h1>
    <ul>
        <li><a href="{% url 'post_detail' id=1 %}">查看第 1 篇文章</a></li>
        <li><a href="{% url 'post_detail' id=2 %}">查看第 2 篇文章</a></li>
        <li><a href="{% url 'post_detail' id=3 %}">查看第 3 篇文章</a></li>
    </ul>
</body>
</html>

结果演示:

访问路径为/go/,使用 reverse() 反向解析后,跳转到 /posts/3/

Django View 详解(一)

/posts/3/ 会显示“你正在查看第 3 篇文章”

/目录下渲染模板,用 {% url %} 生成多个跳转链接

Django View 详解(一)

视图函数与 HTTP 响应

HttpResponse

最基本的返回

from django.http import HttpResponse
def simple_response(request):
    return HttpResponse("这是一个简单响应")

render()

知识点:

  • 渲染模板 + 传值

render() 是什么?它做了什么?

定义:

render(request, template_name, context=None)

render() 是 Django 提供的快捷函数,用于:

  • 加载指定模板(HTML 文件)
  • 使用 context 上下文中的变量进行渲染
  • 返回一个包含渲染结果的 HttpResponse

底层其实这样

from django.template import loader
from django.http import HttpResponse

template = loader.get_template("blog/index.html")
html = template.render({"posts": posts}, request)
return HttpResponse(html)

作用流程:

  1. 找到模板文件(路径是:templates/blog/index.html
  2. 把视图中传入的 posts 列表交给模板
  3. 模板用 {% for post in posts %} 遍历并展示
  4. 最后返回一个完整 HTML 页面给浏览器

完整示例:博客首页

models.py(定义数据模型)

# blog/models.py
from django.db import models

class Post(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()

    def __str__(self):
        return self.title

views.py(视图函数)

# blog/views.py
from django.shortcuts import render
from .models import Post

def index(request):
    # 获取所有文章
    posts = Post.objects.all()

    # 渲染模板并传入上下文变量
    return render(request, "blog/index.html", {"posts": posts})

urls.py(路由系统)

# blog/urls.py
from django.urls import path
from . import views

urlpatterns = [
    path("", views.index, name="post_index"),  # 命名路由
]
# 项目根目录 urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('blog/', include("blog.urls")),  # 引入 blog 应用的路由
]

templates/blog/index.html

<!-- templates/blog/index.html -->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>博客首页</title>
</head>
<body>
    <h1>所有文章</h1>
    <ul>
        {% for post in posts %}
            <li>{{ post.title }}</li>
        {% empty %}
            <li>暂无文章</li>
        {% endfor %}
    </ul>
</body>
</html>

用户访问 /posts/ → URL 交给 views.index → views.py 获取所有文章 Post.objects.all() → render() 渲染 blog/index.html → 模板中遍历 posts 显示标题 → 浏览器收到完整 HTML 页面

扩展:如果你准备实现文章详情页,那就该同时:

blog/urls.py 添加对应路由:

# blog/urls.py
from django.urls import path
from . import views

urlpatterns = [
    path("", views.index, name="post_index"),
    path("<int:id>/", views.detail, name="post_detail"),  # 加这个
]

blog/views.py 中添加 detail 视图:

# blog/views.py
from django.shortcuts import render, get_object_or_404
from .models import Post

def detail(request, id):
    post = get_object_or_404(Post, id=id)
    return render(request, "blog/detail.html", {"post": post})

新建模板 templates/blog/detail.html

<!-- templates/blog/detail.html -->
<!DOCTYPE html>
<html>
<head>
  <title>{{ post.title }}</title>
</head>
<body>
  <h1>{{ post.title }}</h1>
  <p>{{ post.content }}</p>
  <a href="{% url 'post_index' %}">返回首页</a>
</body>
</html>

修改 templates/blog/index.html

<!DOCTYPE html>
<html>
<head>
  <title>所有文章</title>
</head>
<body>
  <h1>所有文章</h1>
  <ul>
    {% for post in posts %}
      <li>
        <!-- 每个文章标题链接到详情页 -->
        <a href="{% url 'post_detail' id=post.id %}">{{ post.title }}</a>
      </li>
    {% empty %}
      <li>暂无文章</li>
    {% endfor %}
  </ul>
</body>
</html>

完成这些之后,你访问 /blog/ 时看到的首页文章列表,每个标题就能点进去,跳转到对应文章的详情页了。

Django View 详解(一)

获取请求参数与body处理

URL 动态路径参数

什么是“动态路径参数”?

就是 URL 地址中直接嵌入一个“值”,比如:

/post/1/   表示访问 ID 为 1 的文章
/post/23/  表示访问 ID 为 23 的文章

Django 如何实现?

urls.py 这样写:

path('post/<int:id>/', views.post_detail, name='post_detail')

<int:id> 表示这是一个整数类型的参数,叫做 id

当用户访问 /post/3/ 时,Django 会自动把 3 提取出来,传给 views.post_detail 函数。

views.py 中处理:

from django.http import HttpResponse
from .models import Post  # 假设你有这个模型

def post_detail(request, id):
    post = Post.objects.get(id=id)  # 根据 id 找文章
    return HttpResponse(f"文章:{post.title}")

访问测试:

你访问 /post/3/,它会去数据库里查 ID=3 的文章,并返回:

Django View 详解(一)

复杂的 URL 路由动态路径参数推荐使用关键字参数

 URL 正则表达式配置

假设我们仍然在博客应用的上下文中,有一个能够处理动态路径参数 id 的文章详情页,使用 re_path()。我们将允许 id 参数为数字,且可以指定文章的 slug(短语)如: /post/1/python-introduction/

首先,在 urls.py 中使用 re_path()

# blog/urls.py
from django.urls import re_path
from . import views

urlpatterns = [
    re_path(r'^post/(?P<id>\d+)/(?P<slug>[\w-]+)/$', views.post_detail, name='post_detail'),
]
  • (?P<id>\d+) 是一个命名捕获组,它捕获数字,并将其存储为 id
  • (?P<slug>[\w-]+) 捕获一个包含字母、数字、下划线和连字符的字符串并将其存储为 slug

在 views.py 中定义如何处理这个视图:

# blog/views.py
from django.http import HttpResponse
from django.shortcuts import get_object_or_404
from .models import Post  # 假设你有这个模型

def post_detail(request, id, slug):
    # 使用 get_object_or_404 确保获取的文章存在
    post = get_object_or_404(Post, id=id)
    
    # 返回文章详情
    return HttpResponse(f"你正在查看的文章是:{post.title},Slug: {slug}")

可以通过以下 URL 来访问文章详情:

  • /post/1/python-introduction/
  • /post/23/another-article/
Django View 详解(一)

获取 GET 请求参数(如 /search/?q=xxx

什么是 GET 请求参数?

当你访问一个 URL,并带上参数,如:

/search/?q=django

这叫 GET 请求参数,q=django 中:

  • q 是参数名
  • django 是参数值

常用于搜索功能、筛选功能等。

单个键单个值 get 请求

代码讲解:

urls.py

path('search/', views.search, name='search')

views.py

from django.http import HttpResponse

def search(request):
    query = request.GET.get('q')  # 从 URL 中取出参数 q 的值
    return HttpResponse(f"搜索关键词:{query}")

访问 /search/?q=django 会返回 “搜索关键词:django”

继续完善和扩展:如果你希望能返回标题或内容中包含 “django” 的所有文章(Post)。

修改 views.py 中的 search 视图

# blog/views.py
from django.shortcuts import render
from .models import Post

def search(request):
    query = request.GET.get('q')  # 从 URL 中获取查询参数
    if query:
        # 使用 Django ORM 进行模糊查询
        posts = Post.objects.filter(title__icontains=query) | Post.objects.filter(content__icontains=query)
    else:
        # 如果没有搜索关键词,返回空结果或所有文章
        posts = Post.objects.none()  # 返回一个空的 QuerySet

    return render(request, 'blog/search_results.html', {'query': query, 'posts': posts})

这里的关键点是使用 icontains 来实现不区分大小写的模糊查询,返回标题或内容中包含指定关键词的所有文章。

添加一个模板 search_results.html

文件路径:templates/blog/search_results.html

<!DOCTYPE html>
<html>
<head>
  <title>搜索结果</title>
</head>
<body>
  <h1>搜索关键词:{{ query }}</h1>

  {% if posts %}
    <ul>
      {% for post in posts %}
        <li>
          <strong>{{ post.title }}</strong><br>
          <small>作者:{{ post.author.name }} | 时间:{{ post.created_at }}</small><br>
          <p>{{ post.content }}</p>
        </li>
      {% endfor %}
    </ul>
  {% else %}
    <p>没有找到相关的文章。</p>
  {% endif %}
</body>
</html>

页面会显示标题或内容中包含 “django” 的所有文章,如:

Django View 详解(一)

多个键值对

如果您需要处理多个查询参数,可以使用 request.GET 来提取多个参数的值。这是一个类字典对象,允许您访问 URL 中的所有查询参数。您可以通过参数名称来访问相应的参数值,并且可以提供默认值以处理参数可能不存在的情况。

以下是一个示例代码:

# urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('search/', views.search, name='search')
]

# views.py
from django.http import HttpResponse

def search(request):
    # 从 URL 中获取多个参数的值
    keyword = request.GET.get('q', '')  # 当参数不存在时,默认值为空字符串
    category = request.GET.get('category', 'all')  # 当参数不存在时,默认值为 'all'
    date = request.GET.get('date', None)  # 当参数不存在时,默认值为 None
    
    response_text = f"搜索关键词:{keyword}, 类别:{category}, 日期:{date}"
    return HttpResponse(response_text)

在这个例子中,我们查询三个参数:qcategory 和 date。URL 访问示例:

  • /search/?q=django&category=books&date=2023-01-01 会返回 "搜索关键词:django, 类别:books, 日期:2023-01-01"
  • /search/?q=django&category=books 会返回 "搜索关键词:django, 类别:books, 日期:None"
  • /search/?category=books 会返回 "搜索关键词:, 类别:books, 日期:None"

单个键多个值 request.GET.getlist()

假设您正在处理一个允许用户选择多个类别进行搜索的场景,这里是一个使用 request.GET.getlist() 的例子

例如,您有一个搜索接口,用户可以通过多个类别进行搜索,使用 URL 参数的形式如下:/search/?category=books&category=music&category=movies

# urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('search/', views.search, name='search'),
]

# views.py
from django.http import HttpResponse

def search(request):
    # 使用 getlist() 获取所有 category 参数的值列表
    categories = request.GET.getlist('category')
    
    # 将类别列表转换为一个字符串,以便在响应中显示
    categories_str = ", ".join(categories)
    
    response_text = f"选择的类别:{categories_str}"
    return HttpResponse(response_text)

在这个例子中,request.GET.getlist('category') 将返回 ['books', 'music', 'movies']。然后,我们将这些值合并成一个字符串并返回给客户端。

Django View 详解(一)

请求体body中发送数据(表单数据、json、xml)

获取 POST 表单参数

什么是 POST 表单提交?

POST 请求通常用于向服务器提交数据(比如用户发评论、注册、登录等)。
HTML 中写 <form method="post">,就代表是 POST 请求。

路由配置:urls.py

这是 URL 路由系统的入口,你必须定义“表单页面”和“处理提交”的地址:

from django.urls import path
from . import views

urlpatterns = [
    path('comment/', views.comment_page, name='comment_page'),  # 用户访问这个页面填写评论
    path('submit_comment/', views.comment_post, name='comment_post'),  # 提交表单数据处理
]

前端页面:templates/blog/comment.html

必须创建一个 HTML 页面,里面包含 <form> 表单。

<!-- templates/blog/comment.html -->
<!DOCTYPE html>
<html>
<head>
  <title>发表评论</title>
</head>
<body>
  <h1>评论文章</h1>

  <!-- 表单区域 -->
  <form method="post" action="{% url 'comment_post' %}">
    {% csrf_token %}  <!-- 防止跨站攻击,必须有 -->
    <textarea name="content" placeholder="写下你的评论..." rows="5" cols="40"></textarea>
    <br>
    <button type="submit">提交评论</button>
  </form>
</body>
</html>
表单字段含义
method="post"表示使用 POST 请求提交数据
action="{% url 'comment_post' %}"提交数据到后端处理路径(匹配上面第二个路由)
name="content"表示评论内容字段,后端要用这个名字提取值
{% csrf_token %}Django 安全机制要求表单必须带上这个字段
后端视图函数处理表单提交:views.py
from django.http import HttpResponse
from django.shortcuts import render
from django.views.decorators.csrf import csrf_exempt  # 如果你没用 {% csrf_token %},可临时关闭 CSRF

def comment_page(request):
    return render(request, 'blog/comment.html')

@csrf_exempt  # 如果你没有 {% csrf_token %},临时加这个。生产环境不要加
def comment_post(request):
    if request.method == "POST":
        content = request.POST.get("content")
        return HttpResponse(f"你提交的评论内容是:{content}")
    return HttpResponse("请通过 POST 提交")

完整流程演示:

步骤说明
用户访问 /comment/会触发 views.comment_page,渲染并显示 comment.html 表单页面
用户填写评论并点击“提交”按钮浏览器向 /submit_comment/ 发出一个 POST 请求
后端的 comment_post() 处理函数会被调用request.POST.get('content') 中获取表单字段值,进行处理或保存

难点:请问用户填写评论并点击“提交”按钮后,为什么会触发浏览器向 /submit_comment/ 发出一个 POST 请求?

用户填写评论并点击“提交”按钮后,浏览器会向 /submit_comment/ 发送 POST 请求的原因是由于 HTML <form> 元素的配置。以下是 HTML <form> 的关键属性,以及它们如何影响数据提交:

  1. method="post"
    • 这意味着表单数据将使用 HTTP POST 方法提交。POST 请求被用于向服务器发送数据以创建或更新资源。
  2. action="{% url 'comment_post' %}"
    • 这个属性定义了表单数据提交的目标 URL。在这个例子中,{% url 'comment_post' %} 是 Django 模板标签,它将被解析为 URL 路由系统中名称为 'comment_post' 的路径。因此,这会生成 /submit_comment/ 路径(通过 name='comment_post' 方向解析出路径),依据您在 urls.py 中定义的路由。
    • 因此,当用户点击提交按钮时,请求会被发送到 /submit_comment/
Django View 详解(一)

整个步骤过程:

  1. 用户请求表单页面
    • 请求: 用户在浏览器中访问 URL /comment/
    • 处理: Django 路由将该请求对应到 views.comment_page
    • 响应comment_page 函数通过render将 templates/blog/comment.html 页面返回给客户端。
    • 展示: 浏览器渲染并显示 HTML 表单页面给用户。
  2. 用户填写表单并提交
    • 操作: 用户在浏览器中填写评论内容,并点击提交按钮。
    • 网络请求: 浏览器根据 <form> 元素的 method 和 action 属性,向 /submit_comment/ 发出一个 POST 请求。
  3. 服务器处理提交的表单数据
    • 请求收集: POST 请求由 Django 框架处理,并通过 URL 路由系统对应到 views.comment_post
    • 数据处理comment_post 函数检查请求方法为 POST,提取数据 request.POST.get('content')
    • 响应生成: 将提取的评论内容生成响应,并以 HttpResponse 返回给客户端。
  4. 响应到客户端
    • 用户可见: 浏览器接收来自服务器的响应,并呈现给用户(例如显示“你提交的评论内容是:…”)。

可以用postman 测试过程

  1. 请求设置:
    • 打开 Postman,选择 HTTP 请求类型为 POST
    • 设置请求 URL 为 http://your-server-domain/submit_comment/(替换 your-server-domain 为实际服务器地址或 localhost)。
  2. 设置请求 Body:
    • 在 Body 标签中,选择 x-www-form-urlencoded
    • 添加一个键值对:
      • Key: content
      • Value: 输入您想测试的评论内容,例如 This is a test comment.
  3. 发送请求:
    • 点击 Send 发送请求。
  4. 查看响应:
Django View 详解(一)

POST 方式传递和解析 json 数据

传递和解析 JSON 数据在现代 web 应用中非常普遍,尤其是在使用 JavaScript 和后端 API 通信时。以下是基础概念和一个简单的例子。

JSON 数据介绍

  • JSON (JavaScript Object Notation) 是一种轻量级的数据交换格式,易于人和机器读取和写入。
  • 它基于键值对结构,类似于 Python 的字典或 JavaScript 的对象。
  • JSON 数据类型包括字符串、数字、布尔值、数组和对象。

传递 JSON 数据

可以通过 HTTP POST 请求发送 JSON 格式的数据。通常这会在应用程序的前端和后端之间进行。

案例:传递和解析 JSON 数据

假设有一个 Django 后端应用,需要处理用户的个人信息,该信息以 JSON 格式传递。

修改 urls.py

# urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('user_info/', views.user_info, name='user_info'),  # 配置路由以处理用户信息请求
]

后端视图处理 JSON 数据 (views.py)

from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
import json

@csrf_exempt  # 再生产环境应启用 CSRF 防护机制,目前为了便于测试禁用
def user_info(request):
    if request.method == "POST":
        try:
            # 从请求体中解析 JSON 数据
            data = json.loads(request.body) # json 形式的字符串不太好操作,一般都会通过 json.loads转化成字符串
            name = data.get('name')
            age = data.get('age')
            # 可以对数据进行处理或存储

            return JsonResponse({'message': f'Hello, {name}, your age is {age}.'})
        except json.JSONDecodeError:
            return JsonResponse({'error': 'Invalid JSON'}, status=400)

    return JsonResponse({'error': 'Only POST method allowed'}, status=405)

可以使用 Postman 或任何其他 HTTP 客户端工具进行测试:

  • 请求设置:
    • 打开 Postman,选择请求类型为 POST
    • 设置请求 URL 为 http://your-server-domain/user_info/
  • 设置请求 Header:
    • 确保 Content-Type 设置为 application/json
  • 设置请求 Body:
    • 在 Body 标签中,选择 raw
    • 输入 JSON 数据,例如:
{
  "name": "John Doe",
  "age": 30
}
  • 发送请求:
    • 点击 Send 发送请求。
  • 查看响应:
    • 服务器应该返回一条消息,确认已成功接收到并处理了 JSON 数据。
Django View 详解(一)

json.dumps 和 json.load 

json.dumps 用于将 Python 对象(如字典或列表)序列化为 JSON 格式的字符串。这个过程称为“序列化”。序列化的主要用途是在数据在网络传输或存储到文件时,将数据转换为一种标准格式。

用法示例:

import json

data = {
    "name": "John Doe",
    "age": 30,
    "active": True,
    "roles": ["admin", "user"]
}

# 将 Python 对象序列化为 JSON 字符串
json_string = json.dumps(data)
print(json_string)

在这个示例中,json.dumps(data) 将 Python 字典转换为 JSON 字符串,并将结果打印出来。

json.load 用于从文件对象中读取 JSON 数据,并将其解析为 Python 对象。这与 json.loads 有所不同,因为 json.loads 解析的是字符串,而 json.load 解析的是文件。

假设我们有一个文件 data.json,其内容如下:

{
  "name": "Jane Doe",
  "age": 25,
  "active": false,
  "roles": ["editor", "user"]
}

我们用 json.load 读取这个文件:

import json

# 打开 JSON 文件进行读取
with open('data.json', 'r') as file:
    # 使用 json.load 解析文件中的 JSON 数据
    data = json.load(file)

print(data)

在这个示例中,json.load(file) 从文件中读取 JSON 数据并解析为 Python 字典,然后将结果打印出来。

请求头获取

在处理 HTTP 请求时,请求头(HTTP Headers)是非常重要的部分。请求头携带了关于客户端环境、请求细节、传输数据等多种信息,这些信息用于告知服务器如何处理请求。理解和使用请求头是开发 Web 应用时的基本技能之一。

  1. Content-Type:
    • 描述请求体的媒体类型。例如,application/json 表示请求体是 JSON 数据,application/x-www-form-urlencoded 表示表单数据。
    • 服务器通过这个头来决定如何解析请求体内容。
  2. Accept:
    • 指定客户端能够处理的内容类型。这意味着客户端期望从服务器接收的数据类型,比如 text/html 或 application/json
    • 服务器根据 Accept 头选择合适的 MIME 类型进行响应。
  3. Authorization:
    • 包含用于验证客户端身份的凭据信息。它常用于实施认证机制,如 Basic Auth、Bearer Token 等。
    • 安全性关键,用于保护 API,确保只有授权用户才能访问。
  4. User-Agent:
    • 提供有关发起请求的客户端的详细信息,通常是浏览器名称和版本。
    • 服务器可以使用 User-Agent 头来定制响应内容,比如为不同浏览器优化显示。
  5. Accept-Language:
    • 指定客户端能够理解的语言种类,例如 en-US 表示美国英语。
    • 服务器可以基于这个信息提供多语言支持。
  6. Referer:
    • 包含表示请求来源的 URL,指示用户从哪个页面链接到当前请求的资源。
    • 较常用于分析流量源或防止 CSRF 攻击。
  7. Cookie:
    • 包含与请求关联的 cookie 数据,通常包括会话信息。
    • 服务器可以利用 cookie 头来跟踪会话状态。
  8. Cache-Control:
    • 指示客户端的缓存机制相关指令,控制如何缓存请求和响应数据。
    • 服务器可以根据 Cache-Control 头调整对客户端的缓存策略。

在 Django 或其他 Web 框架中,处理请求头非常方便。通常可以通过 request.headers 访问请求头。例如,在 Django 中:

def my_view(request):
    content_type = request.headers.get('Content-Type', '')
    user_agent = request.headers.get('User-Agent', '')

    # Do something with the request headers
    print(f'Content-Type: {content_type}')
    print(f'User-Agent: {user_agent}')
Django View 详解(一)

常用的 httprequest 对象属性

常用的 HttpRequest 属性

  1. GET:
    • 包含查询字符串参数,是一个 QueryDict 对象。
    • 使用示例:request.GET['param_name']
  2. POST:
    • 包含请求主体中的表单数据,也是一个 QueryDict
    • 使用示例:request.POST['param_name']
  3. FILES:
    • 包含上传的文件信息,是一个 MultiValueDict
    • 使用示例:request.FILES['file_field_name']
  4. COOKIES:
    • 一个字典,包含请求中发送的所有 cookies。
    • 使用示例:request.COOKIES['cookie_name']

HTTP 响应返回

常用的响应类总结

类名说明用途示例
HttpResponse返回纯文本或 HTML返回普通字符串、HTML、状态码
render返回渲染后的模板页面常用于展示网页
redirect重定向到新地址登录后跳转,提交表单后跳转等
JsonResponse返回 JSON 数据前后端交互、AJAX 请求
HttpResponseNotFound返回 404 响应页面不存在时使用
HttpResponseRedirectredirect() 类似,直接构造跳转响应

假设你的 app 叫做 blog,我们现在要在 blog/views.pyblog/urls.py 中写代码。

一、HttpResponse():返回纯文本或 HTML

views.py

from django.http import HttpResponse

def hello(request):
    return HttpResponse("你好,世界!")

def forbidden(request):
    return HttpResponse("禁止访问", status=403)

urls.py

from django.urls import path
from . import views

urlpatterns = [
    path('hello/', views.hello, name='hello'),
    path('forbidden/', views.forbidden, name='forbidden'),
]

访问 /hello/ → 显示文本「你好,世界!」
访问 /forbidden/ → 显示文本「禁止访问」,状态码 403

Django View 详解(一)

二、render():返回 HTML 模板页面

views.py

from django.shortcuts import render

def index(request):
    return render(request, 'blog/index.html', {"title": "博客首页"})

urls.py

path('index/', views.index, name='index'),

templates/blog/index.html 示例模板:

<!DOCTYPE html>
<html>
<head>
  <title>{{ title }}</title>
</head>
<body>
  <h1>{{ title }}</h1>
  <p>欢迎来到首页!</p>
</body>
</html>

访问 /index/ → 渲染 HTML 模板页面

Django View 详解(一)

三、redirect():页面跳转

views.py

from django.shortcuts import redirect

def login_success(request):
    return redirect('/hello/')  # 直接跳转到另一个路径

def redirect_named(request):
    return redirect('index')  # 跳转到命名路由

urls.py

path('login_success/', views.login_success, name='login_success'),
path('redirect_named/', views.redirect_named, name='redirect_named'),

访问 /login_success/ → 会跳转到 /hello/
访问 /redirect_named/ → 会跳转到 /index/

四、JsonResponse():返回 JSON 数据

views.py

from django.http import JsonResponse

def api_data(request):
    data = {"name": "Django", "type": "framework"}
    return JsonResponse(data)

urls.py

path('api/data/', views.api_data, name='api_data'),

访问 /api/data/ → 返回 JSON:

Django View 详解(一)

五、FileResponse:下载文件

你可以先在项目根目录下放一个 PDF 文件,比如:example.pdf

views.py

from django.http import FileResponse
import os

def download_file(request):
    filepath = os.path.join(os.path.dirname(__file__), 'example.pdf')
    return FileResponse(open(filepath, 'rb'), as_attachment=True, filename='example.pdf')

urls.py

path('download/', views.download_file, name='download_file'),

访问 /download/ → 下载 example.pdf 文件

Django View 详解(一)

实际开发中如何选择响应方式?

场景推荐用法
返回一个 HTML 页面render()
提交表单成功后跳转redirect()
AJAX/FetchAPI 请求获取数据JsonResponse()
非页面的错误提示HttpResponse("错误信息", status=403)

错误页面处理方式

主动返回:

from django.http import HttpResponseNotFound

def my_view(request):
    return HttpResponseNotFound("页面不存在")

使用 get_object_or_404:

from django.shortcuts import get_object_or_404

post = get_object_or_404(Post, id=3)

根据模型和条件尝试从数据库中获取一条数据,如果找不到,就自动返回 404 页面(而不是抛出异常)

get_object_or_404(模型类, **查询条件)

  • 模型类:你要查询的模型(比如 Post
  • 查询条件:用字段名=值的形式,比如 id=3
  • 如果能查到,就返回那条记录
  • 如果查不到,就返回 Http404 错误,自动显示 “页面未找到”

这种方式的好处:如果使用post = Post.objects.get(id=3),如果 id=3 的文章存在,一切正常
,如果不存在,会抛出异常 Post.DoesNotExist,程序就会崩溃。而使用post = get_object_or_404(Post, id=3),程序更健壮,不需要自己写 try-except,并且可以自动处理错误页(返回 404)

发布者:LJH,转发请注明出处:https://www.ljh.cool/43491.html

Like (0)
LJH的头像LJH
Previous 2025年7月29日 下午4:53
Next 2025年8月7日 下午3:19

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注