多條件搜索在很多網站上都有用到,比如京東,淘寶,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})

