就是 “列表视图” 别被名字吓到了 这是最简单的视图构建“套路”
就是在指定的数据库(类)中取出所有数据 然后列表显示出来
比如像百度那种就是典型的
还记得上节 我们是编辑过view的
像这样从数据库取数据:
num_books = Book.objects.all().count()
num_instances = BookInstance.objects.all().count()
num_instances_available = BookInstance.objects.filter(status__exact='a').count()
num_authors = Author.objects.count() # The 'all()' is implied by default.
然后 context打包 通过render送到template那边去填空:
context = {
'num_books': num_books,
'num_instances': num_instances,
'num_instances_available': num_instances_available,
'num_authors': num_authors,
'num_visits': num_visits,
}
# Render the HTML template index.html with the data in the context variable.
return render(request, 'index.html', context=context)
不过上次有点不同 需要统计数据(多少本书什么的) 用了count()
这里 我们更加傻瓜化——直接把数据库所有书倒出来 然后一列显示就ok了
django给我们封装了这种傻瓜化的view处理 就是Listview
而且用as_view() 函数来执行
具体操作很简单
1.catalog/view.py 添加:
from django.views import generic
class BookListView(generic.ListView):
model = Book
BookListView 针对数据库Book模型的ListView
模板编辑:{% extends "base_generic.html" %}
{% block content %}
Book List
{% if book_list %}
{% for book in book_list %}
-
{{ book.title }} ({{book.author}})
{% endfor %}
{% else %}
There are no books in the library.
{% endif %}
{% endblock %}
当然 URL映射别忘了:
urlpatterns = [
path('', views.index, name='index'),
path('books/', views.BookListView.as_view(), name='books'),
path('authors/', views.AuthorListView.as_view(), name='authors'),
]
我们可以发现
模板的名字 book_list.html 模板变量 就是那个{% for book in book_list %} 引用的book_list 这个变量奇怪不?我们从来没定义过 怎么就能用了呢?
这就是ListView帮我们干的事 当然也约定 模板名字与模板变量都采用model那个类的名字+list
class book ->book_list
事实上 是一个函数为get queryset 做了 从数据库拿数据到view的工作
因此 我们通过修改这个函数 自然也可以控制输出的结果‘
实现这点 ’
class BookListView(generic.ListView):
model = Book
paginate_by = 4
def get_queryset(self):
return Book.objects.filter(title__icontains='ryan')[:5] # Get 5 books containing the title war
筛选所有title包含ryan的数据记录 然后返回给render
另外 paginate_by = 4
限制了一页中显示最大的记录条数
类似sql的LIMIT BY
然后这里我们就可以runserver一下啦:
我们只是作了个书的清单 但是详情页还没弄
这里 先把book_list.html 修改一下
{% for book in book_list %}
{{ book.title }} ({{book.author}})
{% endfor %}
主要是超链接的内容加上了
然后我们大胆的添加书本的详情页 url映射
urlpatterns = [
path('', views.index, name='index'),
path('books/', views.BookListView.as_view(), name='books'),
path('authors/', views.AuthorListView.as_view(), name='authors'),
path('book/', views.BookDetailView.as_view(), name='book-detail'),
path('author/', views.AuthorDetailView.as_view(), name='author-detail'),
]
author的套路相同 一并添加了:)
这里 就类似正则表达式 捕获url地址中 author/
后面所有的数字 并且存到pk
这个变量里面
如果url捕获参数的模式(pattern) 很复杂 欢迎使用re_path() 函数代替path() 并且使用re正则表达式
这里限于篇幅不讲了 网上有关教程很多
我们应用repath 可以这么写:
re_path(r'^book/(?P\d+)$', views.BookDetailView.as_view(), name='book-detail'),
注意path()不采用·正则 其语法规则很简单 功能很弱
re_path()是完全用正则表达式的 功能无敌强
ListView特别适合 大致列个表 这种应用 目录菜单什么的
然而detailview提供一个适合“详情页”的布局视图
非常类似ListView 你只需在catalog/view.py 中添加:
class BookDetailView(generic.DetailView):
model = Book
同样 book_detail 作为模板的文件名称:
不过模板变量变成model的类名 book
在catalog/templates/catalog/book_detail.html 填写:
{% extends "base_generic.html" %}
{% block content %}
Title: {{ book.title }}
Author: {{ book.author }}
Summary: {{ book.summary }}
ISBN: {{ book.isbn }}
Language: {{ book.language }}
Genre: {% for genre in book.genre.all %} {{ genre }}{% if not forloop.last %}, {% endif %}{% endfor %}
Copies
{% for copy in book.bookinstance_set.all %}
{{ copy.get_status_display }}
{% if copy.status != 'a' %}Due to be returned: {{copy.due_back}}
{% endif %}
Imprint: {{copy.imprint}}
Id: {{copy.id}}
{% endfor %}
{% endblock %}
注意“book.bookinstance_set”
首先 book 与 bookinstance 是外键 而且是一对多的
我们这里在book这端 用“一”引用多 就用了book.bookinstance_set 这是django给我们封装好的
我们之前通过paginate_by = 10 进行分页 但这只是源头上限制了数据 但不能实现“前一页”“后一页”的按钮等
django封装了这个
由于我们几乎所有网页都这样式 我们直接在base_generic 更改:
打开 /locallibrary/catalog/templates/base_generic.html
{% block content %}{% endblock %}
{% block pagination %}
{% if is_paginated %}
{% endif %}
{% endblock %}
page_obj 是一个 Paginator 对象,如果在当前页面上使用分页 如paginate_by = 10 ,它将启动
这玩意允许您获取有关当前页面,之前页面,有多少页面等的所有信息。
{{ request.path }}可用来获取用于创建分页链接的当前页面URL。
另外 我们顺便把author的也弄了:
模板 template/catalog/author_detail.html:
{% extends "base_generic.html" %}
{% block content %}
{{ author.first_name }}.{{author.last_name}}
living: {{ author.first_name }}.{{ author.last_name }} ({{ author.date_of_birth }}-{{ author.date_of_death }})
What this poor bastard wrote:
{% for copy in author.book_set.all %}
- 《{{copy.title}}》 ISBN:{{copy.isbn}}
{% endfor %}
{% endblock %}
模板 template/catalog/author_list.html:
{% extends "base_generic.html" %}
{% block content %}
Author List
{% if author_list %}
{% for author in author_list %}
-
{{ author.first_name }}.{{ author.last_name }}
{% endfor %}
{% else %}
There are no one.
{% endif %}
{% endblock %}
catalog/view.py 添加
class AuthorListView(generic.ListView):
model = Author
paginate_by = 5
class AuthorDetailView(generic.DetailView):
model = Author
结语( ̄︶ ̄)↗
runserver检验战果
不出意外 你将收获:
到这里 基本上很多页面都能搞定了
下一站 我们会聊聊 会话
这是软菜鸡的其他系列学习文章 希望能够帮到你 ( •̀ ω •́ )✧
想学习数据库嘛? 不妨从MySQL入手
MySQL专栏
python这么火 想要深入学习python 玩一下简单的应用嘛?可以看我专栏 还在持续更新中哦:
python应用
这是本服务端编程专栏
手把手带你学服务端
谢谢大佬支持!