Django笔记 路由和视图 - 接上期MVT模型

上期由于篇幅问题,MVT模型并未进行记录,这里让我们熟悉路由和视图。

路由简介

        在我们创建django项目时,会在目录下生成一个urls的文件,这个就是管理django路由的文件

如果你对前端有过接触,就会感觉这个文件和vue框架中的routre做一样的事情

from django.contrib import admin
from django.urls import path
from Blog import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('',views.index_blog),
]

其主要格式为

path(路由,视图函数,别名)

路由包含

        在上期中,引入过这个概念,当项目复杂时,如果单个urls会非常复杂,所以需要路由包含,进行解决这个问题

开始进行验证

# /blog/views
from django.shortcuts import render
from django.http import HttpResponse
# Create your views here.
def index_blog(request):
    return render(request,'index/index.html')
def test(request):
    return HttpResponse("这个方法是为了测试路由包含功能,显示则是证明成功!")
# /blog/urls
from django.urls import path
from Blog import views

urlpatterns = [
    path('blog/test/',views.test),
]
# /myblog/urls
from django.contrib import admin
from django.urls import include, path
from Blog import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('',views.index_blog),
    path('',include('Blog.urls')),
]

带参数的路由配置

        在web请求,携带数据参数的请求往往占据多数,django也提供这种方法

# /blog/views
from django.shortcuts import render
from django.http import HttpResponse
# Create your views here.
def index_blog(request):
    return render(request,'index/index.html')
def test(request,id):
    return HttpResponse(f"这个方法是为了测试路由参数功能,显示id:{id}则是证明成功!")
# /blog/urls
from django.urls import path
from Blog import views

urlpatterns = [
    path('blog/test/<int:id>',views.test),
]

        路由规则<>中的内容,我们称为url参数,格式是:

<数据类型:参数名称>

数据类型为五种

  1. str:匹配任何非空字符串,不包括路径分隔符'/'。这是默认的转换器。

  2. int:匹配零和任何正整数。返回一个int类型。

  3. slug:匹配任何由字母、数字、连字符和下划线组成的字符串片段。

  4. uuid:匹配格式化的UUID。返回一个uuid.UUID实例。

  5. path:匹配任何非空字符串,包括路径分隔符'/'。这允许你匹配完整的URL路径。

正则匹配复杂路由

        在一些情况下,我们需要传递复杂格式这种需要校验格式的数据参数,所以django提供了正则路由

# /blog/views
from django.shortcuts import render
from django.http import HttpResponse
# Create your views here.
def index_blog(request):
    return render(request,'index/index.html')
def test(request,date,time):
    return HttpResponse(f"这个方法是为了测试路由参数功能,显示日期为{date},时间为{time}则是证明成功!")
# /blog/urls
from django.urls import path,re_path
from Blog import views

urlpatterns = [
    re_path(r'blog/test/(?P<date>\d{4}-\d{1,2}-\d{1,2})&(?P<time>\d{1,2}:\d{1,2}:\d{1,2})',views.test),
]

路由反向解析

        URL模式需要改变时,我们不必一个个配置,只需要在URL配置中修改一次即可使用,这就是运用了路由别名的功能,别名则是基于django的路由反向解析

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

urlpatterns = [
    path(r'blog/test/',views.test,name='myblog_blog_test'),
]
# /blog/views
from django.shortcuts import render
from django.http import HttpResponse
from django.urls import reverse
# Create your views here.
def index_blog(request):
    return render(request,'index/index.html')
def test(request):
    return HttpResponse(f"这个方法是为了测试路由反解析,显示路由路径为{reverse("myblog_blog_test")}")

MTV模型之视图层

        现在,我们了解到了django中的视图层,其用于处理客户端请求,并生成返回数据

        web请求   ->   创建request对象接收   ->     django  -  视图层 响应 封装response    ->   web返回

        一般,我们将web请求称为 request web返回称为 response,如果是基于http协议,那么就是httprequest 和 httpresponse

# /blog/views
from django.shortcuts import render
from django.http import HttpResponse
# Create your views here.
def test(request):
    return HttpResponse("你好!Django!")

        views中,用于处理这些请求,以及根据请求返回的函数,我们称之为视图函数

        比如视图函数test() 其第一个参数为 request(请求),针对这个请求,我们有一个返回       HttpResponse 返回内容("你好!Django!")

在了解django的视图之前,我们需要先了解,这些请求和响应包含了哪些东西

HttpRequest的属性和方法

HttpRequest属性
  1. request.method

    请求的HTTP方法,例如:'GET', 'POST'。
  2. request.GET

    一个类似字典的对象,包含所有GET请求的参数。
  3. request.POST

    一个类似字典的对象,包含所有POST请求的参数。注意:仅当请求的Content-Type为application/x-www-form-urlencoded或multipart/form-data时,才会包含数据。
  4. request.FILES

    一个类似字典的对象,包含所有上传的文件。每个键是<input type="file" name="">中的name,值是一个UploadedFile对象。
  5. request.COOKIES

    一个包含所有cookies的字典。
  6. request.session

    一个可读写的类似字典的对象,表示当前会话。
  7. request.META

    一个包含所有HTTP请求头的字典。例如:
    • SERVER_PORT:服务器的端口(字符串)。

    • SERVER_NAME:服务器的主机名。

    • REQUEST_METHOD:请求方法,如'GET'、'POST'。

    • REMOTE_ADDR:客户端的IP地址。

    • HTTP_USER_AGENT:客户端的用户代理字符串。

    • HTTP_REFERER:引用页面的URL。

    • HTTP_HOST:客户端发送的Host头。

    • HTTP_ACCEPT_LANGUAGE:可接收的语言。

    • HTTP_ACCEPT_ENCODING:可接收的编码。

    • HTTP_ACCEPT:可接收的响应内容类型。

    • CONTENT_TYPE:请求体的MIME类型。

    • CONTENT_LENGTH:请求体的长度(字符串)。

  8. request.user

    表示当前登录的用户。如果用户未登录,则是一个AnonymousUser实例。通过Django的认证中间件设置。
  9. request.path

    请求的路径,例如:"/music/bands/the_beatles/"
  10. request.path_info

    在某些Web服务器配置下,path_info部分比path更准确。
  11. request.get_full_path()

    返回path,加上查询字符串(如果有的话)。
  12. request.get_full_path_info()

    类似get_full_path,但是使用path_info而不是path。
  13. request.body

    请求体作为字节字符串。用于处理非表单数据(例如JSON、XML)。
  14. request.scheme

    请求的协议,通常是'http'或'https'。
  15. request.encoding

    请求的编码方式。如果为None,则使用DEFAULT_CHARSET。
HttpRequest方法
  1. request.get_host()

    返回请求的主机名。根据HTTP_X_FORWARDED_HOST和HTTP_HOST头信息处理。
  2. request.get_port()

    返回请求的端口。
  3. request.get_full_path()

    返回完整路径,包括查询字符串。
  4. request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)

    返回已签名的cookie的值。如果签名无效或已过期,则抛出异常。
  5. request.is_secure()

    如果请求是安全的(使用HTTPS),返回True。
  6. request.is_ajax()

    如果请求是通过XMLHttpRequest发出的,返回True。判断依据是HTTP头中的X-Requested-With是否为'XMLHttpRequest'。注意:现代前端框架可能不再设置这个头,所以这个方法可能不总是可靠。
  7. request.read(size=None)

    从请求体中读取数据。
  8. request.readline()

    从请求体中读取一行。
  9. request.readlines()

    读取请求体的所有行。
  10. request.iter()

    使请求对象可迭代,逐行返回请求体。

HttpRequest的属性和方法现在不必完全掌握,后面使用多了,自然就慢慢的记下来了,一般来说,做比学的影响更深刻

HttpResponse的属性和方法

HttpResponse的属性
  1. content:响应的内容,字节字符串。可以通过给该属性赋值来修改响应内容。

  2. charset:编码字符集,用于编码响应内容。默认为'utf-8'。

  3. status_code:HTTP状态码,例如200、404等。

  4. reason_phrase:HTTP状态短语,与状态码对应,例如200对应"OK",404对应"Not Found"。如果未设置,则使用默认短语。

  5. headers:响应头的类字典对象。可以通过此属性设置和查看响应头。

  6. cookies:用于设置Cookie的类字典对象。但通常使用set_cookie方法来设置。

  7. closed:布尔值,表示响应是否已关闭。

HttpResponse的方法
  1. init(content='', content_type=None, status=200, reason=None, charset=None):构造函数。

    content:响应内容,可以是字符串或字节。如果是字符串,将使用charset编码为字节。content_type:设置Content-Type头。如果未指定,默认为'text/html'。
    status:状态码。
    reason:状态短语,如果未指定,则使用默认短语。
    charset:编码字符集。
  2. set_cookie(key, value='', max_age=None, expires=None, path='/', domain=None, secure=False, httponly=False, samesite=None):设置一个Cookie。

    key:Cookie的名称。
    value:Cookie的值。
    max_age:Cookie的生存期,以秒为单位。
    expires:过期时间,可以是一个datetime对象或字符串。
    path:Cookie的路径。
    domain:Cookie的域。
    secure:如果为True,则只能通过HTTPS传输。
    httponly:如果为True,则客户端JavaScript无法访问。
    samesite:限制第三方使用Cookie,可选值为'Strict'、'Lax'或'None'。
  3. set_signed_cookie(key, value, salt='', max_age=None, expires=None, path='/', domain=None, secure=False, httponly=False, samesite=None):设置一个签名Cookie,防止篡改。参数与set_cookie类似,但多了一个salt参数用于签名。

  4. delete_cookie(key, path='/', domain=None):删除一个Cookie。实际上是通过设置过期时间为过去的时间来实现。

  5. write(content):将内容写入响应体。允许将响应对象视为文件对象。

  6. flush():清空响应内容。通常用于流式响应。

  7. tell():返回当前响应内容的位置(指针位置)。

  8. getvalue():返回响应内容(字节字符串)。

  9. readable():是否可读,返回False。

  10. seekable():是否可寻址,返回False。

  11. writable():是否可写,返回True。

  12. close():关闭响应,标记为已关闭。

  13. has_header(header):检查响应头中是否存在指定的头。

  14. setdefault(header, value):设置响应头,如果该头已存在则不设置。

  15. setitem(header, value):设置响应头。

  16. getitem(header):获取响应头的值。

  17. delitem(header):删除响应头。

  18. items():返回响应头的(键,值)对。

此外,HttpResponse还有一些子类,用于返回不同类型的响应,例如:

  • HttpResponseRedirect:重定向响应,状态码302。

  • HttpResponsePermanentRedirect:永久重定向,状态码301。

  • HttpResponseNotFound:404错误。

  • HttpResponseForbidden:403错误。

  • HttpResponseBadRequest:400错误。

  • HttpResponseServerError:500错误。

  • JsonResponse:返回JSON响应。

  • FileResponse:返回文件流响应。

简单使用和练习

# /blog/views
from django.shortcuts import render
from django.http import HttpResponse
# Create your views here.
def test(request):
    print("###############属性##################")
    print(request.get_host())
    print(request.path)
    print(request.get_full_path())
    print(request.get_full_path_info())
    print(request.method)
    print(request.GET)
    print(request.scheme)
    print(request.encoding)
    print("###################################")
    return HttpResponse("你好!Django!")
###############属性##################
127.0.0.1:8000
/blog/test/
/blog/test/
/blog/test/
GET
<QueryDict: {}>
http
None
###################################

视图处理函数

Django是一个高度封装的框架,对于一些重复底层的操作过程,django提供几个函数供我们调用

render()函数
# /blog/views
# 导入相关的包
from django.shortcuts import render
# Create your views here.
# 定义视图函数
def index_blog(request):
    # render函数实现渲染
    return render(request,'index/index.html',content_type=None,context_type=None,status=None,using=None)

# (function) def render(
#     request: HttpRequest,
#     template_name: str | Sequence[str],
#     context: Mapping[str, Any] | None = ...,
#     content_type: str | None = ...,
#     status: int | None = ...,
#     using: str | None = ...
# ) -> HttpResponse

render()函数 参数说明

request (HttpRequest)
必须参数。当前的请求对象,通常由视图函数接收。它包含关于当前请求的元数据,如用户、请求方法等。这个参数是必需的,因为渲染过程中可能需要请求的信息(例如,用于CSRF令牌、用户状态等)。

template_name (str 或 list of str)
必须参数。要使用的模板的名称。可以是一个字符串,也可以是字符串列表。如果是列表,Django 将按顺序尝试每个模板,并使用第一个找到的模板。

context (dict, 可选)
可选参数,默认为 None。要传递给模板的上下文数据,是一个字典。字典的键是模板中使用的变量名,值是要传递的变量值。

例如,如果 context 是 {'name': 'John'},那么在模板中就可以使用 {{ name }} 来显示 "John"。

content_type (str, 可选)
可选参数,默认为 None。用于设置 HTTP 响应头 Content-Type 的值。通常,Django 会自动设置为 'text/html',除非你指定其他内容类型。例如,如果你想返回一个 JSON 响应,可以设置为 'application/json',但注意此时模板应该输出 JSON 格式的文本。

默认情况下,Django 使用 'text/html'

status (int, 可选)
可选参数,默认为 None。响应的状态码。例如,如果要返回一个404错误,可以设置 status=404。默认情况下,状态码为200。

using (str, 可选)
可选参数,默认为 None。指定用于加载模板的模板引擎的名称。Django 可以配置多个模板引擎,使用此参数可以指定使用哪个引擎。如果未指定,则使用默认的模板引擎。

render函数的主要作用之一是通过参数渲染模板,下面做一个小示例

# /blog/views
from django.shortcuts import render
# Create your views here.
def test(request):
    return render(request,'index/test.html',context={'data':'你好!世界!'},content_type='text/html')
<!-- templates/index -->
<div>
    下面是接受的变量
    <br>
    {{data}}
</div>
# /blog/urls
from django.urls import path
from Blog import views

urlpatterns = [
    path('blog/test/',views.test),
]
redirect()函数 页面重定向

什么是页面重定向?就是网页被移到了一个新的地址,结构目录发生了变化,但整体改动太过复杂,所以使用网络重定向,访问旧网址时,让其指向新地址或者新的资源目录。

# 最基础的用法
from django.shortcuts import redirect

# 重定向到绝对URL
return redirect('https://www.google.com/')

# 重定向到相对URL
return redirect('/about/')
return redirect('../home/')

重定向到视图

# urls.py 中的配置示例
from django.urls import path
from . import views

urlpatterns = [
    path('', views.home, name='home'),               # 名称: home
    path('about/', views.about, name='about'),       # 名称: about
    path('user/<int:id>/', views.user, name='user'), # 名称: user
]
# views.py 中使用
def login(request):
    # 处理登录逻辑...
    
    # 登录成功后重定向到首页
    return redirect('home')  # 使用 URL 名称

def profile(request):
    # 重定向到关于页面
    return redirect('about')

带参重定向

# 重定向到带数字ID的用户页面
def view_user(request):
    user_id = 42
    return redirect('user', id=user_id)  # 会重定向到 /user/42/

# 或者使用 args 参数
return redirect('user', 42)  # 注意:按位置顺序传递参数
get_absolute_url() 重难点

这里我们详细根据代码,一步一步来理解这个函数的作用

1. 首先,创建模型

# blog/models.py
from django.db import models
from django.urls import reverse  # 重要:导入 reverse 函数,作用是生成url

class Note(models.Model):
    """
        简单的笔记模型
    """
    # 字段 = 数据类型 模型时会详细介绍
    title = models.CharField(max_length=100)
    content = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    
    def __str__(self):
        return self.title
    
    def get_absolute_url(https://blog.csdn.net/self):
        """
            返回这个笔记的详情页网址
            格式:/notes/1/ 或 /notes/2/ 等
        """
        # note_detail 就是urls中定义的名字
        # kwargs={'pk': self.pk} 的意思是:把当前对象的ID(self.pk)传递给名为 'pk' 的参数。
        return reverse('note_detail', kwargs={'pk': self.pk})
# /blog/urls
from django.urls import path
from Blog import views

urlpatterns = [
    path('blog/test/',views.test),
    # 笔记详情页:/notes/1/
    path('notes/<int:pk>/', views.note_detail, name='note_detail'),
    # 创建笔记页:/notes/new/
    path('notes/new/', views.note_create, name='note_create'),
    # 笔记列表页:/
    path('', views.note_list, name='note_list'),
]
# /blog/views
from django.shortcuts import get_object_or_404, redirect, render
from Blog.models import Note
# Create your views here.
def test(request):
    return render(request,'index/test.html',context={'data':'你好!世界!'},content_type='text/html')

def index_blog(request):
    return render(request,'index/index.html')

def note_list(request):
    """显示所有笔记"""
    notes = Note.objects.all()
    return render(request, 'notes/list.html', {'notes': notes})

def note_create(request):
    """创建新笔记"""
    if request.method == 'POST':
        # 1. 创建笔记
        note = Note.objects.create(
            title=request.POST['title'],
            content=request.POST['content']
        )
        
        # 2. 创建成功后,重定向到新笔记的页面
        # 这里会自动调用 note.get_absolute_url()
        return redirect(note)
    
    # 3. 如果是 GET 请求,显示创建表单
    return render(request, 'notes/create.html')

def note_detail(request, pk):
    """显示单个笔记详情"""
    note = get_object_or_404(Note, pk=pk)
    return render(request, 'notes/detail.html', {'note': note})
<!-- templates/notes/create.html -->
<!DOCTYPE html>
<html>
<head>
    <title>创建新笔记</title>
</head>
<body>
    <h1>创建新笔记</h1>
    
    <form method="POST">
        {% csrf_token %}
        <p>
            <label>标题:</label><br>
            <input type="text" name="title" required style="width: 300px;">
        </p>
        <p>
            <label>内容:</label><br>
            <textarea name="content" rows="10" style="width: 300px;"></textarea>
        </p>
        <button type="submit">保存</button>
        <a href="{% url 'note_list' %}">取消</a>
    </form>
</body>
</html>
<!-- templates/notes/detail.html -->
<!DOCTYPE html>
<html>
<head>
    <title>{{ note.title }}</title>
</head>
<body>
    <h1>{{ note.title }}</h1>
    <p><small>创建时间:{{ note.created_at }}</small></p>
    
    <div style="border: 1px solid #ccc; padding: 20px; margin: 20px 0;">
        <h3>内容:</h3>
        <p>{{ note.content|linebreaks }}</p>
    </div>
    
    <hr>
    
    <!-- 用不同方式显示当前笔记的网址 -->
    <p><strong>这个笔记的网址:</strong></p>
    <ul>
        <li>方法1:<code>{{ note.get_absolute_url }}</code></li>
        <li>方法2:<a href="{{ note.get_absolute_url }}">点击查看</a></li>
        <li>方法3:<a href="{{ note.get_absolute_url }}" target="_blank">在新窗口打开</a></li>
    </ul>
    
    <!-- 返回列表 -->
    <p><a href="{% url 'note_list' %}">返回笔记列表</a></p>
</body>
</html>
<!-- templates/notes/list.html -->
<!DOCTYPE html>
<html>
<head>
    <title>我的笔记</title>
</head>
<body>
    <h1>我的笔记列表</h1>
    
    <!-- 创建新笔记的链接 -->
    <a href="{% url 'note_create' %}">创建新笔记</a>
    
    <hr>
    
    <!-- 显示所有笔记 -->
    <ul>
        {% for note in notes %}
        <li>
            <!-- 使用 get_absolute_url() 生成链接 -->
            <a href="{{ note.get_absolute_url }}">
                {{ note.title }} (创建于: {{ note.created_at|date:"Y-m-d" }})
            </a>
        </li>
        {% empty %}
        <li>还没有笔记,快去创建吧!</li>
        {% endfor %}
    </ul>
</body>
</html>

详细解释

为社么,它的流程是怎么的,我知道这里会有很多问题,这个是为社么会是这样

def get_absolute_url(https://blog.csdn.net/self):
        """
        返回这个笔记的详情页网址
        格式:/notes/1/ 或 /notes/2/ 等
        """
        return reverse('note_detail', kwargs={'pk': self.pk})

找名字:找到名为 'note_detail' 的URL模式
看模板:发现模板是 notes/<int:pk>/               //urls中的路由哪里获取到的
填空格:把 self.pk 的值填到 <pk> 这个位置
得地址:得到 notes/5/ 这样的完整地址             //然后通过redirect  视图 - url 对应解析返回视图
def note_create(request):
    """创建新笔记"""
    if request.method == 'POST':
        # 1. 创建笔记
        note = Note.objects.create(
            title=request.POST['title'],
            content=request.POST['content']
        )
        
        # 2. 创建成功后,重定向到新笔记的页面
        # 这里会自动调用 note.get_absolute_url()
        return redirect(note)
    
    # 3. 如果是 GET 请求,显示创建表单
    return render(request, 'notes/create.html')
# 为什么会自动调用?
# 1. 你调用:redirect(note)
# 2. Django 内部检查:
#    - note 是什么类型? → Note 模型实例
#    - note 有 get_absolute_url 方法吗? → 有!
# 3. 自动调用:note.get_absolute_url()
# 4. 得到 URL:/notes/5/
# 5. 返回:HttpResponseRedirect('/notes/5/')

视图类

视图类提供get和post方法,不在需要去if判断,这无疑方便很多

视图类和视图函数的区别

# /blog/urls
from django.urls import path
from Blog import views
from Blog.views import TestPageView

urlpatterns = [
    path('blog/test/',views.test),
    path('blog/testclass/',TestPageView.as_view())
]
# /blog/views
from django.http import HttpResponse
from django.views import View
# Create your views here.
def test(request):
    if request.method == 'GET':
        return HttpResponse(f"视图函数获取到的请求为:{request.method}")
    if request.method == 'POST':
        return HttpResponse(f"视图函数获取到的请求为:{request.method}")
class TestPageView(View):
    def get(self,request):
        return HttpResponse(f"视图类获取到的请求为:{request.method}")
    def post(self,request):
        return HttpResponse(f"视图类获取到的请求为:{request.method}")

可以访问对应的uri,利用postman使用get和post不同的请求方式看一看效果,我这里就不展示了

# /blog/urls
from django.urls import path
from Blog import viewtest
urlpatterns = [
    # View类 - 需要调用 as_view() 方法
    path('', viewtest.HomeView.as_view(), name='home'),
    
    # ListView - 列表页
    path('articles/', viewtest.ArticleListView.as_view(), name='article_list'),
    
    # DetailView - 详情页 (需要传入ID)
    path('articles/<int:pk>/', viewtest.ArticleDetailView.as_view(), name='article_detail'),
]
# blog/viewtest.py
from django.views import View
from django.views.generic import ListView, DetailView
from django.http import HttpResponse
from .models import Article

# 1. 通用视图类(View)- 最基础
class HomeView(View):
    """首页 - 处理GET和POST请求"""
    def get(self, request):
        """处理GET请求"""
        return HttpResponse("这是首页 - GET请求")
    
    def post(self, request):
        """处理POST请求"""
        return HttpResponse("这是首页 - POST请求")

# 2. 列表视图类(ListView)- 显示列表
class ArticleListView(ListView):
    """文章列表页"""
    model = Article  # 告诉Django我要显示哪个模型的数据
    template_name = 'article_list.html'  # 模板名称
    
    # 默认:自动获取所有Article对象,传递给模板
    # 模板中默认变量名:object_list 或 article_list

# 3. 详细视图类(DetailView)- 显示详情
class ArticleDetailView(DetailView):
    """文章详情页"""
    model = Article  # 告诉Django我要显示哪个模型的数据
    template_name = 'article_detail.html'  # 模板名称
    
    # 默认:自动根据URL中的pk参数查找Article对象
    # 模板中默认变量名:object 或 article
# blog/models.py
from django.db import models
from django.urls import reverse

class Article(models.Model):
    title = models.CharField(max_length=100)
    
    def __str__(self):
        return self.title
    
    def get_absolute_url(https://blog.csdn.net/self):
        from django.urls import reverse
        return reverse('article_detail', kwargs={'pk': self.pk})
<!-- templates/article_detail.html -->
<!DOCTYPE html>
<html>
<body>
    <h1>文章详情</h1>
    
    <!-- 方式1:使用 object -->
    <h2>{{ object.title }}</h2>
    
    <!-- 方式2:使用 article(因为模型名是Article) -->
    <h2>{{ article.title }}</h2>
    
    <hr>
    <a href="/articles/">返回列表</a>
</body>
</html>
<!-- templates/article_list.html -->
<!DOCTYPE html>
<html>
<body>
    <h1>文章列表</h1>
    
    <!-- 方式1:使用 object_list -->
    {% for article in object_list %}
        <p><a href="{{ article.get_absolute_url }}">{{ article.title }}</a></p>
    {% endfor %}
    
    <!-- 方式2:使用 article_list(因为模型名是Article) -->
    {% for article in article_list %}
        <p><a href="{{ article.get_absolute_url }}">{{ article.title }}</a></p>
    {% endfor %}
    
    <hr>
    <a href="/">返回首页</a>
</body>
</html>

这里我使用了三种视图类来展示,分别是

通用视图类(View):最基本的类,需要自己编写get和post方法。

列表视图类(ListView):用于显示一个对象列表。

详细视图类(DetailView):用于显示单个对象的详细信息。

他们如何作用的,在代码中都详细注释

# 用户访问 / 时:
# 1. Django 找到 HomeView.as_view()
# 2. 创建 HomeView 实例
# 3. 调用实例的 dispatch() 方法
# 4. dispatch() 根据请求方法调用相应的 handler
# 5. 如果是 GET → 调用 get() 方法
# 6. 返回 HttpResponse
# ListView相当于帮你写了:
class ArticleListView(View):
    def get(self, request):
        articles = Article.objects.all()  # 自动获取所有数据
        return render(request, 'article_list.html', {
            'article_list': articles,      # 自动创建上下文
            'object_list': articles        # 自动创建上下文
        })
# DetailView相当于帮你写了:
class ArticleDetailView(View):
    def get(self, request, pk):
        article = Article.objects.get(pk=pk)  # 自动根据ID查找
        return render(request, 'article_detail.html', {
            'article': article,               # 自动创建上下文
            'object': article                 # 自动创建上下文
        })

一句话总结

View:我要自己处理所有请求(写 get()post()

ListView:我要显示一堆东西(自动获取所有数据)

DetailView:我要显示一个东西(自动根据ID查找)

MVT - 视图暂时到这里

最后问一个问题,什么是UDP?

就像 你不断向她发送数据包,但从来不会得到任何作为握手的回音。这注定是一场没有握手、没有连接、也没有回响的孤独传输,我的意思是,你的每一次自我感动,本身就得不到任何回应,但你依旧乐此不疲。丢包事故也在所不惜,这不是爱情的勇敢,而是自我感动式的沉沦。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值