# day16 Django 开发
主题:员工管理系统
# 1. 新建项目
# 2. 创建 app
python manage.py startapp app01 |
注册 app:
# 3. 设计表结构(django)
from django.db import models | |
class Department(models.Model): | |
""" 部门表 """ | |
title = models.CharField(verbose_name='标题', max_length=32) | |
class UserInfo(models.Model): | |
""" 员工表 """ | |
name = models.CharField(verbose_name="姓名", max_length=16) | |
password = models.CharField(verbose_name="密码", max_length=64) | |
age = models.IntegerField(verbose_name="年龄") | |
account = models.DecimalField(verbose_name="账户余额", max_digits=10, decimal_places=2, default=0) | |
create_time = models.DateTimeField(verbose_name="入职时间") | |
# 无约束 | |
# depart_id = models.BigIntegerField (verbose_name="部门 ID") | |
# 1. 有约束 | |
# - to,与那张表关联 | |
# - to_field,表中的那一列关联 | |
# 2.django 自动 | |
# - 写的 depart | |
# - 生成数据列 depart_id | |
# 3. 部门表被删除 | |
# ### 3.1 级联删除 | |
depart = models.ForeignKey(to="Department", to_field="id", on_delete=models.CASCADE) | |
# ### 3.2 置空 | |
# 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) |
# 4. 在 MySQL 中生成表
工具连接 MySQL 生成数据库。
n create database gx_day16 DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
修改配置文件,连接 MySQL
n DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'gx_day16', # 数据库名字
'USER': 'root',
'PASSWORD': 'root123',
'HOST': '127.0.0.1', # 那台机器安装了 MySQL
'PORT': 3306,
}
}
django 命令生成数据库表
h python manage.py makemigrations
python manage.py migrate
表结构创建成功:
# 5. 静态文件管理
static
目录
# 6. 部门管理
体验,最原始方法来做。
Django 中提供 Form 和 ModelForm 组件(方便)
# 7. 模板的继承
- 部门列表
- 添加部门
- 编辑部门
定义目版: layout.html
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<title>Title</title> | |
<link rel="stylesheet" href="{\% static 'plugin...min.css' %}"> | |
{\% block css %}{\% endblock %} | |
</head> | |
<body> | |
<h1>标题</h1> | |
<div> | |
{\% block content %}{\% endblock %} | |
</div> | |
<h1>底部</h1> | |
<script src="{\% static 'js/jquery-3.6.0.min.js' %}"></script> | |
{\% block js %}{\% endblock %} | |
</body> | |
</html> |
继承母版:
{\% extends 'layout.html' %} | |
{\% block css %} | |
<link rel="stylesheet" href="{\% static 'pluxxx.css' %}"> | |
<style> | |
... | |
</style> | |
{\% endblock %} | |
{\% block content %} | |
<h1>首页</h1> | |
{\% endblock %} | |
{\% block js %} | |
<script src="{\% static 'js/jqxxxin.js' %}"></script> | |
{\% endblock %} |
# 8. 用户管理
insert into app01_userinfo(name,password,age,account,create_time,gender,depart_id) values("韩超","666",23,100.68,"2020-01-11",2,1); | |
insert into app01_userinfo(name,password,age,account,create_time,gender,depart_id) values("刘东","123",23,100.68,"2010-11-11",1,4); | |
insert into app01_userinfo(name,password,age,account,create_time,gender,depart_id) values("朱虎飞","999",33,9900.68,"2021-05-11",1,1); |
+-------------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+---------------+------+-----+---------+----------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| name | varchar(16) | NO | | NULL | |
| password | varchar(64) | NO | | NULL | |
| age | int(11) | NO | | NULL | |
| account | decimal(10,2) | NO | | NULL | |
| create_time | datetime(6) | NO | | NULL | |
| gender | smallint(6) | NO | | NULL | |
| depart_id | bigint(20) | NO | MUL | NULL | |
+-------------+---------------+------+-----+---------+----------------+
新建用户:
原始方式理思路:不会采用(本质)【麻烦】
- 用户提交数据没有校验。 - 错误,页面上应该有错误提示。 - 页面上,没一个字段都需要我们重新写一遍。 [OK] - 关联的数据,手动去获取并展示循环展示在页面。 [OK]
Django 组件
- Form 组件(小简便)
- ModelForm 组件(最简便)
# 8.1 初识 Form
# 1. views.py
class MyForm(Form): | |
user = forms.CharField(widget=forms.Input) | |
pwd = form.CharFiled(widget=forms.Input) | |
email = form.CharFiled(widget=forms.Input) | |
account = form.CharFiled(widget=forms.Input) | |
create_time = form.CharFiled(widget=forms.Input) | |
depart = form.CharFiled(widget=forms.Input) | |
gender = form.CharFiled(widget=forms.Input) | |
def user_add(request): | |
if request.method == "GET": | |
form = MyForm() | |
return render(request, 'user_add.html',{"form":form}) |
# 2.user_add.html
<form method="post"> | |
{\% for field in form%} | |
{\% endfor %} | |
<!-- <input type="text" placeholder="姓名" name="user" /> --> | |
</form> |
<form method="post"> | |
<!-- <input type="text" placeholder="姓名" name="user" /> --> | |
</form> |
# 8.3 ModelForm(推荐)
# 0. models.py
class UserInfo(models.Model): | |
""" 员工表 """ | |
name = models.CharField(verbose_name="姓名", max_length=16) | |
password = models.CharField(verbose_name="密码", max_length=64) | |
age = models.IntegerField(verbose_name="年龄") | |
account = models.DecimalField(verbose_name="账户余额", max_digits=10, decimal_places=2, default=0) | |
create_time = models.DateTimeField(verbose_name="入职时间") | |
depart = models.ForeignKey(to="Department", to_field="id", on_delete=models.CASCADE) | |
gender_choices = ( | |
(1, "男"), | |
(2, "女"), | |
) | |
gender = models.SmallIntegerField(verbose_name="性别", choices=gender_choices) |
# 1. views.py
class MyForm(ModelForm): | |
xx = form.CharField*("...") | |
class Meta: | |
model = UserInfo | |
fields = ["name","password","age","xx"] | |
def user_add(request): | |
if request.method == "GET": | |
form = MyForm() | |
return render(request, 'user_add.html',{"form":form}) |
# 2.user_add.html
<form method="post"> | |
{\% for field in form%} | |
{\% endfor %} | |
<!-- <input type="text" placeholder="姓名" name="user" /> --> | |
</form> |
<form method="post"> | |
<!-- <input type="text" placeholder="姓名" name="user" /> --> | |
</form> |
# day17 Django 开发
部门管理
用户管理
用户列表
新建用户
- ModelForm,针对数据库中的某个表。 - Form。
# 8.4 编辑用户
点击编辑,跳转到编辑页面(将编辑行的 ID 携带过去)。
编辑页面(默认数据,根据 ID 获取并设置到页面中)
提交:
错误提示
数据校验
在数据库更新
models.UserInfo.filter(id=4).update(...)
# 8.5 删除
见代码。
# 9. 靓号管理
# 9.1 表结构
根据表结构的需求,在 models.py 中创建类(由类生成数据库中的表)。
class PrettyNum(models.Model): | |
""" 靓号表 """ | |
mobile = models.CharField(verbose_name="手机号", max_length=11) | |
# 想要允许为空 null=True, blank=True | |
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) |
自己在数据模拟创建一些数据:
insert into app01_prettynum(mobile,price,level,status)values("111111111",19,1,1); |
mysql> select * from app01_prettynum;
+----+-----------+-------+-------+--------+
| id | mobile | price | level | status |
+----+-----------+-------+-------+--------+
| 1 | 111111111 | 19 | 1 | 1 |
| 2 | 111111111 | 19 | 1 | 1 |
| 3 | 111111111 | 19 | 1 | 1 |
| 4 | 111111111 | 19 | 1 | 1 |
+----+-----------+-------+-------+--------+
4 rows in set (0.01 sec)
# 9.2 靓号列表
URL
函数
获取所有的靓号
结合 html+render 将靓号罗列出来
id 号码 价格 级别(中文) 状态(中文)
# 9.3 新建靓号
列表点击跳转:
/pretty/add/
URL
ModelForm 类
from django import forms class PrettyModelForm(forms.ModelForm): ...
函数
- 实例化类的对象
- 通过 render 将对象传入到 HTML 中。
- 模板的循环展示所有的字段。
点击提交
- 数据校验
- 保存到数据库
- 跳转回靓号列表
# 9.4 编辑靓号
- 列表页面:
/pretty/数字/edit/
- URL
- 函数
- 根据 ID 获取当前编辑的对象
- ModelForm 配合,默认显示数据。
- 提交修改。
不允许手机号重复。
添加:【正则表达式】【手机号不能存在】
# [obj,obj,obj]
queryset = models.PrettyNum.objects.filter(mobile="1888888888")
obj = models.PrettyNum.objects.filter(mobile="1888888888").first()
# True/False
exists = models.PrettyNum.objects.filter(mobile="1888888888").exists()
编辑:【正则表达式】【手机号不能存在】
排除自己以外,其他的数据是否手机号是否重复?
# id!=2 and mobile='1888888888'
models.PrettyNum.objects.filter(mobile="1888888888").exclude(id=2)
# 9.5 搜索手机号
models.PrettyNum.objects.filter(mobile="19999999991",id=12) | |
data_dict = {"mobile":"19999999991","id":123} | |
models.PrettyNum.objects.filter(**data_dict) |
models.PrettyNum.objects.filter(id=12) # 等于 12 | |
models.PrettyNum.objects.filter(id__gt=12) # 大于 12 | |
models.PrettyNum.objects.filter(id__gte=12) # 大于等于 12 | |
models.PrettyNum.objects.filter(id__lt=12) # 小于 12 | |
models.PrettyNum.objects.filter(id__lte=12) # 小于等于 12 | |
data_dict = {"id__lte":12} | |
models.PrettyNum.objects.filter(**data_dict) |
models.PrettyNum.objects.filter(mobile="999") # 等于 | |
models.PrettyNum.objects.filter(mobile__startswith="1999") # 筛选出以 1999 开头 | |
models.PrettyNum.objects.filter(mobile__endswith="999") # 筛选出以 999 结尾 | |
models.PrettyNum.objects.filter(mobile__contains="999") # 筛选出包含 999 | |
data_dict = {"mobile__contains":"999"} | |
models.PrettyNum.objects.filter(**data_dict) |
# 9.6 分页
queryset = models.PrettyNum.objects.all() | |
queryset = models.PrettyNum.objects.filter(id=1)[0:10] | |
# 第 1 页 | |
queryset = models.PrettyNum.objects.all()[0:10] | |
# 第 2 页 | |
queryset = models.PrettyNum.objects.all()[10:20] | |
# 第 3 页 | |
queryset = models.PrettyNum.objects.all()[20:30] |
data = models.PrettyNum.objects.all().count() | |
data = models.PrettyNum.objects.filter(id=1).count() |
分页的逻辑和处理规则
封装分页类
- 从头到尾开发
- 写项目用【pagination.py】公共组件。
小 Bug,搜索 + 分页情况下。
分页时候,保留原来的搜索条件 http://127.0.0.1:8000/pretty/list/?q=888 http://127.0.0.1:8000/pretty/list/?page=1 http://127.0.0.1:8000/pretty/list/?q=888&page=23
# 10. 时间插件
<link rel="stylesheet" href="static/plugins/bootstrap-3.4.1/css/bootstrap.css">
<link rel="stylesheet" href="static/plugins/bootstrap-datepicker/css/bootstrap-datepicker.css">
<input type="text" id="dt" class="form-control" placeholder="入职日期">
<script src="static/js/jquery-3.6.0.min.js"></script>
<script src="static/plugins/bootstrap-3.4.1/js/bootstrap.js"></script>
<script src="static/plugins/bootstrap-datepicker/js/bootstrap-datepicker.js"></script>
<script src="static/plugins/bootstrap-datepicker/locales/bootstrap-datepicker.zh-CN.min.js"></script>
<script>
$(function () {
$('#dt').datepicker({
format: 'yyyy-mm-dd',
startDate: '0',
language: "zh-CN",
autoclose: true
});
})
</script>
# 11.ModelForm 和 BootStrap
ModelForm 可以帮助我们生成 HTML 标签。
class UserModelForm(forms.ModelForm):
class Meta:
model = models.UserInfo
fields = ["name", "password",]
form = UserModelForm()
普通的input框
普通的input框
定义插件
class UserModelForm(forms.ModelForm):
class Meta:
model = models.UserInfo
fields = ["name", "password",]
widgets = {
"name": forms.TextInput(attrs={"class": "form-control"}),
"password": forms.PasswordInput(attrs={"class": "form-control"}),
"age": forms.TextInput(attrs={"class": "form-control"}),
}
class UserModelForm(forms.ModelForm):
name = forms.CharField(
min_length=3,
label="用户名",
widget=forms.TextInput(attrs={"class": "form-control"})
)
class Meta:
model = models.UserInfo
fields = ["name", "password", "age"]
BootStrap的input框
BootStrap的input框
重新定义的 init 方法,批量设置
class UserModelForm(forms.ModelForm):
class Meta:
model = models.UserInfo
fields = ["name", "password", "age",]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# 循环 ModelForm 中的所有字段,给每个字段的插件设置
for name, field in self.fields.items():
field.widget.attrs = {
"class": "form-control",
"placeholder": field.label
}
class UserModelForm(forms.ModelForm):
class Meta:
model = models.UserInfo
fields = ["name", "password", "age",]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# 循环 ModelForm 中的所有字段,给每个字段的插件设置
for name, field in self.fields.items():
# 字段中有属性,保留原来的属性,没有属性,才增加。
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 UserEditModelForm(forms.ModelForm):
class Meta:
model = models.UserInfo
fields = ["name", "password", "age",]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# 循环 ModelForm 中的所有字段,给每个字段的插件设置
for name, field in self.fields.items():
# 字段中有属性,保留原来的属性,没有属性,才增加。
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(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# 循环 ModelForm 中的所有字段,给每个字段的插件设置
for name, field in self.fields.items():
# 字段中有属性,保留原来的属性,没有属性,才增加。
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 UserEditModelForm(BootStrapModelForm):
class Meta:
model = models.UserInfo
fields = ["name", "password", "age",]
# 操作
提取公共的类
ModelForm 拆分出来
视图函数的归类
# day18 Django 开发
# 12. 管理员操作
# 13. 用户登录
http 无状态短连接(在一次请求响应后断开连接,当重新发起请求的时候认为是新人):
什么是 cookie 和 session?
cookie 理解为一个字典
http://127.0.0.1:8000/admin/list/
https://127.0.0.1:8000/admin/list/
# 13.1 登录
登录成功后:
- cookie,随机字符串
- session,用户信息
在其他需要登录才能访问的页面中,都需要加入:
def index(request): | |
info = request.session.get("info") | |
if not info: | |
return redirect('/login/') | |
... |
目标:在 18 个视图函数前面统一加入判断。
info = request.session.get("info") | |
if not info: | |
return redirect('/login/') |
# 13.2 中间件的体验
定义中间件
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse
class M1(MiddlewareMixin):
""" 中间件1 """
def process_request(self, request):
# 如果方法中没有返回值(返回 None),继续向后走
# 如果有返回值 HttpResponse、render 、redirect
print("M1.process_request")
return HttpResponse("无权访问")
def process_response(self, request, response):
print("M1.process_response")
return response
class M2(MiddlewareMixin):
""" 中间件2 """
def process_request(self, request):
print("M2.process_request")
def process_response(self, request, response):
print("M2.process_response")
return response
应用中间件 setings.py
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'app01.middleware.auth.M1',
'app01.middleware.auth.M2',
]
在中间件的 process_request 方法
# 如果方法中没有返回值(返回 None),继续向后走
# 如果有返回值 HttpResponse、render 、redirect,则不再继续向后执行。
# 13.3 中间件实现登录校验
编写中间件
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse, redirect
class AuthMiddleware(MiddlewareMixin):
def process_request(self, request):
# 0. 排除那些不需要登录就能访问的页面
# request.path_info 获取当前用户请求的 URL /login/
if request.path_info == "/login/":
return
# 1. 读取当前访问的用户的 session 信息,如果能读到,说明已登陆过,就可以继续向后走。
info_dict = request.session.get("info")
print(info_dict)
if info_dict:
return
# 2. 没有登录过,重新回到登录页面
return redirect('/login/')
应用中间件
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'app01.middleware.auth.AuthMiddleware',
]
# 13.4 注销
def logout(request): | |
""" 注销 """ | |
request.session.clear() | |
return redirect('/login/') |
# 13.5 当前用户
# 14. 图片验证码
<img src="./images/ 员工管理系统 - django/image-20211127152344329.png" alt="image-20211127152344329" style="zoom: 50%;" />
# 14.1 生成图片
pip install pillow
import random | |
from PIL import Image, ImageDraw, ImageFont, ImageFilter | |
def check_code(width=120, height=30, char_length=5, font_file='Monaco.ttf', font_size=28): | |
code = [] | |
img = Image.new(mode='RGB', size=(width, height), color=(255, 255, 255)) | |
draw = ImageDraw.Draw(img, mode='RGB') | |
def rndChar(): | |
""" | |
生成随机字母 | |
:return: | |
""" | |
return chr(random.randint(65, 90)) | |
def rndColor(): | |
""" | |
生成随机颜色 | |
:return: | |
""" | |
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): | |
draw.point([random.randint(0, width), random.randint(0, height)], 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, y1, x2, y2), fill=rndColor()) | |
img = img.filter(ImageFilter.EDGE_ENHANCE_MORE) | |
return img, ''.join(code) | |
if __name__ == '__main__': | |
img, code_str = check_code() | |
print(code_str) | |
with open('code.png', 'wb') as f: | |
img.save(f, format='png') |
# 15. Ajax 请求
浏览器向网站发送请求时:URL 和 表单的形式提交。
- GET
- POST
特点:页面刷新。
除此之外,也可以基于 Ajax 向后台发送请求(偷偷的发送请求)。
依赖 jQuery
编写 ajax 代码
$.ajax({
url:"发送的地址",
type:"get",
data:{
n1:123,
n2:456
},
success:function(res){
console.log(res);
}
})
# 15.1 GET 请求
$.ajax({ | |
url: '/task/ajax/', | |
type: "get", | |
data: { | |
n1: 123, | |
n2: 456 | |
}, | |
success: function (res) { | |
console.log(res); | |
} | |
}) |
from django.shortcuts import render, HttpResponse | |
def task_ajax(request): | |
print(request.GET) | |
return HttpResponse("成功了") |
# 15.2 POST 请求
$.ajax({ | |
url: '/task/ajax/', | |
type: "get", | |
data: { | |
n1: 123, | |
n2: 456 | |
}, | |
success: function (res) { | |
console.log(res); | |
} | |
}) |
from django.shortcuts import render, HttpResponse | |
from django.views.decorators.csrf import csrf_exempt | |
@csrf_exempt | |
def task_ajax(request): | |
print(request.GET) | |
print(request.POST) | |
return HttpResponse("成功了") |
# 15.3 关闭绑定事件
{\% extends 'layout.html' %} | |
{\% block content %} | |
<div class="container"> | |
<h1>任务管理</h1> | |
<h3>示例1</h3> | |
<input id="btn1" type="button" class="btn btn-primary" value="点击"/> | |
</div> | |
{\% endblock %} | |
{\% block js %} | |
<script type="text/javascript"> | |
$(function () { | |
// 页面框架加载完成之后代码自动执行 | |
bindBtn1Event(); | |
}) | |
function bindBtn1Event() { | |
$("#btn1").click(function () { | |
$.ajax({ | |
url: '/task/ajax/', | |
type: "post", | |
data: { | |
n1: 123, | |
n2: 456 | |
}, | |
success: function (res) { | |
console.log(res); | |
} | |
}) | |
}) | |
} | |
</script> | |
{\% endblock %} |
# 15.4 ajax 请求的返回值
一般都会返回 JSON 格式。
{\% extends 'layout.html' %} | |
{\% block content %} | |
<div class="container"> | |
<h1>任务管理</h1> | |
<h3>示例1</h3> | |
<input id="btn1" type="button" class="btn btn-primary" value="点击"/> | |
</div> | |
{\% endblock %} | |
{\% block js %} | |
<script type="text/javascript"> | |
$(function () { | |
// 页面框架加载完成之后代码自动执行 | |
bindBtn1Event(); | |
}) | |
function bindBtn1Event() { | |
$("#btn1").click(function () { | |
$.ajax({ | |
url: '/task/ajax/', | |
type: "post", | |
data: { | |
n1: 123, | |
n2: 456 | |
}, | |
dataType: "JSON", | |
success: function (res) { | |
console.log(res); | |
console.log(res.status); | |
console.log(res.data); | |
} | |
}) | |
}) | |
} | |
</script> | |
{\% endblock %} |
import json | |
from django.shortcuts import render, HttpResponse | |
from django.http import JsonResponse | |
from django.views.decorators.csrf import csrf_exempt | |
def task_list(request): | |
""" 任务列表 """ | |
return render(request, "task_list.html") | |
@csrf_exempt | |
def task_ajax(request): | |
print(request.GET) | |
print(request.POST) | |
data_dict = {"status": True, 'data': [11, 22, 33, 44]} | |
return HttpResponse(json.dumps(data_dict)) |