django多條件篩選搜索(項目實例)


多條件搜索在很多網站上都有用到,比如京東,淘寶,51cto,等等好多購物教育網站上都有,當然網上也有很多開源的比樓主寫的好的多了去了,僅供參考,哈哈

先來一張效果圖吧,不然幻想不出來是什么樣的,前端樣式很low,畢竟主要是說后台的嘛,前端為了簡單測試就簡單的寫出來啦,喜歡好的樣式可以自己去調哈

寫后台的應該都知道先從數據庫方面入手,所以我們先來設計數據庫

 

數據庫設計

1、視頻video

復制代碼
class Video(models.Model):

    status_choice = (
        (0, u'下線'),
        (1, u'上線'),
    )
    level_choice = (
        (1, u'初級'),
        (2, u'中級'),
        (3, u'高級'),
    )
    status = models.IntegerField(verbose_name='狀態', choices=status_choice, default=1)
    level = models.IntegerField(verbose_name='級別', choices=level_choice, default=1)
    classification = models.ForeignKey('Classification', null=True, blank=True)

    weight = models.IntegerField(verbose_name='權重(按從大到小排列)', default=0)

    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
復制代碼

2、視頻方向Direction

復制代碼
class Direction(models.Model):
    weight = models.IntegerField(verbose_name='權重(按從大到小排列)', default=0)
    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
復制代碼

3、視頻分類Classification

復制代碼
class Classification(models.Model):
    weight = models.IntegerField(verbose_name='權重(按從大到小排列)', default=0)
    name = models.CharField(verbose_name='名稱', max_length=32)

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

    def __str__(self):
        return self.name
復制代碼

好了大家一起來分析下數據庫設計

  • 視頻方向Direction類和視頻分類Classification多對多關系,因為一個視頻方向可以有多個分類,一個視頻分類也可以有多個視頻方向視頻分類

  • Classification視頻分類和視頻Video類是一對多關系,因為一個分類肯定有好多視頻

  • 視頻Video類中level_choice 與視頻也是一對多關系,因為這個也就這三個分類,所以我選擇把他放在內存里面取,畢竟這玩意常年不會變

 

url映射

復制代碼
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^video-(?P<direction_id>\d+)-(?P<classification_id>\d+)-(?P<level_id>\d+).html', views.video),
]
復制代碼

輸入的url為:http://127.0.0.1:8080/video-0-0-0.html

  • 中間第一個0代表視頻方向,第二個0代表食品分類,第三個0是視頻等級,這個是根據汽車之間那個二手車學的,用着很方便哈哈

  • 0代表全部,然后遞增,當選擇運維自動化,第一個0就會變成1

  • 下面那些都是一樣的道理

 

前端代碼

前端HTML,有用到django的simple_tag,從總體效果圖可以看出,前端主要分為兩部分,選擇部分和視頻展示部分

1、選擇部分

復制代碼
    <h3>選擇:</h3>
    <div>
        {% action_all current_url 1 %} :
        {% for item in direction_list %}

             {% action current_url item %}
        {% endfor %}
    </div>
    <div>
        {% action_all current_url 2 %} :
        {% for item in class_list %}

            {% action current_url item %}
        {% endfor %}
    </div>
    <div>
        {% action_all current_url 3 %} :
        {% for item in level_list %}
            {% action current_url item %}
        {% endfor %}
    </div>
復制代碼

中間主要是用simple_tag來做的前端代碼

復制代碼
@register.simple_tag
def action_all(current_url,index):
    """
    獲取當前url,video-1-1-2.html
    :param current_url:
    :param item:
    :return:
    """
    url_part_list = current_url.split('-')
    if index == 3:
        if url_part_list[index] == "0.html":
            temp = "<a href='%s' class='active'>全部</a>"
        else:
            temp = "<a href='%s'>全部</a>"

        url_part_list[index] = "0.html"
    else:
        if url_part_list[index] == "0":
            temp = "<a href='%s' class='active'>全部</a>"
        else:
            temp = "<a href='%s'>全部</a>"

        url_part_list[index] = "0"


    href = '-'.join(url_part_list)

    temp = temp % (href,)
    return mark_safe(temp)


@register.simple_tag
def action(current_url, item,index):
    # videos-0-0-1.html
    # item: id name
    # video-   2   -0-0.html
    url_part_list = current_url.split('-')
 
    if index == 3:
        if str(item['id']) == url_part_list[3].split('.')[0]:  #如果當前標簽被選中
             temp = "<a href='%s' class='active'>%s</a>"
        else:
            temp = "<a href='%s'>%s</a>"
 
        url_part_list[index] = str(item['id']) + '.html' #拼接對應位置的部分url
    else:
        if str(item['id']) == url_part_list[index]:
            temp = "<a href='%s' class='active'>%s</a>"
        else:
            temp = "<a href='%s'>%s</a>"
 
        url_part_list[index] = str(item['id'])
 
    ur_str = '-'.join(url_part_list)  #拼接整體url
    temp = temp %(ur_str, item['name']) #生成對應的a標簽
    return mark_safe(temp)  #返回安全的html
復制代碼

 

2、視頻展示區域

復制代碼
    <h3>視頻:</h3>
    {% for item in video_list %}
        <a class="item" href="{{ item.href }}">
            <img src="/{{ item.img }}" width="300px" height="400px">
            <p>{{ item.title }}</p>
            <p>{{ item.summary }}</p>
        </a>
    {% endfor %}
復制代碼

關鍵來啦關鍵來啦,最主要的處理部分在這里,往這看,往這看,往這看,主要的事情說三遍哈

視頻后台邏輯處理部分

復制代碼
def video(request,*args,**kwargs):
    print(kwargs)
    # 當前請求的路徑
    request_path = request.path
    # 從數據庫獲取視頻時的filter條件字典
    q = {}
    # 狀態為審核通過的
    q['status'] = 1
    # 獲取url中的視頻分類id
    class_id = int(kwargs.get('classification_id'))
    # 從數據庫中獲取所有的視頻方向(包括視頻方向的id和name)
    direction_list = models.Direction.objects.all().values('id','name')

    # 如果視頻方向是0
    if kwargs.get('direction_id') == '0':
        # 方向選擇全部
        # 方向id=0,即獲取所有的視頻分類(包括視頻分類的id和name)
        class_list = models.Classification.objects.all().values('id', 'name')
        # 如果視頻分類id也為0,即全部分類,那就什么都不用做,因為已經全取出來了
        if kwargs.get('classification_id') == '0':
            pass
        else:
            # 如果視頻分類不是全部,過濾條件為視頻分類id在[url中的視頻分類id]
            q['classification_id__in'] = [class_id,]

    else:
        print('方向不為0')
        # 方向選擇某一個方向,
        # 如果分類是0
        if kwargs.get('classification_id') == '0':
            print('分類為0')
            # 獲取已選擇的視頻方向
            obj = models.Direction.objects.get(id=int(kwargs.get('direction_id')))
            # 獲取該方向的所有視頻分類
            class_list = obj.classification.all().values('id', 'name')
            # 獲取所有視頻分類對應的視頻分類id
            id_list = list(map(lambda x: x['id'], class_list))
            # 過濾條件為視頻分類id in [該方向下的所有視頻分類id]
            q['classification_id__in'] = id_list 
        else:
            # 方向不為0,分類也不為0
            obj = models.Direction.objects.get(id=int(kwargs.get('direction_id')))
            class_list = obj.classification.all().values('id', 'name')
            id_list = list(map(lambda x:x['id'], class_list))
            # 過濾條件為視頻分類id in [已經選擇的視頻分類id]
            q['classification_id__in'] = [class_id,] 
            print('分類不為0')
            # 當前分類如果在獲取的所有分類中,則方向下的所有相關分類顯示
            # 當前分類如果不在獲取的所有分類中,
            if int(kwargs.get('classification_id')) in id_list:
                pass
            else:
                print('不再,獲取指定方向下的所有分類:選中的回到全部')
                url_part_list = request_path.split('-')
                url_part_list[2] = '0'
                request_path = '-'.join(url_part_list)
    # 視頻等級id
    level_id = int(kwargs.get('level_id'))
    if level_id == 0:
        pass
    else:
        # 過濾條件增加視頻等級
        q['level'] = level_id 

    # 取出相對應的視頻
    video_list = models.Video.objects.filter(**q).values('title','summary', 'img', 'href')
    # 把視頻等級轉化為單個標簽是字典格式,整體是列表格式
    ret = map(lambda x:{"id": x[0], 'name': x[1]}, models.Video.level_choice)
    level_list = list(ret)
    return render(request, 'video.html', {'direction_list': direction_list,
                                          'class_list': class_list,
                                          'level_list': level_list,
                                          'current_url': request_path,
                                          "video_list": video_list})
復制代碼

 

 
 
 
好文要頂  關注我  收藏該文   


免責聲明!

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



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