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