模型的Objects
获取或操作模型的对象
1. views.py
要怎么写
在第三课创建好应用后,打开应用目录显示如下:
其中,templates
文件夹和urls.py
是我后创建的。其他都是一开始就有的。
在经过上节课一番折腾后,我们来到了写views.py
的环节。这次views.py
是已经自带了,不需要手动创建。初始代码如下:
# views.py
from django.shortcuts import render
# Create your views here
除了import
了一个模块之后便再无其他内容。需要我们手写。
先去models.py
定义model
如下:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from django.db import models
# Create your models here.
class Article(models.Model): # 从models中找字段类型
title = models.CharField(max_length = 30)
content = models.TextField()
然后回到views.py
,重新定义:
from django.shortcuts import render
from .models import Article
from django.http import HttpResponse
# Create your views here
def article_detail(request, article_id):
article = Article.objects.get(id = article_id)
return HttpResponse("文章内容是{} <br> 标题是{}".format(article.title, article.content))
这样一来,我们就可以在页面中显示文章内容与标题了。但由于Django是后端框架,这样写反而是前后端代码混一起了,违背了我们“前后端分离”的原则,所以怎样把前端代码从后端中剥离出来呢?
首先,新建templates
文件夹,用于存放html代码。这是Django固定语法,不要叫别的名字。
然后,根据实际情况建立对应的html文件。比如,显示文章细节,则需要article_detail.html
。这时候默认引入的render
方法开始起作用了。我们要将HttpResponse("文章内容是{} <br> 标题是{}".format(article.title, article.content))
这一行代码换成render
方法可以做如下变换:
from django.shortcuts import render
from .models import Article
# Create your views here
def article_detail(request, article_id):
article = Article.objects.get(id = article_id)
context = dict()
context["article"] = article
return render(request, "article_detail.html", context)
同时,在templates
文件夹下的article_detail.html
可以这样写:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Article Detail</title>
</head>
<body>
<h2>{{ article.title }}</h2>
<!---article.title就是原models.py中的article对象属性,用两个圆括号括起来--->
<hr>
<p>{{ article.content }}</p>
</body>
</html>
可以看到上面的html代码中的<h2>{{ article.title }}</h2>
一行。这一行是Django模板的应用。更多关于模板的可以点这里。下面一行还有模板。
但这样写的views.py
还有一个问题。就是当文章不存在时,怎么返回404信息?于是我们发现django.http
有一个Http404
方法可以使用,于是我们可以引入它。
from django.http import Http404
经过优化后,代码可以变成如下形式:
# views.py
from django.shortcuts import render
from django.http import Http404
from .models imprt Article
# Create your views here
def article_detail(request, article_id):
try:
article = Article.objects.get(id = article_id)
context = dict()
context["article"] = article
return render(request, "article_detail.html", context)
except Article.DoesNotExist:
raise Http404("文章不存在!")
但这样写的话依然很复杂,有没有一个方法,可以在正常时返回结果,错误时返回404呢?有的。get_object_or_404
可以达到这一点。
from django.shortcuts import get_object_or_404
同样,render
方法可以被简化为:
from django.shortcuts import render_to_response
通过一通操作后,我们的代码可以简化为:
# views.py
from django.shortcuts import render_to_response, get_object_or_404
from .models imprt Article
# Create your views here
def article_detail(request, article_id):
article = get_object_or_404(Article, pk = article_id)
context = dict()
context["article"] = article
return render_to_response("article_detail.html", context)
如果我们还想定义一个文章列表的view
,那么可以这样操作:
# views.py
from django.shortcuts import render_to_response, get_object_or_404
from .models imprt Article
# Create your views here
def article_detail(request, article_id):
article = get_object_or_404(Article, pk = article_id)
context = dict()
context["article"] = article
return render_to_response("article_detail.html", context)
def article_list(request):
articles = Article.objects.all() # 用对象.objects方法
context = dict()
context["articles"] = articles
return render_to_response("article_list.html", context)
同理,我们还需要定义article_list.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Article List</title>
</head>
<body>
{% for article in articles %}
<a href = {% url "article_id" article.pk %}>{{ article.title }}</a>
{% endfor %}
</body>
</html>
中间的这段代码非常显眼:
{% for article in articles %}
<a href = {% url "article_id" article.pk %}>{{ article.title }}</a>
{% endfor %}
-
{% %}
这是模板语法。 -
{% for %}
:模板中使用for循环的标志,常与{% endfor %}
搭配使用。 -
{% url %}
:url标签。后面两个参数,article_id
是我们在urls.py
中指定的别名。path("article/<int:article_id>", article_detail, name = "article_id"),
。这就是前面为什么urls.py
中为什么要指定name参数的原因了。article.pk
指的是article = get_object_or_404(Article, pk = article_id)
中的pk = article_id
而写的。这个标签意思是article.title
显示标题,链接指向具体的文章。
于是乎,这样一来我们就实现了前后端分离。
2. 分会场路由
我在article中另创建了一个urls.py
,意思是每个应用都应有每个应用的路由。这样一来就不用总是去总应用中的urls.py
中改来改去了。
这样做的好处是每个应用都可以创建自己的路由,不用改来改去了,节省代码量。
先看一下总应用中怎样包括分应用路由的说明:
Including another URLconf
- Import the include() function: from django.urls import include, path
- Add a URL to urlpatterns: path('blog/', include('blog.urls'))
翻译一下:
- 开头引入
include()
函数; - 在
urlpatterns
列表中可以写元素如右:path('blog/', include('blog.urls'))
于是乎,我们的总会场的urls.py
可以修改如下:
from django.contrib import admin
# from django.urls import path
from django.urls import include,path # 引入include函数
from .views import index
# from article.views import article_detail, article_list
urlpatterns = [
path('admin/', admin.site.urls),
path("", index),
# path("article/<int:article_id>", article_detail, name = "article_id"), #原代码,被我注释掉了
# path("article/", article_list, name = "article_list"), # 原代码,被我注释掉了
path("article/", include("article.urls")), # 新代码,可以看到我们用了include函数之后是什么样的
]
那么,分会场的urls.py
要怎么写呢?
- 首先,仿照总会场,
from django.urls import path
和定义urlpatterns
列表是必须的。 - 然后,引入本应用的
views
。可以写作from . import views
- 最后,改一下总会场被我注释的两行代码即可写成。
最终效果如下:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from django.urls import path
from . import views
urlpatterns = [
path("<int:article_id>", views.article_detail, name="article_id"), # 相对路径即可
path("", views.article_list, name="article_list"), # 已经在总会场指定了分会场的上级路由是"articles/"了,就不需要做重复工作了
]
这样一来,分会场的urls.py
便定义完成了。