MVVM模式不但可用于Form表单,在复杂的管理页面中也能大显身手。例如,分页显示Blog的功能,我们先把后端代码写出来:
在apis.py中定义一个Page类用于存储分页信息:
class Page(object): ''' Page object for display pages. ''' def __init__(self, item_count, page_index=1, page_size=8): ''' Init Pagination by item_count, page_index and page_size. >>> p1 = Page(100, 1) >>> p1.page_count 10 >>> p1.offset 0 >>> p1.limit 10 >>> p2 = Page(90, 9, 10) >>> p2.page_count 9 >>> p2.offset 80 >>> p2.limit 10 >>> p3 = Page(91, 10, 10) >>> p3.page_count 10 >>> p3.offset 90 >>> p3.limit 10 ''' self.item_count = item_count self.page_size = page_size self.page_count = item_count // page_size + (1 if item_count % page_size > 0 else 0) if (item_count == 0) or (page_index > self.page_count): self.offset = 0 self.limit = 0 self.page_index = 1 else: self.page_index = page_index self.offset = self.page_size * (page_index - 1) self.limit = self.page_size self.has_next = self.page_index < self.page_count self.has_previous = self.page_index > 1 def __str__(self): return 'item_count: %s, page_count: %s, page_index: %s, page_size: %s, offset: %s, limit: %s' % (self.item_count, self.page_count, self.page_index, self.page_size, self.offset, self.limit) __repr__ = __str__
在handlers.py中实现API:
## 获取日志列表API @get('/api/blogs') async def api_blogs(*, page='1'): page_index = get_page_index(page) num = await Blog.findNumber('count(id)') p = Page(num, page_index) if num == 0: return dict(page=p, blogs=()) blogs = await Blog.findAll(orderBy='created_at desc', limit=(p.offset, p.limit)) return dict(page=p, blogs=blogs)
在www/templates下创建blogs.html:
<!-- 继承父模板 '__base__.html' --> {% extends '__base__.html' %} <!--jinja2 title 块内容替换--> {% block title %}凹大卜{% endblock %} <!--jinja2 beforehead 块内容替换--> {% block beforehead %} {% endblock %} <!--jinja2 content 块内容替换--> {% block content %} <[email protected]是大于中等尺寸屏幕时显示的UI--> <!--日志列表内容--> <div class="uk-grid [email protected]"> <div class="uk-width-3-4"> {% for blog in blogs %} <article class="uk-article"> <h3><a href="/blog/{{ blog.id }}">{{ blog.name }}</a></h3> <p class="uk-article-meta">发表于{{ blog.created_at|datetime }}</p> <p>{{ blog.summary }}</p> <p><a href="/blog/{{ blog.id }}">继续阅读 <i class="uk-icon-angle-double-right"></i></a></p> </article> <hr> {% endfor %} <!--分页导航栏,在父模板的开头定义过--> {{ pagination(page) }} </div> <[email protected]是大于中等尺寸屏幕时显示的UI--> <!--右边侧导航栏--> <div class="uk-width-1-4 [email protected]"> <h4>站内搜索</h4> <FORM method=GET action="https://www.google.com/search"> <div class="uk-inline"> <a class="uk-form-icon uk-form-icon-flip" href="#" uk-icon="search"></a> <INPUT class="uk-input" TYPE=text name=q placeholder="站内搜索" size=31 maxlength=255 value=""> </div> <font size=-1> <INPUT TYPE=hidden name=domains value="woodmanzhang.com"><br> <INPUT TYPE=hidden name=sitesearch value="woodmanzhang.com"></br> </font> <button TYPE=submit name=btnG class="uk-button uk-button-default"> SEARCH</button> </FORM> <h4>亲密链接</h4> <ul class="uk-list uk-list-divider"> <li><a target="_blank" href="https://woodmanzhang.com/" rel="noopener noreferrer">木人张</a></li> </ul> </div> </div> <[email protected]是小于中等尺寸屏幕时显示的UI--> <!--移动屏幕时日志列表排版--> <div class="[email protected]"> {% for blog in blogs %} <article class="uk-article"> <h5><a href="/blog/{{ blog.id }}">{{ blog.name }}</a></h5> <p class="uk-article-meta">发表于{{ blog.created_at|datetime }}</p> <p>{{ blog.summary }}</p> <p><a href="/blog/{{ blog.id }}">继续阅读 <i class="uk-icon-angle-double-right"></i></a></p> </article> <hr> {% endfor %} <!--分页导航栏,在父模板的开头定义过--> {{ pagination(page) }} </div> {% endblock %}