服务端编程(十)- Django -创建网站页面

前言 ´・ᴗ・`

  • 上一节我们建立了主页 这里我们来创建一些别的网页 比如关于books author等等
  • 本篇内容将会帮助你学习…
    • 1 ListView的应用
    • 2 DetailView的应用

Listview

就是 “列表视图” 别被名字吓到了 这是最简单的视图构建“套路”
就是在指定的数据库(类)中取出所有数据 然后列表显示出来
比如像百度那种就是典型的
在这里插入图片描述
还记得上节 我们是编辑过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

  1. 模板编辑:
    创建: /locallibrary/catalog/templates/catalog/book_list.html
{% extends "base_generic.html" %}

{% block content %}
    <h1>Book List</h1>

    {% if book_list %}
    <ul>

      {% for book in book_list %}
      <li>
        <a href="">{{ book.title }}</a> ({{book.author}})
      </li>
      {% endfor %}

    </ul>
    {% else %}
      <p>There are no books in the library.</p>
    {% 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

ListView 的细节修改

事实上 是一个函数为get queryset 做了 从数据库拿数据到view的工作
因此 我们通过修改这个函数 自然也可以控制输出的结果
实现这点 ’

  • 可以从前端搞定 前端js当然可以限制 动态输出
  • 也可以后端限制 通过django支持的模板的一些分支语句(if else)
  • 还可以源头上 数据库调用的时候就减少数据传输
    这里更改get queryset算是第三种方式 举例:
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 %}
      <li>
        <a href="{{ book.get_absolute_url }}">{{ book.title }}</a> ({{book.author}})
      </li>
      {% 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/<int:pk>', views.BookDetailView.as_view(), name='book-detail'),
    path('author/<int:pk>', views.AuthorDetailView.as_view(), name='author-detail'),
    ]

author的套路相同 一并添加了:)
这里 <> 就类似正则表达式 捕获url地址中 author/ 后面所有的数字 并且存到pk这个变量里面

如果url捕获参数的模式(pattern) 很复杂 欢迎使用re_path() 函数代替path() 并且使用re正则表达式
这里限于篇幅不讲了 网上有关教程很多
我们应用repath 可以这么写:

re_path(r'^book/(?P<pk>\d+)$', views.BookDetailView.as_view(), name='book-detail'),

注意path()不采用·正则 其语法规则很简单 功能很弱
re_path()是完全用正则表达式的 功能无敌强

detailView

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 %}
  <h1>Title: {{ book.title }}</h1>

  <p><strong>Author:</strong> <a href="">{{ book.author }}</a></p> <!-- author detail link not yet defined -->
  <p><strong>Summary:</strong> {{ book.summary }}</p>
  <p><strong>ISBN:</strong> {{ book.isbn }}</p> 
  <p><strong>Language:</strong> {{ book.language }}</p>  
  <p><strong>Genre:</strong> {% for genre in book.genre.all %} {{ genre }}{% if not forloop.last %}, {% endif %}{% endfor %}</p>  

  <div style="margin-left:20px;margin-top:20px">
    <h4>Copies</h4>

    {% for copy in book.bookinstance_set.all %}
    <hr>
    <p class="{% if copy.status == 'a' %}text-success{% elif copy.status == 'm' %}text-danger{% else %}text-warning{% endif %}">{{ copy.get_status_display }}</p>
    {% if copy.status != 'a' %}<p><strong>Due to be returned:</strong> {{copy.due_back}}</p>{% endif %}
    <p><strong>Imprint:</strong> {{copy.imprint}}</p>
    <p class="text-muted"><strong>Id:</strong> {{copy.id}}</p>
    {% endfor %}
  </div>
{% 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 %}
      <div class="pagination">
          <span class="page-links">
              {% if page_obj.has_previous %}
                  <a href="{{ request.path }}?page={{ page_obj.previous_page_number }}">previous</a>
              {% endif %}
              <span class="page-current">
                  Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
              </span>
              {% if page_obj.has_next %}
                  <a href="{{ request.path }}?page={{ page_obj.next_page_number }}">next</a>
              {% endif %}
          </span>
      </div>
  {% endif %}
{% endblock %} 
  • page_obj 是一个 Paginator 对象,如果在当前页面上使用分页 如paginate_by = 10 ,它将启动
    这玩意允许您获取有关当前页面,之前页面,有多少页面等的所有信息。

  • {{ request.path }}可用来获取用于创建分页链接的当前页面URL

另外 我们顺便把author的也弄了:
模板 template/catalog/author_detail.html:

{% extends "base_generic.html" %}

{% block content %}
  <h1> {{ author.first_name }}.{{author.last_name}}</h1>
  <p><strong>living:</strong> {{ author.first_name }}.{{ author.last_name }} ({{ author.date_of_birth }}-{{ author.date_of_death }})</p>

  <div style="margin-left:20px;margin-top:20px">
    <h4>What this poor bastard wrote:</h4><ul>
<!-- 这里反向查找 ‘多’引用‘一’ 而不像之前的 ‘一’引用‘多’ -->
    {% for copy in author.book_set.all %}
      <li><a href="">《{{copy.title}}》 ISBN:{{copy.isbn}}</a></li>
    {% endfor %}
  </ul>
  </div>
{% endblock %}

模板 template/catalog/author_list.html:

{% extends "base_generic.html" %}

{% block content %}
    <h1>Author List</h1>

    {% if author_list %}
    <ul>

      {% for author in author_list %}
      <li>
        <a href="{{ author.get_absolute_url }}">{{ author.first_name }}.{{ author.last_name }}</a>
      </li>
      {% endfor %}

    </ul>
    {% else %}
      <p>There are no one.</p>
    {% endif %}
{% endblock %}

catalog/view.py 添加

class AuthorListView(generic.ListView):
    model = Author
    paginate_by = 5
    
class AuthorDetailView(generic.DetailView):
    model = Author

结语( ̄︶ ̄)↗

runserver检验战果
不出意外 你将收获:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
到这里 基本上很多页面都能搞定了
下一站 我们会聊聊 会话
服务端编程(十一)- Django - session 认识会话 cookies

这是软菜鸡的其他系列学习文章 希望能够帮到你 ( •̀ ω •́ )✧

  • 想学习数据库嘛? 不妨从MySQL入手
    MySQL专栏

  • python这么火 想要深入学习python 玩一下简单的应用嘛?可以看我专栏 还在持续更新中哦:
    python应用

  • 这是本服务端编程专栏
    手把手带你学服务端

  • 谢谢大佬支持!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值