Django中組合搜索功能


需求分析

很多電商網站中有組合搜索的功能,所謂組合搜索就是網頁中組合多個條件,對數據庫中進行查詢,並且將結果顯示在頁面中,看個例子吧:
組合search

注意紅框中的標識,我們可以根據URL來做組合搜索.

video-3-1-1.html 使用split可以將三個數字取到,
第一位數字:	分類
第二位數字:	課程名稱
第三位數字:	級別

分析到這里,我們就可以進行下一步了.

Code分析

urls.py

首先,如果想把url按我們的需求取出來,我們可以在urls.py中設置:

from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    # url(r'^student/', views.student),
    url(r'^video-(?P<direction_id>\d+)-(?P<classfication_id>\d+)-(?P<level_id>\d+).html', views.video),
]

說明下,這里是本身的正則表達式的語法,先分組,並且賦予了變量


1.此處的(?P<name>…),和普通的(?…):

基本類似。區別在於,此處由於是給此group命名了,所以,后續(同一正則表達式內和搜索后得到的Match對象中),都可以通過此group的名字而去引用此group。

2. group的名字,當前需要是正常的Python標識符,即字母,數字,下划線等,即,沒有特殊的字符。

3.同一正則表達式內,每個group的組名,是唯一的,不能重復。

4. 雖然此處group內命名了,但是其仍然和普通的

這樣,我們就可以在后續的代碼中用到這些了!

modles.py

from django.db import models

# 技術方向,
class Direction(models.Model):
    name = models.CharField(verbose_name='名稱', max_length=32)

    classification = models.ManyToManyField('Classification')

    class Meta:
        db_table = 'Direction'
        verbose_name_plural = u'方向(視頻方向)'

    def __str__(self):
        return self.name


# 技術分類、語言
class Classification(models.Model):
    name = models.CharField(verbose_name='名稱', max_length=32)

    class Meta:
        db_table = 'Classification'
        verbose_name_plural = u'分類(視頻分類)'

    def __str__(self):
        return self.name


# 技術視頻,
class Video(models.Model):
    level_choice = (
        (1, u'初級'),
        (2, u'中級'),
        (3, u'高級'),
    )
    level = models.IntegerField(verbose_name='級別', choices=level_choice, default=1)

    classification = models.ForeignKey('Classification', null=True, blank=True)

    title = models.CharField(verbose_name='標題', max_length=32)
    summary = models.CharField(verbose_name='簡介', max_length=32)
    img = models.ImageField(verbose_name='圖片', upload_to='./static/images/Video/')
    href = models.CharField(verbose_name='視頻地址', max_length=256)

    create_date = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = 'Video'
        verbose_name_plural = u'視頻'

    def __str__(self):
        return self.title

技術方向:多對多技術分類

技術視頻:一對多技術分類

views.py

from django.shortcuts import render
from app01 import models
# Create your views here.

def video(request,**kwargs):
    #在url.py中已經設置,結果為:{'direction_id': '3', 'classfication_id': '4', 'level_id': '1'}
    print(kwargs)
    print(request.path_info)
    #request.path._info可以得到url的后綴,比如:/video-3-4-1.html
    current_url = request.path_info
    direction_id = kwargs.get('direction_id','0')
    classfication_id = kwargs.get('classfication_id', '0')
    q = {}
    # 方向是0,表示是全部
    if direction_id == '0':
        #如果技術分類id為0,取分類數據庫中的數據,為字典模式,元素為id和name
        cList = models.Classification.objects.values('id', 'name')
        # 分類是0
        if classfication_id == '0':
            # 如果課程也是全部,video-0-0
            pass
        else:
            # video-0-1
            # 否則,選中了對應的分類
            q['classification__id'] = classfication_id
    else:
        #如果分類不是全部,得到分類對應的數據,通過map函數處理迭代器temp,並將其轉化為列表,取得ID
        obj = models.Direction.objects.get(id=direction_id)
        temp = obj.classification.all().values('id','name')
        id_list = list(map(lambda x:x['id'],temp))
        cList = obj.classification.all().values('id','name')

        if classfication_id == '0':
            # video-1-0
            # 根據方向ID,找到所屬的分類ID

            print(id_list)
            q['classification__id__in'] = id_list
        else:
            # video-1-1
            #如果分類ID在方向ID列表中
            if int(classfication_id) in id_list:
                q['classification__id'] = classfication_id
            else:
                q['classification__id__in'] = id_list
                #url分割取分類的ID,然后改為0,修改url
                url_list = current_url.split('-')
                url_list[2] = "0"
                current_url = '-'.join(url_list)
    level_id = kwargs.get('level_id',None)
    if level_id != '0':
        q['level'] = level_id

    result = models.Video.objects.filter(**q)

    dList = models.Direction.objects.values('id', 'name')

    lList = models.Video.level_choice
    # level_choice = (
    #     (1, u'初級'),
    #     (2, u'中級'),
    #     (3, u'高級'),
    # )
    return render(request, 'video.html', {"dList":dList,
                                            'cList': cList,
                                            'lList': lList,
                                          'current_url': current_url})

自定義擴展template函數

由於處理函數比較復雜,所以我們要寫一些自定義的simple_tag函數,用來對相應的a標簽進行href預處理,得到相應的url路徑,xx.py:

from django import template
from django.utils.safestring import mark_safe

############################################
#此部分無用
register = template.Library()
@register.simple_tag
def action1(current_url, nid):
    # /video-2-1-3.html
    url_list = current_url.split('-')
    url_list[1] = str(nid)

    return '-'.join(url_list)

@register.simple_tag
def action2(current_url, nid):
    # /video-2-1-3.html
    url_list = current_url.split('-')
    url_list[2] = str(nid)

    return '-'.join(url_list)

@register.simple_tag
def action3(current_url, nid):
    # /video-2-1-3.html
    url_list = current_url.split('-')
    url_list[3] = str(nid) + '.html'

    return '-'.join(url_list)
    
###################################################

@register.simple_tag
def ac1(current_url, nid, name):
    # # /video-2-1-3.html
    url_list = current_url.split('-')
    old = url_list[1]
    if old == str(nid):
        temp = '<a class="active" href="%s">%s</a>'
    else:
        temp = '<a href="%s">%s</a>'

    url_list[1] = str(nid)
    tag = temp %('-'.join(url_list),name)

    return mark_safe(tag)


@register.simple_tag
def ac2(current_url, nid, name):
    # # /video-2-1-3.html
    url_list = current_url.split('-')
    old = url_list[2]
    if old == str(nid):
        temp = '<a class="active" href="%s">%s</a>'
    else:
        temp = '<a href="%s">%s</a>'

    url_list[2] = str(nid)
    tag = temp %('-'.join(url_list),name)

    return mark_safe(tag)


@register.simple_tag
def ac3(current_url, nid, name):
    # # /video-2-1-3.html
    url_list = current_url.split('-')
    old = url_list[3]
    if old == str(nid) + '.html':
        temp = '<a class="active" href="%s">%s</a>'
    else:
        temp = '<a href="%s">%s</a>'

    url_list[3] = str(nid) +  '.html'
    tag = temp %('-'.join(url_list),name)

    return mark_safe(tag)

@register.simple_tag
def all_menu(current_url):
    # video-0-10-0.html
    url_list = current_url.split('-')
    if url_list[1] == '0':
        temp = '<a class="active" href="%s">全部</a>'
    else:
        temp = '<a  href="%s">全部</a>'

    url_list[1] = '0'
    temp = temp %('-'.join(url_list))

    return mark_safe(temp)

vedio.html

{% load xx %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <style>
    		// 設定之間的間隔
        .condition a{
            display: inline-block;
            padding: 5px;
        }
        // 設定當前選擇條件的css樣式
        .condition a.active{
            background-color: coral;
            color: white;
        }
    </style>
</head>
<body>
    <div class="condition">
        <div>
            // 處理全部
            {% all_menu current_url %} :
            // 遍歷方向列表
            {% for i in dList %}
            		// 將方向列表中的id,name作為參數傳入定義好的自定義函數中處理,生成
                {% ac1 current_url i.id i.name %}
            {% endfor %}
        </div>
        <div>
            {% for i in cList %}
                {% ac2 current_url i.id i.name %}
            {% endfor %}
        </div>
        <div>
            {% for i in lList %}
                {% ac3 current_url i.0 i.1 %}

            {% endfor %}
        </div>
    </div>

</body>
</html>

頁面中的搜索條件距離,可以使用css來控制


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM