知识点回顾
安装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
INSTALLED_APPS={
...
'app01.apps.App01Config'
}
注意:否则app下的models.py写类时,无法在数据库中创建表
配置 静态文件目录和模版目录
app01
-static
-templates
配置 数据库相关操作
第三方模块(django3版本)
pip install mysqlclient
手动去mysql创建数据库
create database test default charset utf8 collate utf8_general_ci;
配置数据库连接(settings.py)
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'manage', #数据库的名字
'HOST': '127.0.0.1', #数据库地址
'PORT': '3306', #端口
'USER': 'root', #用户名
"PASSWORD": 'root123456', #密码
}
}
在app下的models.py中编写数据表
from django.db import models
class Department(models.Model):
# 部门表
title = models.CharField(verbose_name="标题", max_length=32)
def __str__(self):
return self.title
数据库生成表:
python manage.py makemigration
python manage.py migrate
在urls.py中编写路由(URL和函数的对应关系)
在views.py中编写视图函数,编写业务逻辑(ModelForm、Form组件,开发增删改查功能)
- 生成HTML标签
- 请求数据进行校验
- 保存到数据库(ModelForm)
- 获取错误信息
templates目录,编写HTML模版(含有模版语法、继承模版、{%static “xxx” %}
Cookie、Session,将用户登录信息保存起来
中间件
基于中间件实现用户认证,基于process_request方法
ORM操作
models.User.objects.filter(id="xxx")
models.User.objects.filter(id="xxx").order_by
分页组件pagination.py
ajax请求
展示任务列表
views/task.py
def task_list(request):
queryset=models.Task.objects.all().order_by('-id')
form = TaskModelForm()
page_object = Pagination(request, queryset)
context = {
"form": form,
"queryset": page_object.page_queryset, # 分完页的数据
"page_string": page_object.html() # 页码html
}
return render(request, "task_list.html", context)
templates/task_list.html
<div class="bs-example" data-example-id="table-within-panel">
<div class="panel panel-default">
<!-- Default panel contents -->
<div class="panel-heading">
<span class="glyphicon glyphicon-th-list" aria-hidden="true"></span>
任务列表
</div>
<!-- Table -->
<table class="table table-bordered">
<thead>
<tr>
<th>ID</th>
<th>标题</th>
<th>级别</th>
<th>负责人</th>
</tr>
</thead>
<tbody>
{% for obj in queryset %}
<tr>
<th>{{obj.id}}</th>
<td>{{obj.title}}</td>
<td>{{obj.get_level_display}}</td>
<td>{{obj.user.username}}</td>
<td>
<a class="btn btn-primary btn-xs" href="/admin/{{obj.id}}/edit/">编辑 </a>
<a class="btn btn-danger btn-xs" href="/admin/{{obj.id}}/delete/">删除 </a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="clearfix">
<ul class="pagination">
{{page_string}}
</ul>
</div>
</div>
订单管理
models.py
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)
urls.py
#订单管理
path('order/list/',order.order_list),
path('order/add/',order.order_add),
path('order/delete/', order.order_delete),
path('order/detail/',order.order_detail ),
path('order/edit/',order.order_edit ),
views/order.py
import random
from datetime import datetime
from django import forms
from django.http import JsonResponse
from django.shortcuts import render, HttpResponse
from django.views.decorators.csrf import csrf_exempt
from app01.utils.bootstrap import BootstrapModelForm
from app01 import models
from app01.utils.pagination import Pagination
import json
class OrderModelForm(BootstrapModelForm):
class Meta:
model = models.Order
fields = "__all__"
exclude = ["oid", 'admin']
def order_list(request):
form = OrderModelForm()
queryset = models.Order.objects.all().order_by('-id')
page_object = Pagination(request, queryset)
context = {
"form": form,
"queryset": page_object.page_queryset, # 分完页的数据
"page_string": page_object.html() # 页码html
}
return render(request, "Order_list.html", context)
@csrf_exempt
def order_add(request):
form = OrderModelForm(data=request.POST)
if form.is_valid():
# 随机订单号:额外增加一些不是用户输入的值
form.instance.oid = datetime.now().strftime("%Y%m%d%H%M%S") + \
str(random.randint(1000, 1999))
# 管理员:当前登录的管理员id
form.instance.admin_id = request.session["info"]["id"]
form.save()
return JsonResponse({"status": True})
return JsonResponse({"status": False, "errors": form.errors})
def order_delete(request):
uid = request.GET.get('uid')
exists = models.Order.objects.filter(id=uid).exists()
if not exists:
return JsonResponse({"status": False, "errors": "数据不存在"})
models.Order.objects.filter(id=uid).delete()
return JsonResponse({"status": True})
def order_detail(request):
uid = request.GET.get('uid')
# 方式1,直接获取对象,用obj.id/.price获取内容
# row_object = models.Order.objects.filter(id=uid).first()
# 方式2,.valus_list,内部是[(1,"xx"),(2,"xx")]
# row_object = models.Order.objects.filter(id=uid).values_list("title","price","status").first()
# 方式3,.values()得到字典,内部是[{'id':1, 'price':"xx"},{'id':2, 'price':"yy"}]
row_object = models.Order.objects.filter(id=uid).values("title","price","status").first()
if not row_object:
return JsonResponse({"status": False, "errors": "数据不存在"})
result = {
"status": True,
"data": row_object
# "data": {
# "title": row_dict.title,
# "price": row_dict.price,
# "status": row_dict.status,
# }
}
return JsonResponse(result)
@csrf_exempt
def order_edit(request):
uid= request.GET.get('uid')
row_object = models.Order.objects.filter(id=uid).first()
if not row_object:
return JsonResponse({"status": False, "tips": "数据不存在"})
form = OrderModelForm(data=request.POST,instance=row_object)
if form.is_valid():
form.save()
return JsonResponse({"status": True})
return JsonResponse({"status":False, "errors": form.errors})
templates/order_list.html
{% extends 'layout.html' %}
{% block content %}
<div class="container">
<div style="margin-bottom: 10px;">
<input type="button" id="btnadd" value="新建订单" class="btn btn-success" data-toggle="collapse">
</div>
<div class="bs-example" data-example-id="table-within-panel">
<div class="panel panel-default">
<!-- Default panel contents -->
<div class="panel-heading">
<span class="glyphicon glyphicon-th-list" aria-hidden="true"></span>
订单列表
</div>
<!-- Table -->
<table class="table table-bordered">
<thead>
<tr>
<th>ID</th>
<th>订单号</th>
<th>名称</th>
<th>价格</th>
<th>状态</th>
<th>管理员</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for obj in queryset %}
<tr>
<th>{{obj.id}}</th>
<td>{{obj.oid}}</td>
<td>{{obj.title}}</td>
<td>{{obj.price}}</td>
<td>{{obj.status}}</td>
<td>{{obj.admin.username}}</td>
<td>
<input uid="{{obj.id}}" class="btn btn-primary btn-xs btn-edit" type="button" value="编辑" />
<input uid="{{obj.id}}" class="btn btn-danger btn-xs btn-delete" type="button" value="删除" />
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="clearfix">
<ul class="pagination">
{{page_string}}
</ul>
</div>
</div>
</div>
<!-- 新建订单对话框 -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">×</span></button>
<h4 class="modal-title" id="myModalLabel">新建</h4>
</div>
<div class="modal-body">
<div class="clearfix">
<form id="formAdd" novalidate>
{% for field in form %}
<div class="col-xs-6">
<div class="form-group" style="position: relative;margin-bottom: 20px;">
<label>{{field.label}}</label>
{{field}}
<span class="error-msg" style="color:red; position: absolute;"></span>
</div>
</div>
{% endfor %}
</form>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">取 消</button>
<button id="btn-save" type="button" class="btn btn-primary">保 存</button>
</div>
</div>
</div>
</div>
<!-- 删除订单对话框 -->
<!-- Modal -->
<div class="modal fade" id="deleteModal" tabindex="-1" role="dialog" aria-labelledby="deleteModalLabel">
<div class="modal-dialog" role="document">
<div class="alert alert-danger alert-dismissible fade in" role="alert">
<h4>是否删除</h4>
<p style="margin: 10px;">删除订单</p>
<p style="text-align: right" ;>
<button id="btnConfirmDelete" type="button" class="btn btn-danger">确 定</button>
<button type="button" class="btn btn-default" data-dismiss="modal">取 消</button>
</p>
</div>
</div>
</div>
{% endblock %}
{% 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;
// 清空对话框中的数据
$('#formAdd')[0].reset();
$('#myModalLabel').text('新建');
// 点击新建按钮,显示对话框
$('#myModal').modal('show');
});
}
function bindBtnSaveEvent() {
$('#btn-save').click(function () {
// 清除所有信息
$(".error-msg").empty();
if (EDIT_ID) {
// 编辑
doEdit();
} else {
// 添加
doAdd();
}
});
}
function doAdd() {
// 向后台发送请求
$.ajax({
url: "/order/add/",
type: "POST",
data: $('#formAdd').serialize(),
dataType: "JSON",
success: function (res) {
if (res.status) {
// alert("创建成功");
// 清空表单
$('#formAdd')[0].reset();
// 关闭对话框
$('#myModal').modal('hide');
location.reload();//页面刷新
} else {
$.each(res.errors, function (name, errorlist) {
$("#id_" + name).next().text(errorlist[0]);
})
}
}
})
}
function doEdit(){
// 向后台发送请求
$.ajax({
url: "/order/edit/"+"?uid="+EDIT_ID,
type: "POST",
data: $('#formAdd').serialize(),
dataType: "JSON",
success: function (res) {
if (res.status) {
$('#formAdd')[0].reset();// 清空表单
$('#myModal').modal('hide');// 关闭对话框
location.reload();//页面刷新
} else {
if(res.tips) {
alert(res.tips);
}
$.each(res.errors, function (name, errorlist) {
$("#id_" + name).next().text(errorlist[0]);
})
}
}
})
}
function bindBtnDeleteEvent() {
$('.btn-delete').click(function () {
// alert("点击了删除");
$('#deleteModal').modal('show');
// 获取当前行的ID并赋值给全局变量
DELETE_ID = $(this).attr("uid");
});
}
function bindBtnConfirmDeleteEvent() {
$("#btnConfirmDelete").click(function () {
$.ajax({
type: "GET",
url: "/order/delete/",
data: {
uid: DELETE_ID,
},
dataType: "JSON",
success: function (res) {
if (res.status) {
// alert("删除成功")
// 关闭对话框
$('#deleteModal').modal('hide');
DELETE_ID = 0;//要删除的id置空
location.reload();
} else {
alert(res.errors)
}
}
});
});
}
function bindBtnEditEvent() {
$(".btn-edit").click(function () {
// 清空对话框中的数据
$('#formAdd')[0].reset();
var uid = $(this).attr("uid");
EDIT_ID = uid;
//发送ajax到后端获取当前行的相关数据
$.ajax({
type: "GET",
url: "/order/detail/",
data: {
uid: uid
},
dataType: "JSON",
success: function (res) {
if (res.status) {
//将数据赋值到对话框中的标签
$.each(res.data, function (name, value) {
$('#id_' + name).val(value);
})
$('#myModalLabel').text('编辑');
// alert("点击编辑");
$('#myModal').modal('show');
} else {
alert("不存在")
}
}
});
});
}
</script>
{% endblock %}
图表
第三方工具
urls.py
#数据统计
path('chart/list/',chart.chart_list ),
path('chart/bar/',chart.chart_bar),
path('chart/pie/',chart.chart_pie),
path('chart/line/',chart.chart_line),
views/chart.py
from django import forms
from django.http import JsonResponse
from django.shortcuts import render, HttpResponse
from django.views.decorators.csrf import csrf_exempt
from app01.utils.bootstrap import BootstrapModelForm
from app01 import models
from app01.utils.pagination import Pagination
import json
def chart_list(request):
return render(request, 'chart_list.html')
def chart_bar(request):
# 柱状图数据
# 数据可以从数据库中获取
legend = ['a', 'b']
x_axis = ['1月', '2月', '3月', '4月', '5月', '6月']
series_list = [
{
"name": 'a',
"type": 'bar',
"data": [5, 20, 36, 10, 10, 20]
},
{
"name": 'b',
"type": 'bar',
"data": [45, 50, 46, 30, 40, 10]
}
]
result = {
"status": True,
"data": {
"legend": legend,
"series_list": series_list,
"x_axis": x_axis,
}
}
return JsonResponse(result)
def chart_pie(request):
db_data_list = [
{"value": 1048, "name": 'IT部门'},
{"value": 1735, "name": '运营'},
{"value": 2580, "name": '新媒体'},
]
result = {
"status": True,
"data": db_data_list
}
return JsonResponse(result)
def chart_line(request):
db_data_list = [820, 932, 901, 934, 1290, 1330, 1320]
result = {
"status": True,
"data": db_data_list
}
return JsonResponse(result)
templates/chart_list.html
{% extends 'layout.html' %}
{% load static%}
{% block content %}
<div class="container">
<div class="panel panel-default">
<div class="panel-heading">折线图</div>
<div class="panel-body">
<div id="m1" style="width: 100%;height:400px;"></div>
</div>
</div>
<div class="row">
<div class="col-sm-7">
<div class="panel panel-default">
<div class="panel-heading">柱状图</div>
<div class="panel-body">
<div id="m2" style="width: 100%;height:400px;"></div>
</div>
</div>
</div>
<div class="col-sm-5">
<div class="panel panel-default">
<div class="panel-heading">饼图</div>
<div class="panel-body">
<div id="m3" style="width: 100%;height:400px;"></div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{%block js%}
<script src="{%static 'js/echarts.js' %}"></script>
<script type="text/javascript">
$(function () {
initBar();
initPie();
initLine();
});
// 初始化柱状图
function initBar() {
// 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('m2'));
// 指定图表的配置项和数据
var option = {
title: {
text: '业绩',
subtext: '吸吸吸',
textAlign: 'auto',
left: 'center',
},
tooltip: {},
legend: {
data: [],
bottom: 0
},
xAxis: {
data: []
},
yAxis: {},
series: []
};
$.ajax({
url: "/chart/bar/",
type: 'get',
dataType: 'json',
success: function (res) {
if (res.status) {
option.legend.data = res.data.legend;
option.xAxis.data = res.data.x_axis;
option.series = res.data.series_list;
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);
}
}
})
}
function initPie() {
// 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('m3'));
var option = {
title: {
text: '部门预算占比',
subtext: '广西分公司',
left: 'center'
},
tooltip: {
trigger: 'item'
},
legend: {
orient: 'vertical',
left: 'left',
bottom: 0,
},
series: [
{
name: '预算',
type: 'pie',
radius: '50%',
data: [],
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}
]
};
$.ajax({
url: "/chart/pie",
type: 'get',
dataType: 'json',
success: function (res) {
if (res.status) {
option.series[0].data = res.data;
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);
}
}
})
}
function initLine() {
// 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('m1'));
option = {
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
type: 'value'
},
series: [
{
type: 'line',
smooth: true
}
]
};
$.ajax({
url: "/chart/line",
type: 'get',
dataType: 'json',
success: function (res) {
if (res.status) {
option.series[0].data = res.data;
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);
}
}
})
}
</script>
{%endblock%}
文件上传
urls.py
# 上传文件
path('upload/list/', upload.upload_list),
views/upload.py
from django.shortcuts import render, HttpResponse
def upload_list(request):
if request.method == 'GET':
return render(request, 'upload_list.html')
file_obj = request.FILES.get("avatar")
print(file_obj.name) # 文件名
f = open(file_obj.name,mode='wb')
for chunk in file_obj.chunks():
f.write(chunk)
f.close()
return HttpResponse()
templates/upload_list.html
{% extends 'layout.html' %}
{% block content %}
<div class="container">
<!-- enctype="multipart/form-data"接受文件 -->
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<input type="text" name="username">
<input type="file" name="avatar">
<input type="submit" value="提交">
</form>
</div>
{% endblock %}
案例:混合数据(Form)
提交页面时:用户输入数据+文件
urls.py
path('upload/form/', upload.upload_form),
views/upload.py
from django import forms
from django.http import JsonResponse
from django.shortcuts import render, HttpResponse
from django.views.decorators.csrf import csrf_exempt
from app01.utils.bootstrap import BootstrapForm
from app01 import models
from app01.utils.pagination import Pagination
import json
import os
class UpForm(BootstrapForm):
bootstrap_exclude_fields=["img"]
name = forms.CharField(label="姓名")
age = forms.IntegerField(label="年龄")
img = forms.FileField(label="头像")
def upload_form(request):
title="Form上传"
if request.method =="GET":
form= UpForm()
return render(request, 'upload_form.html',{"form":form,"title":title})
form = UpForm(request.POST,files=request.FILES)
if form.is_valid():
# 读取图片内容,写入到文件夹中并获取文件的路径,将路径存到数据库
image_object = form.cleaned_data.get("img")
db_file_path = os.path.join("static","img",image_object.name)
file_path = os.path.join('app01','static','img',image_object.name)
f = open(file_path,mode='wb')
for trunk in image_object.chunks():
f.write(trunk)
f.close()
models.Boss.objects.create(
name=form.cleaned_data["name"],
age=form.cleaned_data["age"],
img=db_file_path
)
return HttpResponse("..")
return render(request, 'upload_form.html',{"form":form,"title":title})
templates/upload_form.html
from django import forms
from django.http import JsonResponse
from django.shortcuts import render, HttpResponse
from django.views.decorators.csrf import csrf_exempt
from app01.utils.bootstrap import BootstrapForm
from app01 import models
from app01.utils.pagination import Pagination
import json
import os
def upload_list(request):
if request.method == 'GET':
return render(request, 'upload_list.html')
file_obj = request.FILES.get("avatar")
print(file_obj.name) # 文件名
f = open(file_obj.name,mode='wb')
for chunk in file_obj.chunks():
f.write(chunk)
f.close()
return HttpResponse()
class UpForm(BootstrapForm):
bootstrap_exclude_fields=["img"]
name = forms.CharField(label="姓名")
age = forms.IntegerField(label="年龄")
img = forms.FileField(label="头像")
def upload_form(request):
title="Form上传"
if request.method =="GET":
form= UpForm()
return render(request, 'upload_form.html',{"form":form,"title":title})
form = UpForm(request.POST,files=request.FILES)
if form.is_valid():
# 读取图片内容,写入到文件夹中并获取文件的路径,将路径存到数据库
image_object = form.cleaned_data.get("img")
db_file_path = os.path.join("static","img",image_object.name)
file_path = os.path.join('app01','static','img',image_object.name)
f = open(file_path,mode='wb')
for trunk in image_object.chunks():
f.write(trunk)
f.close()
models.Boss.objects.create(
name=form.cleaned_data["name"],
age=form.cleaned_data["age"],
img=db_file_path
)
return HttpResponse("..")
return render(request, 'upload_form.html',{"form":form,"title":title})
启用media
urls.py
from django.urls import path,re_path
from django.conf import settings
from django.views.static import serve
re_path(r'^media/(?P<path>.*)$',serve,{'document_root':settings.MEDIA_ROOT},name='media'),
settings.py
import os
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
混合数据ModalForm
model.py
class City(models.Model):
name = models.CharField(verbose_name="姓名", max_length=32)
count = models.IntegerField(verbose_name="人口")
# 本质上数据库也是CharField,文件保存能自动保存
logo = models.FileField(verbose_name="Logo", max_length=128,upload_to='city/')
views/upload.py
class UpModelForm(BootstrapModelForm):
bootstrap_exclude_fields = ['logo']
class Meta:
model = models.City
fields = "__all__"
def upload_modal_form(request):
if request.method == "GET":
form = UpModelForm()
return render(request, 'upload_form.html',{'form':form,"title":"modelForm上传"})
form = UpModelForm(data=request.POST,files=request.FILES)
if form.is_valid():
form.save()
return redirect("/city/list/")
return render(request, 'upload_form.html',{'form':form,"title":"modelForm上传"})
templates/upload_form.html
{% extends 'layout.html' %}
{% block content %}
<div class="container">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{{title}}</h3>
</div>
<div class="panel-body">
<form method="post" enctype="multipart/form-data" novalidate>
{% csrf_token %}
{% for field in form %}
<div class="form-group">
<label>{{field.label}}</label>
{{field}}
<span style="color:red;">{{field.errors.0}}</span>
</div>
{% endfor %}
<button type="submit" class="btn btn-primary">提交</button>
</form>
</div>
</div>
</div>
{% endblock %}
展示列表
templates/city_list.html
{% extends 'layout.html' %}
{% block content %}
<div class="container">
<div style="margin-bottom: 10px;">
<a class="btn btn-success" href="#">
<span class="glyphicon glyphicon-plus-sign" aria-hidden="true"></span>
城市列表
</a>
</div>
<div class="bs-example" data-example-id="table-within-panel">
<div class="panel panel-default">
<!-- Default panel contents -->
<div class="panel-heading">
<span class="glyphicon glyphicon-th-list" aria-hidden="true"></span>
部门列表
</div>
<!-- Table -->
<table class="table table-bordered">
<thead>
<tr>
<th>ID</th>
<th>Logo</th>
<th>名称</th>
<th>人口</th>
</tr>
</thead>
<tbody>
{% for obj in queryset %}
<tr>
<th>{{obj.id}}</th>
<td>
<img src="/media/{{obj.logo}}" style="height: 80px;">
</td>
<td>{{obj.name}}</td>
<td>{{obj.count}}</td>
<td>
<a class="btn btn-primary btn-xs" href="/depart/{{obj.id}}/edit/">编辑 </a>
<a class="btn btn-danger btn-xs" href="/depart/delete/?nid={{obj.id}}/">删除 </a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% endblock %}
views/city.py
from django.shortcuts import render
from app01 import models
def city_list(request):
queryset = models.City.objects.all()
return render(request, 'city_list.html', {'queryset': queryset})
|