提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
提示:以下是本篇文章正文内容,下面案例可供参考
总结、Django知识点回顾
- 安装Django
pip install django
- 创建Django项目
django-admin startproject mysite
注意: Pycharm可以创建。如果用Pycharm创建,记得settings.py中的DIR templates 删除
- 创建app&注册
python manage.py startapp app01
python manage.py startapp app02>>>python manage.py startapp app03
python
INSTALLED APPS = [
...
'app01.apps.App0lConfig'
]
注意:否则app下的models.py写类时,无法在数据库中创建表
-
配置静态文件路径&模板的路径 (放在app目录下)
-
配置数据库相关操作(MySQL)
-
第三方模块(django3版本)
pip install mysqlclient
'
- 自己先去MySQL创建一个数据库
- 配置数据库连接settingspy
python
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': "gx_day1", # 数据库名字
"USER":'root',
'PASSWORD':'12345',#密码
'HOST':'127.0.0.1',
'POST':3306,# 那台机器安装了MySQLPORT': 3306
}
}
- 在app下的models.py中编写
python
from django.db import models
class Admin(models.Model):
"""管理员"""
username = models.CharField(verbose_name="用户名",max_length=32)
password = models.CharField(verbose_name="密码",max_length=64)
def __str__(self):
return self.username #连接表中所显示的内容
class Department(models.Model):
"""部门表"""
title =models.CharField(verbose_name="标题",max_length=32)
def __str__(self):
return self.title
class UserInfo(models.Model):
"""员工表"""
name =models.CharField(verbose_name="姓名",max_length=32)
password =models.CharField(verbose_name="密码",max_length=32)
age =models.IntegerField(verbose_name="年龄")
account =models.DecimalField(verbose_name="余额",max_digits=10,decimal_places=2,default=0)
creat_time =models.DateField(verbose_name="入职时间")
# 有约束 on_delete=models.CASCADE级联删除
depart = models.ForeignKey(verbose_name="所属部门",to="Department",to_field="id",on_delete=models.CASCADE)
# 链接部分被删除时置空
# depart = models.ForeignKey(to="Department",to_field="id",null=True,blank=True,on_delete=models.SET_NULL)
# 在django中做的约束
gender_choices=(
(1,"男"),
(2,"女"),
)
gender =models.SmallIntegerField(verbose_name="性别",choices=gender_choices)
class PrettyNum(models.Model):
"""靓号表"""
mobile = models.CharField(verbose_name="电话", max_length=11)
price = models.IntegerField(verbose_name="单价",default=0)
level_choices = (
(1, "1级"),
(2, "2级"),
(3, "3级"),
(4, "4级"),
)
level = models.SmallIntegerField(verbose_name="级别", choices=level_choices,default=1)
status_choices = (
(1, "已占用"),
(2, "未占用"),
)
status = models.SmallIntegerField(verbose_name="状态", choices= status_choices,default=2)
class Task(models.Model):
"""任务"""
level_choices=(
(1,"临时"),
(2,"重要"),
(3,"紧急"),
)
level = models.SmallIntegerField(verbose_name="级别",choices=level_choices,default = 1)
title = models.CharField(verbose_name="标题",max_length=64)
detail = models.TextField(verbose_name="详细信息")
user = models.ForeignKey(verbose_name="负责人",to="Admin",on_delete=models.CASCADE)
class Order(models.Model):
"""订单号"""
oid = models.CharField(verbose_name="订单号",max_length=64)
title = models.CharField(verbose_name="名称",max_length=32)
price = models.IntegerField(verbose_name="价格")
status_choices={
(1,"待支付"),
(2,"已支付"),
}
status = models.SmallIntegerField(verbose_name="状态",choices = status_choices,default=1)
admin = models.ForeignKey(verbose_name="管理员",to="Admin",on_delete=models.CASCADE)
class City(models.Model):
name = models.CharField(verbose_name="名称",max_length=32)
count = models.IntegerField(verbose_name="人口")
img = models.FileField(verbose_name="Logo",max_length=32,upload_to="city/")
- 执行两个命令
-
在urls.py,路由 (URL和函数的对应关系)
-
在views.py,视图函数,编写业务逻辑。
-
templates目录,编写HTML模板 (含有模板语法、继承、{% static 'xx' %})
-
ORM操作
python
models.User.objects .filter(id="xxx")
models.User.objects .filter(id="xxx").order_by("-id")
- **ModelForm & Form组件,在我们开发增删改查功能**
- 生成HTML标签(生成默认值)
- 请求数据进行校验
- 保存到数据库 (ModelForm)
- 获取错误信息
- Cookie和Session,用户登录信息保存起来
- Bootstrap样式(封装使用)
python
from django import forms
class BootStrap:
bootstrap_exclude_fields = []
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# 循环找到所有的插件,添加了"class":"form-control"得样式
for name, field in self.fields.items():
if name in self.bootstrap_exclude_fields:
continue
# 字段中有属性,保留原来的属性,没有属性,才增加
if field.widget.attrs:
# 有则添加字典值
field.widget.attrs["class"] = "form-control"
field.widget.attrs["placeholder"] = field.label
else:
field.widget.attrs = {
"class": "form-control",
"placeholder": field.label
}
class BootstrapModelForm(BootStrap,forms.ModelForm):
pass
class BootstrapForm(BootStrap,forms.Form):
pass
- 分页组件(封装使用)
python
"""
自定义分页组件 如果以后想要使用这个分页组件,你需要做如下几件事:
在视图函数views.py函数中:
def pretty_list(request):
#1.根据所需筛选数据
queryset = models.PrettyNum.objects.all()
#2.实例化分页对象
page_object = Pagination(request,queryset,page_size=2)
context ={
"queryset": page_object.page_queryset, #分完页的数据
"page_string": page_object.html() #生成页码
}
return render(request, 'pretty_list.html',context)
在html页面中
<ul class="pagination">
{{ page_string }}
</ul>
"""
from django.utils.safestring import mark_safe
class Pagination(object):
def __init__(self,request,queryset,page_size=10,page_param="page",plus=5):
"""
:param request: 请求对象
:param queryset: 符合条件的数据
:param page_size: 每页显示多少条数据
:param page_param: 在URL中传递的获取分页的参数 例如/pretty/list/?page=4
:param plus:显示当前页的前或后几页(页码)
"""
import copy
query_dict = copy.deepcopy(request.GET)
query_dict._mutable = True
self.query_dict = query_dict
page = request.GET.get(page_param, "1")
if page.isdecimal():
page=int(page)
else:
page=1
self.page =page
self.page_size=page_size
self.page_param=page_param
self.start = (page - 1) * page_size
self.end = page * page_size
self.page_queryset = queryset[self.start:self.end]
total_count = queryset.count()
total_page_count, div = divmod(total_count, page_size)
if div:
total_page_count += 1
self.total_page_count =total_page_count
self.plus=plus
def html(self):
# 计算出显示当前页的的前五页后五页
# 数据较少,显示全部页码
if self.total_page_count <= 2 * self.plus + 1:
start_page = 1
end_page = self.total_page_count
else:
# 数据较多
# 当前页<5
if self.page <= self.plus:
start_page = 1
end_page = 2 * self.plus + 1
else:
# 当前页>5
# 当前页+5>总页面
if (self.page + self.plus) > self.total_page_count:
start_page = self.total_page_count - 2 * self.plus
end_page = self.total_page_count
else:
start_page = self.page - self.plus
end_page = self.page + self.plus
# 页码
page_str_list = []
self.query_dict.setlist(self.page_param,[1])
first = '<li><a href="?{}">首页</a></li>'.format(self.query_dict.urlencode())
page_str_list.append(first)
# 上一页
if self.page > 1:
self.query_dict.setlist(self.page_param,[self.page-1])
prev = '<li><a href="?{}">《</a></li>'.format(self.query_dict.urlencode())
else:
prev = '<li><a href="?{}">《</a></li>'.format(1)
page_str_list.append(prev)
for i in range(start_page, end_page + 1):
self.query_dict.setlist(self.page_param,[i])
if i == self.page:
ele = '<li class="active"><a href="?{}">{}</a></li>'.format(self.query_dict.urlencode(), i)
else:
ele = '<li><a href="?{}">{}</a></li>'.format(self.query_dict.urlencode(), i)
page_str_list.append(ele)
if self.page >= self.total_page_count:
self.query_dict.setlist(self.page_param,[self.page+1])
next = '<li><a href="?{}">》</a></li>'.format(self.query_dict.urlencode())
else:
self.query_dict.setlist(self.page_param,[self.total_page_count])
next = '<li><a href="?{}">》</a></li>'.format(self.query_dict.urlencode())
page_str_list.append(next)
# 尾页
self.query_dict.setlist(self.page_param,[self.total_page_count])
end = '<li><a href="?{}">尾页</a></li>'.format(self.query_dict.urlencode())
page_str_list.append(end)
search_string = """
<li >
<form method="get" style="float: left">
<input type="text"
class="form-control" name="page" placeholder="页码"
style="width: 80px;position: relative;float: left;display: inline-block;border-radius: 0">
<button type="submit" class="btn btn-default">跳转</button>
</form>
</li>
"""
page_str_list.append(search_string)
page_string = mark_safe("".join(page_str_list))
return page_string
- 中间件(封装使用)
-
- 中间件,基于中间件实现用户认证,基于:process request。
python
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import redirect
class AuthMiddleware(MiddlewareMixin):
"""中间件"""
def process_request(selfself,request):
#0.排除那些不需要登录就能访问的页面
#request.path_info 获取当前用户请求的url /login/
if request.path_info in["/login/","/image/code/"]:
return
#1.读取当前访问的用户的session信息,如果能读到,说明已经登录过,可以继续向后走
info_dict = request.session.get("info")
print(info_dict)
if info_dict:
return
#2.没有登录过,重新回到登录页面
return redirect("/login/")
- 验证码(封装使用)
python
# pillow创建图片
# from PIL import Image,ImageDraw,ImageFont
#
# img = Image.new(mode='RGB',size=(120,30),color=(255,255,255))
# draw =ImageDraw.Draw(img,mode='RGB')
#
# font =ImageFont.truetype("Rainbow-Party-2.ttf",18)
# draw.text([0, 0],'python','red',font=font)
#
# with open('code.png','wb') as f:
# img.save(f,format='png')
import random
from PIL import Image, ImageDraw, ImageFont, ImageFilter
def check_code(width=120, height=30, char_length=5, font_file='D:\pythonproject\Django_project\mysite2\Rainbow-Party-2.ttf', font_size=20):
code = []
img = Image.new(mode='RGB', size=(width, height), color=(255, 255, 255))
draw = ImageDraw.Draw(img, mode='RGB')
def rndChar():
"""生成随机字母"""
# return chr(random.randint(65, 90))
return str(random.randint(0,9))
def rndColor():
return (random.randint(0, 255), random.randint(10, 255), random.randint(64, 255))
# 写文字
font = ImageFont.truetype(font_file, font_size)
for i in range(char_length):
char = rndChar()
code.append(char)
h = random.randint(0, 4)
draw.text([i * width / char_length, h], char, font=font, fill=rndColor())
# 写干扰点
for i in range(40):
x = random.randint(0, width)
y = random.randint(0, height)
draw.point((x, y), fill=rndColor())
# 写干扰圆圈
for i in range(40):
draw.point([random.randint(0, width), random.randint(0, height)], fill=rndColor())
x = random.randint(0, width)
y = random.randint(0, height)
draw.arc((x, y, x + 4, y + 4), 0, 90, fill=rndColor())
# 写干扰线
for i in range(5):
x1 = random.randint(0, width)
y1 = random.randint(0, height)
x2 = random.randint(0, width)
y2 = random.randint(0, height)
draw.line((x1, x2, y1, y2), fill=rndColor())
img = img.filter(ImageFilter.EDGE_ENHANCE_MORE)
return img, ''.join(code)
- Ajax请求 (可跳转到【web开发】9、Django(4)ajax请求处学习)
python
{% block js %}
<script type="text/javascript">
var DELETE_ID
var EDIT_ID
$(function () {
bindBtnAddEvent();
bindBtnSaveEvent();
bindBtnDeleteEvent();
bindBtnConfirmDeleteEvent();
bindBtnEditEvent();
})
function bindBtnAddEvent() {
$('#btnAdd').click(function () {
{#将正在编辑的ID设置为空#}
EDIT_ID = undefined;
{#清空对话框中的数据#}
$("#formSave")[0].reset();
$("#myModalLabel").text("新建")
$('#myModal').modal('show')
});
}
function bindBtnSaveEvent() {
$("#btnSave").click(function () {
{#清除错误信息#}
$(".error-msg").empty();
if (EDIT_ID) {
//编辑
doEdit();
} else {
//添加
doAdd();
}
function doEdit() {
$.ajax({
url: '/order/edit/' + "?uid=" + EDIT_ID,
type: "post",
data: $("#formSave").serialize(),
dataType: "JSON",
success: function (res) {
if (res.status) {
alert("添加成功");
{##清空表单#}
$("#formSave")[0].reset();
{#关闭对话框#}
$('#myModal').modal('hide')
{#添加自动刷新#}
location.reload();
} else {
if (res.tips) {
alert(res.tips);
} else {
$.each(res.error, function (name, errorlist) {
{#console.log(name, errorlist)#}
$("#id_" + name).next().text(errorlist[0]);
})
}
}
}
})
}
function doAdd() {
$.ajax({
url: '/order/add/',
type: "post",
data: $("#formSave").serialize(),
dataType: "JSON",
success: function (res) {
if (res.status) {
alert("添加成功");
{##清空表单#}
$("#formSave")[0].reset();
{#关闭对话框#}
$('#myModal').modal('hide')
{#添加自动刷新#}
location.reload();
} else {
{#console.log(res.error);#}
$.each(res.error, function (name, errorlist) {
{#console.log(name, errorlist)#}
$("#id_" + name).next().text(errorlist[0]);
})
}
}
})
}
{#向后台发送请求(添加ajax请求#}
})
}
function bindBtnDeleteEvent() {
$(".btn-delete").click(function () {
{#alert("点击了删除");#}
$("#deleteModal").modal('show');
{# 获取当前行的ID并赋值给全局变量 #}
DELETE_ID = $(this).attr("uid");
})
}
function bindBtnConfirmDeleteEvent() {
$("#btnConfirmDelete").click(function () {
{# 确认删除按钮,将确定删除的id发送给后台#}
$.ajax({
url: "/order/delete/",
type: "GET",
data: {
uid: DELETE_ID
},
dataType: "JSON",
success: function (res) {
if (res.status) {
{#alert("删除成功");#}
{#$('#deleteModal').modal('hide');#}
{#location.reload();#}
{# 在页面上将当前一行数据删除#}
{#$("tr[uid='"+DELETE_ID +"']").remove();#}
{# 要删除的id置为空#}
{#DELETE_ID = 0;#}
location.reload();
} else {
alert(res.error);
}
}
})
})
}
function bindBtnEditEvent() {
$(".btn-edit").click(function () {
var uid = $(this).attr("uid");
EDIT_ID = uid
{#设置对话框标题#}
$("#myModalLabel").text("编辑")
{#alert("点击了编辑");#}
{# 发送ajax去后端获取当前行的相关数据#}
$.ajax({
url: "/order/detail/",
type: "get",
data: {
uid: uid
},
dataType: "JSON",
success: function (res) {
if (res.status) {
$.each(res.data, function (name, value) {
$("#id_" + name).val(value);
})
$("#myModal").modal('show');
} else {
alert(res.error)
}
}
})
{# 在对话框中默认看到#}
})
}
</script>
-
数据统计 (可跳转到【web开发】10、数据统计(echarts)--柱状图、折线图、饼图 处学习)
-
文件上传 (可跳转到【web开发】11、文件的上传 处学习)