Django实战教程: 开发企业级应用智能文档管理系统smartdoc(3)附GitHub代码地址

版权声明:本文系大江狗原创,请勿直接copy应用于你的出版物或任何公众平台。 https://blog.csdn.net/weixin_42134789/article/details/82381818

本文是我们利用Django开发智能文档管理系统smartdoc的终章。对于智能文档管理,最不可或缺的功能就是搜索。在Django实战教程: 开发企业级应用智能文档管理系统smartdoc(1)里,我们已经搭好了基础框架,并具体实现了以下几个功能性页面(见标黄部分)。在第2部分教程里,我们讲解了不同用户的权限控制。本文将详细讲解开发最后一个功能性页面。

  • 产品列表,产品详情,产品创建和产品修改 - 4个页面

  • 类别列表,类别详情,类别创建和类别修改 - 4个页面

  • 文档列表,文档详情,文档创建和文件修改 - 4个页面

  • 文档一般搜索和Ajax搜索 - 1个页面

项目需求

对于任何IT项目开发,能快速准确描述项目需求是一项技能。本教程中smartdoc对于文档搜索的需求如下, 我们稍后来看看如何实现。

  • 用户可以根据标题,产品名字和代码来搜索相关文档

  • 文档列表或其它页面上带有搜索框(见图1),用户输入关键词并按提交后,跳转到文档搜索页面,显示结果。

  • 在文档搜索页面,用户输入关键词(不用按提交按钮), 实时显示搜索结果 - Ajax搜索(见图2)。

实时文档搜索页面

urls.py

我们需要设计两个urls, 一个负责接收用户输入的关键词q,在前端返回搜索结果。一个负责在后台接收实时变化的关键词q,并给前端提供json格式数据。

urlpatterns = [

    # 文档搜索
    path('document/search/', views.document_search, name='document_search'),

    # Ajax返回json数据
    path('ajax/search/', views.doc_ajax_search, name='doc_ajax_search'),
]

views.py

我们需要编写两个视图方法对应两个urls。因为我们需要使用的搜索条件很多,所以我们调用了Q方法。document_search方法负责接收用户提交的关键词q,查询数据库并返回HTTP页面和搜索结果列表。doc_ajax_search实时接收用户数据的关键词q,并给前端返回一个包含搜索结果json格式的字典。

from .models import Product, Category, Document
from django.db.models import Q
from django.http import JsonResponse, HttpResponse
from django.views.decorators.csrf import csrf_exempt
import json
import datetime


def document_search(request):
    q = request.GET.get('q', None)
    if q:
        document_list = Document.objects.filter(Q(title__icontains=q) |
                                                Q(product__name__icontains=q) |
                                                Q(product__code__icontains=q))
        context = {'document_list': document_list}
        return render(request, 'smartdoc/document_search.html', context)

    return render(request, 'smartdoc/document_search.html',)



def doc_ajax_search(request):
    q = request.GET.get('q', None)
    if q:
        document_list = Document.objects.filter(Q(title__icontains=q) |
                                                Q(product__name__icontains=q) |
                                                Q(product__code__icontains=q))
        data = []
        for document in document_list:
            data.append({"title": document.title, "product_name": document.product.name,
                        "category_name": document.category.name,
                         "format": document.doc_file.url.split('.')[-1].upper(),
                         "size": "{:.1f}KB".format(document.doc_file.size/1024),
                         "version": document.version_no, "date": document.mod_date,
                         "product_id": document.product.id, "id": document.id,
                         "url": document.doc_file.url,
                         })
        json_data = json.dumps(data, cls=MyEncoder)
        return HttpResponse(json_data)


class MyEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime.datetime):
            return obj.strftime('%Y-%m-%d')
        elif isinstance(obj, datetime.date):
            return obj.strftime('%Y-%m-%d')

        return json.JSONEncoder.default(self, obj)

由于Datetime类型数据无法被json序列化,所以我们必需定义MyEcoder,把日期转成我们想要的字符串格式。除了日期和时间外,还有很多Python类型数据不能直接转成json格式,比如单个的对象(object), 二进制(bytes), 方法(method), QuerySet(查询集), ValueQuerySet和集合(set)。Django自带的serializers也能解决一些数据Json序列化问题,但更强大的显然是Django Rest Framework,我们后面会专题介绍。

template

# smartdoc/document_search.html

模板逻辑如下所示:

  • 当有{{ document_list }}时,直接显示搜索结果。

  • 每当输入框元素#q里的值有变化时,将该值通过ajax发送到/smartdoc/ajax/search/。

  • 后台/smartdoc/ajax/search/收到ajax请求后,返回json字典格式数据。

  • 前端如果成功收到json数据,对其遍历,并显示在#id=result的元素里。

{% extends "smartdoc/base.html" %}

{% block content %}
<h3>搜索文档</h3>

<form action=" " role="search" method="get">
    {% csrf_token %}
    <div class="input-group col-md-12">
        <input type="text" name="q" id="q" class="form-control" placeholder="搜索产品名称,代码或文档标题">
        <span class="input-group-btn">
            <button class="btn btn-default form-control" type="submit" value="submit">
                <span class="glyphicon glyphicon-search"></span>
            </button>
        </span>
        </div>
</form>


<table class="table table-striped" id="result">
    {% if document_list %}
        <thead>
        <tr>
            <th>标题</th>
            <th>产品</th>
            <th>类别</th>
             <th>格式</th>
             <th>大小</th>
            <th>修改日期</th>
            <th>版本</th>
            <th>查看</th>
            <th>下载</th>
        </tr>
    </thead>
    <tbody>

         {% for document in document_list %}

     <tr>
            <td>
            {{ document.title }}
            </td>
            <td>
            {{ document.product.name }}
            </td>            <td>
            {{ document.category.name }}
            </td>
             <td>
            {{ document.get_format }}
            </td>
             <td>
            {{ document.doc_file.size | filesizeformat }}
            </td>
              <td>
            {{ document.mod_date | date:"Y-m-d" }}
            </td>

               <td>
            {{ document.version_no }}
            </td>
             <td>
                 <a href="{% url 'smartdoc:document_detail' document.product.id document.id %}"><span class="glyphicon glyphicon-eye-open"></span></a>
            </td>

             <td>
                <a href="{{ document.doc_file.url }}"><span class="glyphicon glyphicon-download"></span></a>
            </td>
      </tr>

     {% endfor %}

    </tbody>
{% endif %}
</table>
{% endblock %}


{% block js %}

<script>
    $("#q").bind('input propertychange', function() {
      var q = $(this).val();

      $.ajax({
        url: '/smartdoc/ajax/search/',
        data: {
          'q': q,
        },
        type: 'GET',
        dataType: 'json',
        success: function (data) {
          var content= '<thead><tr>' +
            '<th>标题</th>' +
            '<th>产品</th>' +
            '<th>类别</th>' +
            '<th>格式</th>' +
            '<th>大小</th>' +
            '<th>修改日期</th>' +
            '<th>版本</th>' +
            '<th>查看</th>' +
            '<th>下载</th>' +
        '</tr></thead><tbody>';

          $.each(data, function(i, item) {
                  content = content +
                  '<tr><td>' +
                  item['title'] +
                  '</td><td>' +
                  item['product_name'] +
                  '</td><td>' +
                  item['category_name'] +
                   '</td><td>' +
                  item['format'] +
                   '</td><td>' +
                   item['size'] +
                   '</td><td>' +
                  item['date'] +
                   '</td><td>' +
                  item['version'] +
                  '</td><td>' +
                  "<a href='/smartdoc/product/"
                  + item['product_id'] + "/document/" +
                  item['id'] + "'> 查看</a>" +
                  '</td><td>' +
                   "<a href='" + item['url'] + "'> 下载</a>" +
                  '</td></tr>'
                });
         content = content + "</tbody>"
         $('#result').html(content)
        },
      });
    });
  </script>

{% endblock %}

Ajax技术的关键在于后台是否能正确地返回json格式的数据,这和其它Web API是一个道理。我们是可以直接在浏览器中访问ajax对应的urls,看其能否提供json格式数据的,如下所示。里面的乱码是unicode格式的汉字,可以在前端正确显示的。

小结

本系列教程详细介绍了如何利用Django开发一个企业级应用smartdoc智能文档管理系统,并重点分析了如何控制和管理用户权限,以及实现Ajax快速搜索。全部代码如下,仅用于学习目的,希望对大家有所帮助。

  • https://github.com/shiyunbo/django-smartdoc

大江狗

2018.8.26

猜你喜欢

转载自blog.csdn.net/weixin_42134789/article/details/82381818