模板创建好之后,自然需要用来显示内容了。我们要达到目的访问127.0.0.1:8000/article可以显示出文章列表,点击文章标题可以链接到具体文章页面,访问127.0.0.1:8000/article/1,127.0.0.1:8000/article/2....可以显示出标题,内容。
一、查看article app的数据库迁移文件
demo article migrations 0001_initial.py
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=40)),
('content', models.TextField()),
],
可以看到里面除了有我们创建的title
,content
字段外,还有一个自动创建字段id
,而且是主键,作为唯一标识。
二、在article app
的views.py
文件中编写处理方法
demo article views.py
from django.shortcuts import render
from django.http import HttpResponse
# Create your views here.
def article_detail(request, article_id):
return HttpResponse("文章ID %s" % article_id)
三、在总路由urls.py
文件里添加新的url
demo urls.py
导入
article_detail
方法用于显示具体页面,增加一个新的path用于处理article/id
页面,<int:article_id>
代表传入的是int类型,name='article_detail'
是别名
from django.contrib import admin
from django.urls import path
from .views import say_hello
from article.views import article_detail
urlpatterns = [
path('admin/', admin.site.urls),
path('', say_hello),
path('article/<int:article_id>',article_detail, name='article_detail')
]
四、启动服务,查看运行情况
命令python manage.py runserver
可以看到如我们预期一样输出了结果
五、导入app模型到article app
的views.py
文件
article views.py
为了让app模型中的文章像上面一样显示出来,需要导入模型,并获取到模型的一个实例对象。
from django.shorcuts import render
from django.http import HttpResponse
from .models import Article
# Create your views here.
def article_detail(request, article_id):
# 通过主键id字段获取模型的实例对象
article = Article.objects.get(id=article_id)
return HttpResponse("文章ID:%s 文章标题:%s 文章内容:%s" % (article.id, article.title, article.content))
六、再次启动服务
启动服务,访问127.0.0.1:8000/article/1、127.0.0.1:8000/article/2....
这样输出结果不美观,我们可以进行优化,加入换行。
在article views.py
中加入html
代码
from django.contrib import render
from django.http import HttpResponse
from .models import Article
# Create your views here.
def article_detial(request, article_id):
article = Article.objects.get(id=article_id)
return HttpResponse("文章ID:%s<br>文章标题:%s<br>文章内容:%s" % (article.id, article.title, article.content))
刷新页面后显示
但是这种前后端耦合在一起的做法显然不合适,以后要修改的时候会特别麻烦。另外当访问
127.0.0.1:8000/article/5
之类不存在的网页时还会报错,需要做异常处理
七、代码的优化
- 访问不存在的页面时候进行异常处理
当访问的页面不存在时显示404
article views.py
from django.contrib import render
from django.http import HttpResponse,Http404
from .models import Article
# Create your views here.
def article_detail(request, article_id):
try:
article = Article.objects.get(id=article_id)
except Article.DoesNotExist:
raise Http404("Not exist")
return HttpResponse("文章ID:%s<br>文章标题:%s<br>文章内容:%s" % (article.id, article.title, article.content))
再次访问127.0.0.1:8000/article/5
,可以得到404显示页面
还可进一步优化如下
get_object_or_404
自动做了异常处理,传入的参数第一个个为模型,第二个为选择的条件
from django.contrib import render,get_object_or_404
from django.http import HttpResponse
from .models import Article
# Create your views here.
def article_detail(request, article_id):
# pk主键的缩写
article = get_object_or_404(Article, pk=article_id)
return HttpResponse("文章ID:%s<br>文章标题:%s<br>文章内容:%s" % (article.id, article.title, article.content))
再次访问127.0.0.1:8000/article/5
- 耦合代码的前后端分离
1、在article
文件夹下面创建一个文件夹templates
,在templates
文件夹里面创建一个article_detail.html
文件。
2、修改article views.py
文件
from django.contrib import render,get_object_or_404
from django.http import HttpResponse
from .models import Article
# Create your views here.
def article_detail(request, article_id):
article = get_object_or_404(Article, pk=article_id)
context = {}
context['article_obj'] = article
# render第一个参数为request,第二个参数为html模板,第三个参数为键值为article对象的字典
return render(request, 'article_detail.html', context)
3、修改article templates article_detail.html
文件
<html>
<head>
</head>
<body>
<h2>
{{article_obj.title}}
</h2>
<hr>
<p>
{{article_obj.content}}
</p>
</body>
</html>
4、再次访问127.0.0.1:8000/article/1
可以正常显示,也完成了前后端分离
ps:除了render外,还有一个render_to_response也能用于返回response,不同的是,render_to_response只需要传入后两个参数
# return render(request, 'article_detail.html', context)
# 以下代码可以得到相同的结果
return render_to_response('article_detail.html', context)
八、编写文章列表
为了让127.0.0.1:8000/article显示出文章列表,同样需要编写路由文件、html模板文件以及与处理方法文件。
-
在
templates
文件夹下面新建一个article_list.html
文件 -
编写
article views.py
文件from django.contrib import render,get_object_or_404,render_to_response from django.http import HttpResponse from .models import Article # Create your views here. def article_detail(request, article_id): article = get_object_or_404(Article, pk=article_id) context = {} context['article_obj'] = article return render_to_response('article_detail.html', context) def article_list(request): # 使用all()获取所有列表 article_list = Article.objects.all() context = {} context['article_list_obj'] = article_list return render_to_response('article_list.html', context)
-
在总路由添加路径和处理方法,
demo urls.py
from django.contrib import admin from django.urls import path from .views import say_hello from articles.views import article_detail,article_list urlpatterns = [ path('admin/', admin.site.urls), path('', say_hello), path('article/<int:article_id>', article_detail, name='article_detail'), path('articl/', article_list, name='article_list') ]
-
修改模板文件
templates article_list.html
<html>
<head>
</head>
<body>
<h2>{{article_list_obj}}</h2>
</body>
</html>
- 访问
127.0.0.1:8000/article
页面,得到的是一个QuerySet类型的列表
- 在
template article_list.html
中修改为for
循环遍历出值
<html>
<head>
</head>
<body>
{% for article in article_list_obj %}
<p>{{ article.title }}</p>
{% endfor %}
</body>
</html>
刷新127.0.0.1:8000/article
页面
我们需要让标题变为一个可链接的,点击标题可以直接进入正文。
进一步对templates article_list.html
进行修改。
增加一个href属性用于链接
<html>
<head>
</head>
<body>
{% for article in article_list_obj %}
<a href="/article/{{article.pk}}">{{article.title}}</a>
{% endfor %}
</body>
</html>
此时再次刷新127.0.0.1:8000/article
可以看到文章列表可以点击,而且可以链接到文章正文了。
还可以使用别名对代码进行进一步优化
template article_list.html
article_detail
是article/<int:article_id>
的别名,之前定义在demo urls.py
文件中。
<html>
<head>
</head>
<body>
{% for article in article_list_obj %}
<a href="{% url 'article_detail' article.pk %}">{{article.title}}</a>
{% endfor %}
</body>
</html>
九、路由优化
一个项目是由多个app组成的,如果所有app的路由都设置到
demo urls.py
文件中的话,会导致文件越来越复杂,以后修改也比较困难。所以需要对路由进行优化,让各个app处理自己的路由。
- 在
demo article
文件夹下面新建一个urls.py
文件,编写如下
from django.urls import path
from . import views
urlpatterns = [
path('<int:article_id>', views.article_details, name='article_details'),
path('', views.article_list, name='article_list')
]
- 修改总路由,使用
include
将子路由与总路由关联起来,demo urls.py
from django.contrib import admin
from django.urls import path,include
from .views import say_hello
urlpatterns = [
path('admin/', admin.site.urls),
path('', say_hello),
path('article', include('article.urls'))
]
- 再次运行
localhost:8000/article
可以得到同样的结果。