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"),
]
视图函数
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>结果:</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>结果:</h3>
{% for foo in video_list %}
<div>{{ foo.title }}</div>
{% endfor %}
</div>
</body>
</html>
表函数,
# 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='状态',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='权重(按从大到小排列)',default=0)
title = models.CharField(verbose_name='标题',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 文件渲染出来的。
瀑布流
也就是在页面设置几个竖直的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; // 这里设置了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)
视频列表:
视频一,视频二
二、瀑布流
瀑布流,升级版
监听滑轮事件,使得滑轮滑到最底下时,触发请求图片事件,使得不断出现新的图片。
# 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 导航也是相同的
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() { // 触发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() { // 鼠标滑轮事件
$(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){ // 满足条件时,到达最低部
initImg();
}
})
}
</script>
</body>
</html>
1.png
不过这个 javascript 出现了全局变量,为了避免冲突,应该在外面封装函数或对象,将其封装到里面,
改为这样
<!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; // 到函数内部的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>
写成一个类的形式,封装所有的变量和函数,但是要十分注意this,that。
效果是一模一样的。
note
一、瀑布流作业
- 布局
- 文档,窗口,滚动
- 面向对象的封装: this,that
二、报障系统
需求分析
- 报障
用户:
提交报账单
自己报障记录
处理着:
查看所有人报障单
处理报账单
- 知识库(博客)
主页:
展示最新文章
展示最热文章
展示评论最多文章
分类查看
个人博客:
个人博客主页
个人博客文章详细:赞,踩,评论
个人博客分类:标签、分类、时间
个人博客主题定制:后台修改
后台管理:
个人信息管理
个人标签
个人分类
个人文章
数据库设计:
用户表: 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(待处理,处理中,已处理) 创建时间 处理事件
分类表:caption Fk(博客bid)
标签表:caption Fk(博客bid)
文章:id,title,summary,ctime,FK(个人分类表),主站分类(choices)
文章详细:detail OneToOne(文章)
文章标签关系: 文章ID 标签ID
赞踩文章关系: 文章ID 用户ID 赞或踩(True,False) 联合唯一索引:(文章ID 用户ID )
评论表:id,content,FK(文章),FK(user),ctime,parent_comment_id
三、程序目录结构
project
- APP(repository) - 数据仓库(操作数据Model)
- APP(backend) - 后台管理
- APP(web) - 首页,个人博客
- utils - 工具包(公共模块)
工作安排:
1. 需求分析
2. 数据库设计思路
3. 实现数据库设计(Admin添加数据)
4. 主站:分类(主站)查看+分页
- 标题菜单:母版
- 登录成功: session['username'] = 'root'
- 主页html:
判断是否有用户:显示用户名
否则 : 登录,注册
<div class="pg-header">
{% if request.session.username %}
<a>{{ request.session.username }}</a>
{% else %}
<a>登录</a><a>注册</a>
{% endif %}
</div>
- 博文内容布局:
div div -> float => 图片下方空白
<a></a>asdflkjasdfkj => 文字环绕
- URL分类筛选:
url(r'^all/(?P<article_type_id>\d+).html$', home.index, name='index'),
url(r'^', home.index),
index根据kwargs判断是否分类查询?
a. 生成分类菜单
b. 考虑是否选中
c. 根据条件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. 登录,注册
- 密码:数字,字母,特殊字符
- 密码两次输入一致
提交:
v = MyForm(request.GET) # 6个字段
if v.is_valid():
pass
密码示例:RegexField自定义密码验证规则
password = forms.RegexField(
'^(?=.*[0-9])(?=.*[a-zA-Z])(?=.*[!@#$\%\^\&\*\(\)])[0-9a-zA-Z!@#$\%\^\&\*\(\)]{8,32}$',
min_length=12,
max_length=32,
error_messages={'required': '密码不能为空.',
'invalid': '密码必须包含数字,字母、特殊字符',
'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}}
网友评论