django 組合搜索
# urls.py
from django.contrib import admin
from django.urls import path
from django.conf.urls import url
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
url(r'^video-(?P<Classification_id>(\d+))-(?P<level_id>(\d+))-(?P<status>(\d+)).html$', views.video),
url(r'^video2-(?P<direction_id>(\d+))-(?P<Classification_id>(\d+))-(?P<level_id>(\d+)).html$', views.video2,name="video2"),
]
視圖函數(shù)
from django.shortcuts import render
from django.shortcuts import HttpResponse
from app01 import models
def video(request,*args,**kwargs):
print("kwargs::",kwargs)
condition = {}
for k,v in kwargs.items():
temp = int(v)
kwargs[k] = temp
if temp:
condition[k] = temp
class_list = models.Classification.objects.all()
level_list = models.Level.objects.all()
video_list = models.Video.objects.filter(**condition)
status_list = list(map(lambda x:{'id':x[0],"name":x[1]},models.Video.status_choice))
print(status_list)
return render(
request,
"video.html",
{
"class_list":class_list,
"level_list":level_list,
"kwargs":kwargs,
"video_list":video_list,
"status_list":status_list,
}
)
def video2(request,*args,**kwargs):
condition = {}
print("=-------------------------",kwargs)
for k,v in kwargs.items():
kwargs[k] = int(v)
direction_id = kwargs.get("direction_id")
classification_id = kwargs.get("Classification_id")
level_id = kwargs.get("level_id")
direction_list = models.Direction.objects.all()
level_list = models.Level.objects.all()
if direction_id == 0:
class_list = models.Classification.objects.all()
if classification_id == 0:
pass
else:
condition['Classification_id'] = classification_id
else:
direction_obj = models.Direction.objects.filter(id=direction_id).first()
class_list = direction_obj.classification.all()
vlist = direction_obj.classification.all().values_list('id')
if not vlist:
classification_id_list = []
else:
classification_id_list = list(zip(*vlist))[0]
if classification_id == 0:
condition['Classification_id__in'] = classification_id_list
else:
if classification_id in classification_id_list:
condition['Classification_id'] = classification_id
else:
#################指定方向:[1,2,3] 分類:5
kwargs["Classification_id"] = 0
condition['Classification_id__in'] = classification_id_list
if level_id == 0:
pass
else:
condition['level_id'] = level_id
video_list = models.Video.objects.filter(**condition)
return render(
request,
"video2.html",
{
"direction_list":direction_list,
"class_list":class_list,
"level_list":level_list,
"video_list":video_list,
"kwargs":kwargs,
}
)
模版文件 video.py 和 video2.py
# video.py
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.condition a{
display: inline-block;
padding: 5px 8px;
border: 1px solid #dddddd;
}
.condition a.active{
background-color: coral;
color: white;
}
</style>
</head>
<body class="condition">
<h3>篩選</h3>
<div>
{% if kwargs.Classification_id == 0 %}
<a class="active" href="video-0-{{ kwargs.level_id }}-{{ kwargs.status }}.html">全部</a>
{% else %}
<a href="video-0-{{ kwargs.level_id }}-{{ kwargs.status }}.html">全部</a>
{% endif %}
{% for foo in class_list %}
{% if kwargs.Classification_id == foo.id %}
<a href="video-{{ foo.id }}-{{ kwargs.level_id }}-{{ kwargs.status }}.html" class="active">{{ foo.name }}</a>
{% else %}
<a href="video-{{ foo.id }}-{{ kwargs.level_id }}-{{ kwargs.status }}.html">{{ foo.name }}</a>
{% endif %}
{% endfor %}
</div>
<div>
{% if kwargs.level_id == 0 %}
<a class="active" href="video-{{ kwargs.Classification_id }}-0-{{ kwargs.status }}.html">全部</a>
{% else %}
<a href="video-{{ kwargs.Classification_id }}-0-{{ kwargs.status }}.html">全部</a>
{% endif %}
{% for foo in level_list %}
{% if foo.id == kwargs.level_id %}
<a href="video-{{ kwargs.Classification_id }}-{{ foo.id }}-{{ kwargs.status }}.html" class="active">{{ foo.title }}</a>
{% else %}
<a href="video-{{ kwargs.Classification_id }}-{{ foo.id }}-{{ kwargs.status }}.html">{{ foo.title }}</a>
{% endif %}
{% endfor %}
</div>
<div>
{% if kwargs.status == 0 %}
<a class="active" href="video-{{ kwargs.Classification_id }}-{{ kwargs.level_id }}-0.html">全部</a>
{% else %}
<a href="video-{{ kwargs.Classification_id }}-{{ kwargs.level_id }}-0.html">全部</a>
{% endif %}
{% for foo in status_list %}
{% if foo.id == kwargs.status %}
<a href="video-{{ kwargs.Classification_id }}-{{ kwargs.level_id }}-{{ foo.id }}.html" class="active">{{ foo.name }}</a>
{% else %}
<a href="video-{{ kwargs.Classification_id }}-{{ kwargs.level_id }}-{{ foo.id }}.html">{{ foo.name }}</a>
{% endif %}
{% endfor %}
</div>
<div>
<h3>結(jié)果:</h3>
{% for foo in video_list %}
<div>{{ foo }}</div>
{% endfor %}
</div>
</body>
</html>
# video2.py
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.condition a{
display: inline-block;
padding: 5px 8px;
border: 1px solid #dddddd;
}
.condition a.active{
background-color: coral;
color: white;
}
</style>
</head>
<body class="condition">
<h3>篩選</h3>
<div>
{% if kwargs.direction_id == 0 %}
<a href="{% url "video2" direction_id=0 Classification_id=kwargs.Classification_id level_id=kwargs.level_id %}" class="active">全部</a>
{% else %}
<a href="{% url "video2" direction_id=0 Classification_id=kwargs.Classification_id level_id=kwargs.level_id %}">全部</a>
{% endif %}
{% for foo in direction_list %}
{% if foo.id == kwargs.direction_id %}
<a href="{% url "video2" direction_id=foo.id Classification_id=kwargs.Classification_id level_id=kwargs.level_id %}" class="active">{{ foo.name }}</a>
{% else %}
<a href="{% url "video2" direction_id=foo.id Classification_id=kwargs.Classification_id level_id=kwargs.level_id %}">{{ foo.name }}</a>
{% endif %}
{% endfor %}
</div>
<div>
{% if kwargs.Classification_id == 0 %}
<a href="{% url "video2" direction_id=kwargs.direction_id Classification_id=0 level_id=kwargs.level_id %}" class="active">全部</a>
{% else %}
<a href="{% url "video2" direction_id=kwargs.direction_id Classification_id=0 level_id=kwargs.level_id %}">全部</a>
{% endif %}
{% for foo in class_list %}
{% if foo.id == kwargs.Classification_id %}
<a href="/video2-{{ kwargs.direction_id }}-{{ foo.id }}-{{ kwargs.level_id }}.html" class="active">{{ foo.name }}</a>
{% else %}
<a href="/video2-{{ kwargs.direction_id }}-{{ foo.id }}-{{ kwargs.level_id }}.html">{{ foo.name }}</a>
{% endif %}
{% endfor %}
</div>
<div>
{% if kwargs.level_id == 0 %}
<a href="{% url "video2" direction_id=kwargs.direction_id Classification_id=kwargs.Classification_id level_id=0 %}" class="active">全部</a>
{% else %}
<a href="{% url "video2" direction_id=kwargs.direction_id Classification_id=kwargs.Classification_id level_id=0 %}">全部</a>
{% endif %}
{% for foo in level_list %}
{% if foo.id == kwargs.level_id %}
<a href="/video2-{{ kwargs.direction_id }}-{{ kwargs.Classification_id }}-{{ foo.id }}.html" class="active">{{ foo.title }}</a>
{% else %}
<a href="/video2-{{ kwargs.direction_id }}-{{ kwargs.Classification_id }}-{{ foo.id }}.html">{{ foo.title }}</a>
{% endif %}
{% endfor %}
</div>
<div>
<h3>結(jié)果:</h3>
{% for foo in video_list %}
<div>{{ foo.title }}</div>
{% endfor %}
</div>
</body>
</html>
表函數(shù),
# models.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 = "方向(視頻方向)"
def __str__(self):
return self.name
class Classification(models.Model):
"""
分類: Python Linux JavaScript OpenStack Node.js
"""
name = models.CharField(verbose_name='名稱',max_length=32)
class Meta:
db_table = "Classification"
verbose_name_plural = "分類(視頻分類)"
def __str__(self):
return self.name
class Level(models.Model):
title = models.CharField(max_length=32)
class Meta:
verbose_name_plural = '難度級別'
def __str__(self):
return self.title
class Video(models.Model):
status_choice = (
(1,'下線'),
(2,'上線'),
)
status = models.IntegerField(verbose_name='狀態(tài)',choices=status_choice,default=1)
level = models.ForeignKey(Level,on_delete=models.CASCADE)
Classification = models.ForeignKey('Classification',null=True,blank=True,on_delete=models.CASCADE)
weight = models.IntegerField(verbose_name='權(quán)重(按從大到小排列)',default=0)
title = models.CharField(verbose_name='標(biāo)題',max_length=32)
summary = models.CharField(verbose_name='簡介',max_length=32)
img = models.CharField(verbose_name='圖片',max_length=32)
href = models.CharField(verbose_name='圖片地址',max_length=256)
create_date = models.DateTimeField(auto_now_add=True)
class Meta:
db_table = 'Video'
verbose_name_plural = '視頻'
def __str__(self):
return self.title
這個是 video2.html 文件渲染出來的。

瀑布流
也就是在頁面設(shè)置幾個豎直的div框,讓圖片分別排列,就形成了瀑布流的效果了。
# 用的還是上面的那張表,
# views.py
def image(request):
return render(request,"image.html")
def get_images(request):
image_list = models.Imgs.objects.all().values("id","src","title")
image_list = list(image_list)
ret = {
"status": True,
"data": image_list,
}
return HttpResponse(json.dumps(ret))
# urls.py 中要添加這兩句
path('image/', views.image),
path('get_images.html/', views.get_images),
所有的排列都在js里
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.w{
width: 1000px;
margin: 0 auto;
}
.w .item{
width: 25%;
float: left;
}
img{
width: 95%;
}
</style>
</head>
<body>
<div class="w" id="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
<script src="/static/jquery-3.3.1.min.js"></script>
<script>
$(function () {
initImg();
});
function initImg() {
$.ajax({
url: "/get_images.html",
type: "GET",
data: {nid:1213},
dataType: "JSON",
success:function (arg) {
var image_list = arg.data;
$.each(image_list,function (index,v) {
var eqv = index%4; // 這里設(shè)置了4個div,
var tag = document.createElement("img");
tag.src = '/' + v.src;
$("#container").children().eq(eqv).append(tag);
});
}
})
}
</script>
</body>
</html>
效果看起來倒是很不錯了,

1.png
一、組合搜索
方向:自動化*,測試,運維[4,5],前端
分類:Python* Linux OpenStack [1,2,3]
級別:初級 中級 高級
condition = {}
models.Video.objects.filter(**condition)
視頻列表:
視頻一,視頻二
二、瀑布流
瀑布流,升級版
監(jiān)聽滑輪事件,使得滑輪滑到最底下時,觸發(fā)請求圖片事件,使得不斷出現(xiàn)新的圖片。
# views.py 基本不用怎么改 ,
def image(request):
return render(request,"image.html")
def get_images(request):
nid = request.GET.get('nid')
image_list = models.Imgs.objects.all().values("id","src","title")
image_list = list(image_list)
ret = {
"status": True,
"data": image_list,
}
print("nid=",nid)
return HttpResponse(json.dumps(ret))
# urls.py 導(dǎo)航也是相同的
path('image/', views.image),
path('get_images.html/', views.get_images),
image.html 模版文件,
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.w{
width: 1000px;
margin: 0 auto;
}
.w .item{
width: 25%;
float: left;
}
img{
width: 95%;
}
</style>
</head>
<body>
<div class="w" id="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
<script src="/static/jquery-3.3.1.min.js"></script>
<script>
$(function () {
initImg();
scollEvent();
});
nid=0;
last_position = 0;
function initImg() { // 觸發(fā)ajax請求圖片,也就是圖片路徑
$.ajax({
url: "/get_images.html",
type: "GET",
data: {nid:nid},
dataType: "JSON",
success:function (arg) {
var image_list = arg.data;
$.each(image_list,function (index,v) {
var eqv = (index+last_position)%4;
console.log(eqv);
var tag = document.createElement("img");
tag.src = '/' + v.src;
$("#container").children().eq(eqv).append(tag);
if(index+1 == image_list.length){
nid=nid+v.id;
last_position=eqv+1; // 我們必須保留上一次的求余
// 使得下次ajax請求時圖片從上次空缺的位置放起
}
});
}
})
}
function scollEvent() { // 鼠標(biāo)滑輪事件
$(window).scroll(function () {
var doc_height = $(document).height(); // 文檔高度
var window_height = $(window).height(); // 窗口高度
var scroll_top = $(window).scrollTop(); // 滑動條滑動高度
if(doc_height==window_height+scroll_top){ // 滿足條件時,到達(dá)最低部
initImg();
}
})
}
</script>
</body>
</html>

1.png
不過這個 javascript 出現(xiàn)了全局變量,為了避免沖突,應(yīng)該在外面封裝函數(shù)或?qū)ο螅瑢⑵浞庋b到里面,
改為這樣
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.w{
width: 1000px;
margin: 0 auto;
}
.w .item{
width: 25%;
float: left;
}
img{
width: 95%;
}
</style>
</head>
<body>
<div class="w" id="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
<script src="/static/jquery-3.3.1.min.js"></script>
<script>
$(function () {
var obj = new allEvent();
obj.initImg();
obj.scollEvent();
});
function allEvent() {
this.nid = 0;
this.last_position = 0;
var that = this; // 到函數(shù)內(nèi)部的this和外部的this是不相同的,所以需要保留這個this
this.initImg = function () {
$.ajax({
url: "/get_images.html",
type: "GET",
data: {nid:that.nid},
dataType: "JSON",
success:function (arg) {
var image_list = arg.data;
$.each(image_list,function (index,v) {
var eqv = (index+that.last_position)%4;
console.log(eqv);
var tag = document.createElement("img");
tag.src = '/' + v.src;
$("#container").children().eq(eqv).append(tag);
if(index+1 == image_list.length){
that.nid=that.nid+v.id;
that.last_position=eqv+1;
}
});
}
})
};
this.scollEvent = function () {
$(window).scroll(function () {
var scroll_height = $(document).height();
var window_height = $(window).height();
var scroll_top = $(window).scrollTop();
if(scroll_height==window_height+scroll_top){
that.initImg();
}
})
}
}
</script>
</body>
</html>
寫成一個類的形式,封裝所有的變量和函數(shù),但是要十分注意this,that。
效果是一模一樣的。
note
一、瀑布流作業(yè)
- 布局
- 文檔,窗口,滾動
- 面向?qū)ο蟮姆庋b: this,that
二、報障系統(tǒng)
需求分析
- 報障
用戶:
提交報賬單
自己報障記錄
處理著:
查看所有人報障單
處理報賬單
- 知識庫(博客)
主頁:
展示最新文章
展示最熱文章
展示評論最多文章
分類查看
個人博客:
個人博客主頁
個人博客文章詳細(xì):贊,踩,評論
個人博客分類:標(biāo)簽、分類、時間
個人博客主題定制:后臺修改
后臺管理:
個人信息管理
個人標(biāo)簽
個人分類
個人文章
數(shù)據(jù)庫設(shè)計:
用戶表: uid,username,pwd,email,img,
博客表: bid,surfix,theme,title,summary, FK(用戶表,unique)=OneToOne(用戶表)
互粉表: id 明星ID(用戶表) 粉絲ID(用戶表)
2 1
1 2
1 3
5 3
報障單:UUID title detail user(用戶表) processor(用戶表 null) status(待處理,處理中,已處理) 創(chuàng)建時間 處理事件
分類表:caption Fk(博客bid)
標(biāo)簽表:caption Fk(博客bid)
文章:id,title,summary,ctime,FK(個人分類表),主站分類(choices)
文章詳細(xì):detail OneToOne(文章)
文章標(biāo)簽關(guān)系: 文章ID 標(biāo)簽ID
贊踩文章關(guān)系: 文章ID 用戶ID 贊或踩(True,F(xiàn)alse) 聯(lián)合唯一索引:(文章ID 用戶ID )
評論表:id,content,FK(文章),FK(user),ctime,parent_comment_id
三、程序目錄結(jié)構(gòu)
project
- APP(repository) - 數(shù)據(jù)倉庫(操作數(shù)據(jù)Model)
- APP(backend) - 后臺管理
- APP(web) - 首頁,個人博客
- utils - 工具包(公共模塊)
工作安排:
1. 需求分析
2. 數(shù)據(jù)庫設(shè)計思路
3. 實現(xiàn)數(shù)據(jù)庫設(shè)計(Admin添加數(shù)據(jù))
4. 主站:分類(主站)查看+分頁
- 標(biāo)題菜單:母版
- 登錄成功: session['username'] = 'root'
- 主頁html:
判斷是否有用戶:顯示用戶名
否則 : 登錄,注冊
<div class="pg-header">
{% if request.session.username %}
<a>{{ request.session.username }}</a>
{% else %}
<a>登錄</a><a>注冊</a>
{% endif %}
</div>
- 博文內(nèi)容布局:
div div -> float => 圖片下方空白
<a></a>asdflkjasdfkj => 文字環(huán)繞
- URL分類篩選:
url(r'^all/(?P<article_type_id>\d+).html$', home.index, name='index'),
url(r'^', home.index),
index根據(jù)kwargs判斷是否分類查詢?
a. 生成分類菜單
b. 考慮是否選中
c. 根據(jù)條件model.xxx.objects.filter(**kwargs)
- URL:
from django.urls import reverse
url(r'^all/(?<article_type_id>\d+).html$', home.index, name='index'),
在HTML中:{% url "index" article_type_id=1 %} => all/1.html
在views中:reverse('index',kwargs={"article_type_id":1}) =>all/1.html
url(r'^all/(\d+).html$', home.index, name='index'),
在HTML中:{% url "index" 1 %} =>all/1.html
在views中:reverse('index',args=(1,)) =>all/1.html
- 利用reverse+分頁組件完成:分類查看+分頁
5. 登錄,注冊
- 密碼:數(shù)字,字母,特殊字符
- 密碼兩次輸入一致
提交:
v = MyForm(request.GET) # 6個字段
if v.is_valid():
pass
密碼示例:RegexField自定義密碼驗證規(guī)則
password = forms.RegexField(
'^(?=.*[0-9])(?=.*[a-zA-Z])(?=.*[!@#$\%\^\&\*\(\)])[0-9a-zA-Z!@#$\%\^\&\*\(\)]{8,32}$',
min_length=12,
max_length=32,
error_messages={'required': '密碼不能為空.',
'invalid': '密碼必須包含數(shù)字,字母、特殊字符',
'min_length': "密碼長度不能小于8個字符",
'max_length': "密碼長度不能大于32個字符"}
)
class RegisterForm(BaseForm, django_forms.Form):
username = django_fields.CharField()
password = django_fields.CharField()
confirm_pwd = django_fields.CharField()
def clean(self):
v1 = self.cleaned_data['password']
v2 = self.cleaned_data['confirm_pwd']
if v1 == v2:
pass
else:
from django.core.exceptions import ValidationError
raise ValidationError('密碼輸入不一致')
def register(request):
v = RegisterForm(request.POST)
if v.is_valid():
pass
else:
v.errors['username']
v.errors['__all__']
v.errors[NON_FIELD_ERRORS]
{
__all__: [],
username: [],
password: []
confirm_pwd: []
}
return render(request, 'register.html', {'v':v})
register.html
{{v.errors.username.0}}
{{v.non_field_errors}}