图书推荐系统(七)之应用配置rank

1、url配置

rank目录添加urls.py

from django.conf.urls import url
from rank.views import score,tag,all

urlpatterns = [
    url(r'^score/$', score),
    url(r'^tag/$', tag),
    url(r'all/$',all),
]

2、index应用目录结构

├── index
    │   ├── __init__.py  # 配置应用
    │   ├── admin.py   # 提供django.contrib.admin 模块管理我们创建的数据模型
    │   ├── apps.py
    │   ├── migrations  # 是一个文件夹,用于数据模型与数据库结构的同步
    │   ├── models.py  # 用于定义数据模型
    │   ├── tests.py      # 供单元测试使用
    │   └── views.py     # 是写主要的业务逻辑的地方
		│   └── urls.py     
		

3、视图和模板

分为三个模块,分别是高分榜、标签榜单、所有图书。 首先用户登录,将用户名写入session,若未登录,则跳转到登录界面login.html (1)高分榜 @views.py

1)从数据库Book表筛选出评分高于9.5的前100本图书,逆序排列; 2)分页,每页展示20条内容 3)传参到rank.html

def score(request):
    # 登录是将用户写入session,此时若获取不到,则返回错误
    username = request.COOKIES.get('name')
    # 如果用户未登录
    if not username:
        return render_to_response('login.html',{
            'error':'用户未登录,请先登录!',
            'user_name':"",
            'user_pwd':"",
        })
    # 筛选出评分高于9.5的前100本图书,"-bookscore"表示逆序
    books = Book.objects.filter(bookscore__gt=9.5).order_by("-bookscore")[:100]

    # 分页,每页展示20条内容
    paginator = Paginator(books, 20)
    #寻找名为page的GET参数
    page = request.GET.get('page')
    try:
        new_book = paginator.page(page)
    except PageNotAnInteger:
        # 若页数不是整数,转向第一页
        new_book = paginator.page(1)
    except EmptyPage:
        # 若页数超出范围了,转向结果最后一页,paginator.num_pages表示页面总数
        new_book = paginator.page(paginator.num_pages)
    return render_to_response("rank.html",{
        "user_name":username,
        "books":new_book,
        "type":1,
        "len_list":range(1,paginator.num_pages + 1),
    })

@rank.html 1)设置表头 2)从views.py获取books,采用for循环传递图书信息 3)采用Django自带的Paginator分页工具。 补充:Paginator分页步骤: 获取要展示的对象列表,将列表和每页个数传递给Paginator,返回一个分页对象,调用该对象的各种方法,获取各种分页信息,在HTML模板中,使用上面的分页信息构建分页栏。

<!--高分榜-->
        {% ifequal type 1 %}
            <ul class="rankcan">
                <li class="recomtitle">
                    <span>封面</span>
                    <div>
                        <span>书名</span>
                        <span>综合评分</span>
                        <span>查看详情</span>
                        <span>相关标签</span>
                    </div>
                </li>
                <!--数据循环部分-->
                {% for book in books %}
                    <li class="recomitem">
                        <img src="/static/bookimg/{{ book.bookid }}.jpg">
                        <div>
                            <span>{{ book.bookname }}</span>
                            <span>{{ book.bookscore }}</span>
                            <span><a href="https://book.douban.com/subject/{{ book.bookid }}" target="_blank">查看详情</a></span>
                            <span class="sign">
                                {% for tag in book.tag_split %}
                                    <a class="badge badge-default">{{ tag }}</a>
                                {% endfor %}
                            </span>
                        </div>
                    </li>
                {% endfor %}
                <!--数据循环部分end-->
            </ul>
        <!--翻页-->
            <div class="eassy-page pagen">
                <ul class="pagination page-list">
                    <li class="previous">
                        {% if books.has_previous %}
                            <a href="?page={{ books.previous_page_number }}"><span>&laquo;</span></a>
                        {% else %}
                            <a><span>&laquo;</span></a>
                        {% endif %}
                    </li>
                    {% for page in len_list %}
                        <li><a href="?page={{ page }}"></a></li>
                    {% endfor %}
                    <li class="next">
                        {% if books.has_next %}
                        <a href="?page={{ books.next_page_number }}"><span>&raquo;</span></a>
                        {% else %}
                            <a><span>&raquo;</span></a>
                        {% endif %}
                    </li>
                </ul>
            </div>
        {% endifequal %}
        <!--高分榜end-->

(2)标签榜 1)加载离线计算好的标签榜单文件,排序 2)传递参数到rank.html @views.py

def tag(request):
    # 登陆是将用户写入session,此时若获取不到,则返回错误
    username = request.COOKIES.get('name')
    # 如果用户为登陆
    if not username:
        return render_to_response('login.html', {
            'error': "用户未登陆,请先登陆!",
            'user_name': "",
            'user_pwd': ""
        })

    # 加载离线计算好的标签榜单
    if os.path.exists(tags_path):
        tags_dict = dict(json.load(open(tags_path,"r")))
    else:
        print("标签统计结果文件不存在,请检查!")

    new_tags_sorted_dict = sorted(tags_dict.items(),key=lambda k:k[1], reverse=True)
    return render_to_response("rank.html",{
        "user_name":username,
        "tags":new_tags_sorted_dict,
        "type":2
    })

@rank.html

<!--标签云-->
        {% ifequal type 2 %}
        <div class="signcan">
            <!--数据循环部分-->
            {% for key,value in tags %}
            <div>
                <a href="/rank/all/?tag={{ key }}"><span class="badge badge-info">{{ key }}:{{ value }}次</span></a>
            </div>
            {% endfor %}
            <!--数据循环部分end-->
        </div>
        {% endifequal %}
        <!--标签云end-->

(3)所有图书 1)采用两种方法,一个是post,一个是get,post需要自己填写信息,get直接获取信息 2)若采用post,从数据库Book表中筛选标签和评分限制,根据评分逆序排列;若采用get,设置默认评分限制,从数据库Book表中筛选标签,根据评分逆序排列 3)分页 4)返回rank.html和参数 @views.py

def all(request):
    # 登陆是将用户写入session,此时若获取不到,则返回错误
    username = request.COOKIES.get('name')
    # 如果用户为登陆
    if not username:
        return render_to_response('login.html', {
            'error': "用户未登陆,请先登陆!",
            'user_name': "",
            'user_pwd': ""
        })

    # 如果是查询某个标签下的数据
    # post需要提交信息,这里自己填写评分限制和标签;get直接获取信息,评分限制默认为0和10,需自己填写标签
    if request.method == "POST":
        tag_temp = request.POST.get("tag")
        tag = tag_temp if tag_temp else "电影"
        low = request.POST.get("lowfen")
        lowfen = float(low) if low else 0.0
        high = request.POST.get("highfen")
        highfen = float(high) if high else 10.0
        books = Book.objects.filter(booktag__icontains=tag).filter(bookscore__range=(lowfen,highfen)).order_by("-bookscore")
    # 如果get请求
    else:
        lowfen = "0"
        highfen = "10"
        get_tag = request.GET.get('tag')
        if get_tag:
            tag = get_tag
            books = Book.objects.filter(booktag__icontains=tag).order_by("-bookscore")
        elif not get_tag:
            tag = "电影"
            books = Book.objects.order_by("-bookscore")

    paginator = Paginator(books, 20)
    page = request.GET.get('page')
    try:
        new_book = paginator.page(page)
    except PageNotAnInteger:
        new_book = paginator.page(1)
    except EmptyPage:
        new_book = paginator.page(paginator.num_pages)

    return render_to_response("rank.html",{
        "user_name":username,
        "books":new_book,
        "type":3,
        "tag":tag,
        "lowfen":lowfen,
        "highfen":highfen,
        "len_list":paginator.num_pages + 1,
    })

@rank.html html中name 属性用于对提交到服务器后的表单数据进行标识,或者在客户端通过 JavaScript 引用表单数据。 1)拿到book变量,获取图书信息 2)“我要评分”:bootstrap框架的data-toggle指以什么事件触发,常用的如modal,popover,tooltips等,data-target指事件的目标,这里是指#{{ book.bookid }}这个Dom元素的内容以模态框的形式展示。

 <!--所有图书-->
        {% ifequal type 3 %}
        <div class="rankcan">
            <div class="rank_all_form">
                <form class="form-inline" role="form" method="post" action="/rank/all/">
                    <div class="form-group">
                        <span>输入标签 :</span>
                    </div>
                    <div class="form-group">
                        <div class="col-sm-10" style="display:inline;">
                            <input type="text" class="form-control" name="tag" id="sign" value="{{ tag }}">
                        </div>
                    </div>
                    <div class="form-group">
                        <span>查询最低分 :</span>
                    </div>
                    <div class="form-group">
                        <div class="col-sm-10">
                            <input type="text" class="form-control" name="lowfen" id="lowfen" value="{{ lowfen }}">
                        </div>
                    </div>
                    <div class="form-group">
                        <span>查询最高分 :</span>
                    </div>
                    <div class="form-group">
                        <div class="col-sm-10">
                            <input type="text" class="form-control" name="highfen" id="highfen" value="{{ highfen }}">
                        </div>
                    </div>
                    <div class="form-group">
                        <div class="col-sm-offset-2 col-sm-10">
                            <button type="submit" class="btn btn-default">搜索</button>
                        </div>
                    </div>
                </form>
            </div>
            <br/>
            <hr class="rank_all_form">
            <ul>
              <li class="recomtitle">
                <span>封面</span>
                <div class="sixta">
                    <span>书名</span>
                    <span>综合评分</span>
                    <span>相关标签</span>
                    <span>查看详情</span>
                    <span>我要评分</span>
                </div>
              </li>
                <!--数据循环部分-->
            {% for book in books %}
            <li class="recomitem">
                <img src="/static/bookimg/{{ book.bookid }}.jpg">
                <div class="sixta">
                    <span>{{ book.bookname }}</span>
                    <span>{{ book.bookscore }}</span>
                    <span class="sign">
                        {% for tag in book.tag_split %}
                             <a class="badge badge-default">{{ tag }}</a>
                        {% endfor %}
                    </span>
                    <span><a href="https://book.douban.com/subject/{{ book.bookid }}" target="_blank">查看详情</a></span>
                    <span class="fenbtn" data-toggle="modal" data-target="#{{ book.bookid }}">我要评分</span>
                </div>
            </li>
            <div class="modal fade" id="{{ book.id }}" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
                <div class="modal-dialog">
                    <div class="modal-content">
                        <div class="modal-header">
                            <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
                            <h4 class="modal-title" id="myModalLabel">我要评分</h4>
                        </div>
                        <div class="modal-body">
                            <form role="form" method="post" action="/user/action/">
                                <div class="form-group">
                                    <label for="name">图书iD</label>
                                    <input type="text" class="form-control" disabled value="{{ book.bookid }}">
                                    <input type="hidden" class="form-control" id="bookid" name="bookid" value="{{ book.bookname }}">
                                </div>
                                <div class="form-group">
                                    <label for="name">书名</label>
                                    <input type="text" class="form-control" id="bookname" name="bookname" disabled value="{{ book.bookname }}">
                                </div>
                                <div class="form-group">
                                    <label for="name">评分</label>
                                    <input type="text" class="form-control" id="bookscore" name="bookscore" placeholder="请输入评分">
                                </div>
                                <div class="modal-footer">
                                    <button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
                                    <button type="submit" class="btn btn-primary">提交</button>
                                </div>
                            </form>
                        </div>
                    </div>
                </div>
            </div>
            {% endfor %}
                <!--数据循环部分end-->
            </ul>
        </div>
        <div class="eassy-page pagan">
            <ul class="pagination page-list page-listli">
                <li class="previous">
                    {% if books.has_previous %}
                        <a href="?page={{ books.previous_page_number }}&tag={{ tag }}"><span>上一页</span></a>
                    {% else %}
                        <a><span>上一页</span></a>
                    {% endif %}
                </li>
                <div class="form-group jump">
                    <span for="name">输入页数(共:{{ len_list }}页)</span>
                    <input type="text" class="form-control" id="pageid" name="pageid">
                    <button type="button" class="btn btn-primary" onclick="transform()">跳转</button>
                </div>
                <li class="next">
                    {% if books.has_next %}
                        <a href="?page={{ books.next_page_number }}&tag={{ tag }}"><span>下一页</span></a>
                    {% else %}
                        <a><span>下一页</span></a>
                </li>
            </ul>
        </div>
        {% endifequal %}
        <!--所有图书end-->
				
				# 跳转
				<script language="javascript" type="text/javascript">
    function transform() {
        var page = document.getElementById('pageid').value;
        location.href = "/rank/all/?page="+page;
    }
</script>