链接:https://pan.baidu.com/s/1GDFNppmTYaN94zoupymLSQ?pwd=7qtw
提取码:7qtw
代码规范
1.分享规范
1.1 不要用中文拼音
xm = "xxx"
xingming = "xxx"
xing_ming = "xxx"
xingMing = "xxx"
name = "xxx"
1.2 Python代码潜规则
变量+函数+方法+文件名
my_car = "汽车"
类名
class UserInfo(object):
pass
1.3 关于注释
1.4 关于脚本
1.5 内部功能,要避免3层以上的if
- 简单逻辑先处理
- return实现
def user_add(request):
form = UserForm(data=request.POST)
if form.is_valid():
# 成功
form.save()
# 生成Excel文件
# 上传到腾讯云存储中
# 将获取的ID持久化保存至数据库和redis
if 11==1:
pass
else:
# 失败
return render(request,"user_add.html", {"form":form })
def user_add(request):
form = UserForm(data=request.POST)
# 错误
if not form.is_valid():
return render(request,"user_add.html", {"form":form })
# 成功
form.save()
# 生成Excel文件
# 上传到腾讯云存储中
# 将获取的ID持久化保存至数据库和redis
if 11==1:
pass
1.6 善用数据类型的结构
def login():
pass
def register():
pass
def download():
pass
def run():
mapping = {"1":login, "2":register, "3":download}
num = input("输入:")
func = mapping.get(num)
if not func:
输入错误
return
func()
关于样式
这个网站找一找,复制黏贴
https://v3.bootcss.com/components/#navbar
模板
{% load permission %}
{% load menu %}
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="{% static 'plugins/bootstrap/css/bootstrap.min.css' %}">
<link rel="stylesheet" href="{% static 'plugins/font-awesome/css/font-awesome.min.css' %}">
<link rel="stylesheet" href="{% static 'css/commons.css' %}">
<link rel="stylesheet" href="{% static 'css/menu.css' %}">
<link rel="stylesheet" href="{% static 'css/nav.css' %}">
</head>
<body>
<div class="pg-header">
<div class="nav">
<div class="logo-area left">
<a href="{% url 'home' %}">
<span style="font-size: 18px;">NB的管理平台 </span>
</a>
</div>
<div class="right-menu right clearfix">
<div class="user-info right">
<a href="#" class="avatar" style="text-decoration: none;">
<span style="color: white;margin-right: 5px;">{{ request.nb_user.name }}</span>
<img class="img-circle" style="width: 35px;height: 35px;" src="{% static 'images/default.png' %}">
</a>
<div class="more-info">
<a href="{% url 'login' %}" class="more-item">注销1</a>
<a href="{% url 'login' %}" class="more-item">注销2</a>
<a href="{% url 'login' %}" class="more-item">注销3</a>
<a href="{% url 'logout' %}" class="more-item">注销3</a>
</div>
</div>
</div>
</div>
</div>
<div class="pg-body">
<div class="left-menu">
<div class="menu-body">
{% nb_menu request %}
</div>
</div>
<div class="right-body">
{% nb_breadcrumb request %}
<div style="padding: 0 20px 20px 20px;">
{% block content %}{% endblock %}
</div>
</div>
</div>
<script src="{% static 'js/jquery.js' %}"></script>
<script src="{% static 'js/menu.js' %}"></script>
</body>
</html>
其余页面便可以继承了
{% extends 'layout.html' %}
{% block content %}
<h1>欢迎登录{{ request.nb_user.name }}</h1>
{% endblock %}
级别相关
先插入好数据
展示
from django.shortcuts import render, redirect
from app01 import models
def level_list(request):
queryset = models.Level.objects.filter(active=1).order_by("-percent")
return render(request, "level_list.html", {"queryset": queryset})
{% extends 'layout.html' %}
{% block content %}
{#加上边框#}
<table class="table table-bordered">
<thead>
<tr>
<th>ID</th>
<th>标题</th>
<th>折扣</th>
<th>选项</th>
</tr>
</thead>
<tbody>
{% for row in queryset %}
<tr>
<td>{{ row.id }}</td>
<td>{{ row.title }}</td>
<td>{{ row.percent }}</td>
<td>
<a>编辑</a>
<a>删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
添加功能
class LevelModelForm(BootStrapForm, forms.ModelForm):
class Meta:
model = models.Level
fields = ["title", "percent"]
def level_add(request):
if request.method == "GET":
form = LevelModelForm()
return render(request, "level_add.html", {"form": form})
{% extends 'layout.html' %}
{% block content %}
<form method="post">
{% csrf_token %}
{% for field in form %}
<div>{{ form.label }}{{ field }}{{ field.errors }}</div>
{% endfor %}
</form>
{% endblock %}
优化
def level_add(request):
if request.method == "GET":
form = LevelModelForm()
return render(request, "level_add.html", {"form": form})
form = LevelModelForm(data=request.POST)
if not form.is_valid():
return render(request, "level_add.html", {"form": form})
form.save()
return redirect("level_list")
{% extends 'layout.html' %}
{% block content %}
<form method="post" novalidate>
<div class="row clearfix">
{% for field in form %}
{% csrf_token %}
<div class="col-sm-6">
<div class="form-group" style="position: relative;margin-bottom: 25px">
<label for="{{ field.id_for_label }}">
{{ field.label }}
{% if field.help_text %}
<span style="font-weight: 400;color: #333333;">({{ field.help_text }})</span>
{% endif %}
</label>
{{ field }}
<span style="color: red;position: absolute;">{{ field.errors.0 }}</span>
</div>
</div>
{% endfor %}
</div>
<button type="submit" class="btn btn-primary">保 存</button>
</form>
{% endblock %}
编辑功能
path('level/edit/<int:nid>/', level.level_edit, name='level_edit'),
def level_edit(request, nid):
instance = models.Level.objects.filter(id=nid, active=1).first()
if request.method == "GET":
form = LevelModelForm(instance=instance)
return render(request, "level_edit.html", {"form": form})
form = LevelModelForm(data=request.POST, instance=instance)
if not form.is_valid():
return render(request, "level_edit.html", {"form": form})
form.save()
return redirect(level_list)
优化小bug
这里的id并不按一定顺序排列
我们这里选择加计数器
<td>{{ forloop.counter }}</td>
补充
- 数据的ID,不连续 & 其他顺序
(当前页-1) * 20 + forloop.counter
1 1/2/3/4/5....20
2 21/22/23/....40
- 模版的循环
common.py
from django.template import Library
register = Library()
@register.simple_tag()
def loop_counter(request, counter):
page = request.GET.get("page", "1")
if not page.isdecimal():
page = "1"
page = int(page)
if page < 1:
page = 1
return (page - 1) * 20 + counter
{% extends 'layout.html' %}
{% load common %}
{% block content %}
{# 权限判断#}
<div style="margin-top: 5px;">
<a class="btn btn-primary" href="{% url 'level_add' %}">添加</a>
</div>
{#加上边框#}
<table class="table table-bordered">
<thead>
<tr>
<th>ID</th>
<th>标题</th>
<th>折扣</th>
<th>选项</th>
</tr>
</thead>
<tbody>
{% for row in queryset %}
<tr>
<td>{% loop_counter request forloop.counter %}</td>
<td>{{ row.id }}</td>
<td>{{ row.title }}</td>
<td>{{ row.percent }}</td>
<td>
{# 权限判断#}
<a href="{% url 'level_edit' nid=row.id %}">编辑</a>
<a>删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
删除功能
这个和编辑功能类似
前端去复制
<div class="alert alert-success" role="alert">...</div>
<div class="alert alert-info" role="alert">...</div>
<div class="alert alert-warning" role="alert">...</div>
<div class="alert alert-danger" role="alert">...</div>
{% extends 'layout.html' %}
{% block content %}
<div class="alert alert-danger alert-dismissible fade in" role="alert">
<form method="post">
{% csrf_token %}
<h4>是否确定删除?</h4>
<p>删除后,数据将恢复 or 删除后请去回收站进行回收。</p>
<p>
<input type="submit" value="确定" class="btn btn-danger"/>
<a class="btn btn-default">取消</a>
</p>
</form>
</div>
{% endblock %}
实现回退的功能
即点击取消以后,自动回到原页面
{# 权限判断#}
<a href="{% url 'level_edit' nid=row.id %}">编辑</a>
<a href="{% url 'level_delete' nid=row.id %}?redirect=/level/list/">删除</a>
<h4>是否确定删除?</h4>
<p>删除后,数据将恢复 or 删除后请去回收站进行回收。</p>
<p>
<input type="submit" value="确定" class="btn btn-danger"/>
<a class="btn btn-default" href="{{ origin }}">取消</a>
</p>
def level_delete(request, nid):
origin = request.GET.get("redirect")
print(":::", origin)
if request.method == "GET":
return render(request, 'level_delete.html', {"origin": origin})
# models.Level.objects.filter(id=nid, active=1).delete()
models.Level.objects.filter(id=nid, active=1).update(active=0)
return redirect(origin)
也可以自行创建函数处理复杂的路由
@register.simple_tag()
def url_plus(request, name, *args, **kwargs):
prev = reverse(name, args=args, kwargs=kwargs)
# param = quote_plus("/level/list/?page=19&xx=10")
# 获取当前请求的URL
from django.core.handlers.wsgi import WSGIRequest
current_url = request.get_full_path()
param = quote_plus(current_url)
return f"{prev}?redirect={param}"
价格策略
url.py
path('price/list/', price.price_list, name='price_list'),
path('price/add/', price.price_add, name='price_add'),
path('price/edit/<int:nid>/', price.price_edit, name='price_edit'),
path('price/delete/<int:nid>/', price.price_delete, name='price_delete'),
settings.py
"ADMIN": [
{
"text": "账户中心",
'icon': "fa-bank",
"children": [
{"text": "级别管理", "name": "level_list", "url": "/level/list/"},
{"text": "价格策略", "name": "price_list", "url": "/price/list/"},
]
},
views.py
类似level.py
from django.shortcuts import render, redirect
from app01 import models
from django import forms
from utils.boostrap import BootStrapForm
class PriceModelForm(BootStrapForm, forms.ModelForm):
class Meta:
model = models.PricePolicy
fields = ["count", "price"]
def price_list(request):
queryset = models.PricePolicy.objects.all().order_by("count")
return render(request, "price_list.html", {"queryset": queryset})
def price_add(request):
origin = request.GET.get("redirect")
if request.method == "GET":
form = PriceModelForm()
return render(request, "form2.html", {"form": form})
form = PriceModelForm(data=request.POST)
if not form.is_valid():
return render(request, "form2.html", {"form": form})
form.save()
return redirect(origin)
def price_edit(request, nid):
origin = request.GET.get("redirect")
instance = models.PricePolicy.objects.filter(id=nid).first()
if request.method == "GET":
form = PriceModelForm(instance=instance)
return render(request, "form2.html", {"form": form})
form = PriceModelForm(data=request.POST, instance=instance)
if not form.is_valid():
return render(request, "form2.html", {"form": form})
form.save()
return redirect(origin)
def price_delete(request, nid):
origin = request.GET.get("redirect")
# print(":::", origin)
if request.method == "GET":
return render(request, 'price_delete.html', {"origin": origin})
# models.Level.objects.filter(id=nid, active=1).delete()
models.PricePolicy.objects.filter(id=nid, active=1).update(active=0)
return redirect(origin)
html
{% extends 'layout.html' %}
{% load common %}
{% load permission %}
{% block content %}
{# 权限判断#}
<div style="margin-top: 5px;">
<a class="btn btn-primary" href="{% url_plus request 'price_add' %}">添加</a>
</div>
{#加上边框#}
<table class="table table-bordered">
<thead>
<tr>
<th>ID</th>
<th>数量</th>
<th>价格</th>
<th>选项</th>
</tr>
</thead>
<tbody>
{% for row in queryset %}
<tr>
<td>{% loop_counter request forloop.counter %}</td>
<td>{{ row.id }}</td>
<td>{{ row.count }}</td>
<td>¥{{ row.price }}</td>
<td>
{# 权限判断#}
{% if request|has_permission:"price_edit" %}
<a class="btn btn-success btn-xs" href="{% url_plus request 'price_edit' nid=row.id %}">编辑</a>
{# <a href="{% url 'level_delete' nid=row.id %}?redirect=/level/list/">删除</a>#}
{% endif %}
{% if request|has_permission:"price_delete" %}
<a class="btn btn-danger btn-xs"
href="{% url_plus request 'price_delete' nid=row.id %}">删除</a>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
form2
{% extends 'layout.html' %}
{% block content %}
<form method="post" novalidate>
<div class="row clearfix">
{% for field in form %}
{% csrf_token %}
<div class="col-sm-6">
<div class="form-group" style="position: relative;margin-bottom: 25px">
<label for="{{ field.id_for_label }}">
{{ field.label }}
{% if field.help_text %}
<span style="font-weight: 400;color: #333333;">({{ field.help_text }})</span>
{% endif %}
</label>
{{ field }}
<span style="color: red;position: absolute;">{{ field.errors.0 }}</span>
</div>
</div>
{% endfor %}
</div>
<button type="submit" class="btn btn-primary">保 存</button>
</form>
{% endblock %}
增删改查
分页组件应用
boostrap:
<nav aria-label="Page navigation">
<ul class="pagination">
<li>
<a href="#" aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
</li>
<li><a href="#">1</a></li>
<li><a href="#">2</a></li>
<li><a href="#">3</a></li>
<li><a href="#">4</a></li>
<li><a href="#">5</a></li>
<li>
<a href="#" aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
</ul>
</nav>
pager.py
import copy
from django.utils.safestring import mark_safe
class Pagination(object):
""" 分页 """
def __init__(self, request, query_set, per_page_count=10):
self.query_dict = copy.deepcopy(request.GET)
self.query_dict._mutable = True
self.query_set = query_set
total_count = query_set.count()
self.total_count = total_count
# 计算出总共有多少页面
self.total_page, div = divmod(total_count, per_page_count)
if div:
self.total_page += 1
# 字符串格式 123908sdfsdf
page = request.GET.get('page', "1")
if not page.isdecimal():
page = 1
else:
page = int(page)
if page <= 0:
page = 1
if page > self.total_page:
page = self.total_page
self.page = page
self.per_page_count = per_page_count
self.start = (page - 1) * per_page_count
self.end = page * per_page_count
def html(self):
pager_list = []
if not self.total_page:
return ""
# 总页码小于11
if self.total_page <= 11:
start_page = 1
end_page = self.total_page
else:
# 总页码比较多
# 判断当前页 <=6: 1~11
if self.page <= 6:
start_page = 1
end_page = 11
else:
if (self.page + 5) > self.total_page:
start_page = self.total_page - 10
end_page = self.total_page
else:
start_page = self.page - 5
end_page = self.page + 5
pager_list.append('<ul class="pagination">')
self.query_dict.setlist('page', [1])
pager_list.append('<li><a href="?{}">首页</a></li>'.format(self.query_dict.urlencode()))
if self.page > 1:
self.query_dict.setlist('page', [self.page - 1])
pager_list.append('<li><a href="?{}">上一页</a></li>'.format(self.query_dict.urlencode()))
for i in range(start_page, end_page + 1):
self.query_dict.setlist('page', [i])
if i == self.page:
item = '<li class="active"><a href="?{}">{}</a></li>'.format(self.query_dict.urlencode(), i)
else:
item = '<li><a href="?{}">{}</a></li>'.format(self.query_dict.urlencode(), i)
pager_list.append(item)
if self.page < self.total_page:
self.query_dict.setlist('page', [self.page + 1])
pager_list.append('<li><a href="?{}">下一页</a></li>'.format(self.query_dict.urlencode()))
self.query_dict.setlist('page', [self.total_page])
pager_list.append('<li><a href="?{}">尾页</a></li>'.format(self.query_dict.urlencode()))
pager_list.append('<li class="disabled"><a>数据{}条{}页</a></li>'.format(self.total_count, self.total_page))
pager_string = mark_safe("".join(pager_list))
pager_list.append('</ul>')
return pager_string
def queryset(self):
if self.total_count:
return self.query_set[self.start:self.end]
return self.query_set
list.html
{% extends 'layout.html' %}
{% load common %}
{% load permission %}
{% block content %}
{# 权限判断#}
<div style="margin-top: 5px;">
<a class="btn btn-primary" href="{% url_plus request 'price_add' %}">添加</a>
</div>
{#加上边框#}
<table class="table table-bordered">
<thead>
<tr>
<th>ID</th>
<th>数量</th>
<th>价格</th>
<th>选项</th>
</tr>
</thead>
<tbody>
{% for row in pager.queryset %}
<tr>
<td>{% loop_counter request forloop.counter %}</td>
<td>{{ row.id }}</td>
<td>{{ row.count }}</td>
<td>¥{{ row.price }}</td>
<td>
{# 权限判断#}
{% if request|has_permission:"price_edit" %}
<a class="btn btn-success btn-xs" href="{% url_plus request 'price_edit' nid=row.id %}">编辑</a>
{# <a href="{% url 'level_delete' nid=row.id %}?redirect=/level/list/">删除</a>#}
{% endif %}
{% if request|has_permission:"price_delete" %}
<a class="btn btn-danger btn-xs"
href="{% url_plus request 'price_delete' nid=row.id %}">删除</a>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{{ pager.html }}
{% endblock %}
效果:
组件的封装
修改settings.py的配置
views.nb.py
from app01 import models
from django.shortcuts import render
from django import forms
from utils.boostrap import BootStrapForm
from utils.pager import Pagination
class PriceModelForm(BootStrapForm, forms.ModelForm):
class Meta:
model = models.PricePolicy
fields = ["count", "price"]
class LevelModelForm(BootStrapForm, forms.ModelForm):
class Meta:
model = models.Level
fields = ["title", "percent"]
class BaseCurd(object):
list_template_name = "nb_list.html"
@classmethod
def list(cls, request):
# cls=LevelCurd PriceCurd
queryset = cls.get_queryset(request)
pager = Pagination(request, queryset)
context = {"pager": pager,
"url_add_name": cls.url_add_name,
"url_edit_name": cls.url_edit_name,
"url_delete_name": cls.url_delete_name,
"table_header": cls.table_header,
"table_field": cls.table_field
}
return render(request, cls.list_template_name, context)
@classmethod
def get_queryset(cls, request):
return cls.queryset
class LevelCurd(BaseCurd):
url_add_name = None
url_edit_name = "level_edit"
url_delete_name = "level_delete"
table_header = ["标题", "折扣"]
table_field = ["title", "percent"]
queryset = models.Level.objects.filter(active=1).order_by("-percent")
class PriceCurd(BaseCurd):
url_add_name = "price_add"
url_edit_name = "price_edit"
url_delete_name = "price_delete"
table_header = ["数量", "价格"]
table_field = ["count", "price"]
queryset = models.PricePolicy.objects.all().order_by("count")
nb_list.html
{% extends 'layout.html' %}
{% load common %}
{% load permission %}
{% block content %}
{# 权限判断#}
{% if request|has_permission:url_add_name %}
<div style="margin-top: 5px;">
<a class="btn btn-primary" href="{% url_plus request url_add_name %}">添加</a>
</div>
{% endif %}
{#加上边框#}
<table class="table table-bordered">
<thead>
<tr>
<th>ID</th>
{% for item in table_header %}
<th>{{ item }}</th>
{% endfor %}
<th>选项</th>
</tr>
</thead>
<tbody>
{% for row in pager.queryset %}
<tr>
<td>{% loop_counter request forloop.counter %}</td>
{% for name in table_field %}
{# 自定义simple_tag#}
<td>{% getattr_plus row name %}</td>
{% endfor %}
<td>
{# 权限判断#}
{% if request|has_permission:url_edit_name %}
<a class="btn btn-success btn-xs" href="{% url_plus request 'price_edit' nid=row.id %}">编辑</a>
{# <a href="{% url 'level_delete' nid=row.id %}?redirect=/level/list/">删除</a>#}
{% endif %}
{% if request|has_permission:url_delete_name %}
<a class="btn btn-danger btn-xs"
href="{% url_plus request 'price_delete' nid=row.id %}">删除</a>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{{ pager.html }}
{% endblock %}
common.py
@register.simple_tag()
def getattr_plus(obj, name):
return getattr(obj, name)
新建&&编辑
删除