需求分析
很多電商網站中有組合搜索的功能,所謂組合搜索就是網頁中組合多個條件,對數據庫中進行查詢,並且將結果顯示在頁面中,看個例子吧:
注意紅框中的標識,我們可以根據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來控制