之前项目使用flask框架进行二次开发,发现代码写的很烂,然后这时学到了django,想用django重写代码
一 Django去除模板url硬编码
一个项目中通常包含多个app,视图函数可能会重名,我们需要使用含有命名空间的urls
app/urls.py
app_name = 'app'
urlpatterns = [
path('', views.index, name='index')
]
模板中:index.html
<li><a href="{% url 'app:index' %}" style="font-size:15px">备件管理</a></li>
二 模板继承问题
模板继承时,最好将script放在最前面,否则写JavaScript有的时候不注意位置会报错
三 Django分页
使用Django 第三方拓展:django-pure-pagination + bootstrap
3.1 视图函数使用方法
- 安装
pip install django-pure-pagination
它注册到 INSTALLED_APPS 里
INSTALLED_APPS = [ 'pure_pagination', # 分页 # ...其他 ]
在settings.py中进行分页配置
PAGINATION_SETTINGS = { 'PAGE_RANGE_DISPLAYED': 5, 'MARGIN_PAGES_DISPLAYED': 2, 'SHOW_FIRST_PAGE_WHEN_INVALID': True, }
- views.py ```python from pure_pagination import Paginator,PageNotAnInteger
def index(request): inventories = Inventory.get_all()
# 对所有的inventories进行分页
try:
page = request.GET.get('page', 1)
except PageNotAnInteger:
page = 1
# 第二个参数代表每一页显示的个数
p = Paginator(inventories, 15,request=request)
page_obj = p.page(page)
return render(request, 'inventory/index.html', context={'page_obj': page_obj})
(1)`inventories = Inventory.get_all()`中get_all()方法是对数据查询的优化,在模型类中已经定义了:
```python
class Inventory(models.Model):
"""其他代码"""
@classmethod
def get_all(cls):
return cls.objects.all()
也可以不在模型类中定义,直接在view中使用未优化前的方法:inventories = Inventory.objects.all()
(2)首先在get方法中,首先获取到所有inventories 的实例,然后是一个异常处理,如果没有给page赋值,默认为1,即首页;异常处理类似。
(3) 然后,调用Paginator接口获得一个实例:p = Paginator(inventories, 15,request=request)
,Paginator接口构造函数如下:
def __init__(self, object_list, per_page, orphans=0,
allow_empty_first_page=True):
self.object_list = object_list
self._check_object_list_is_ordered()
self.per_page = int(per_page)
self.orphans = int(orphans)
self.allow_empty_first_page = allow_empty_first_page
这里一般传递三个参数,分别是:所有inventories 的实例,每一页显示inventories 的数量,request
(4)当我们拿到这个分页控制器实例后,调用page方法,加上page参数(由前端URL传递下来的)即可得到分页实例page_obj , http://127.0.0.1:8000/inventory/?page=8 ,(此处的page=8传递给get方法里的page),即
page_obj = p.page(page)
(5)将返回的分实例返回给前端模板
return render(request, 'inventory/index.html', context={'page_obj': page_obj})
- urls.py ```python from inventory import views
app_name = ‘inventory’
urlpatterns = [ path(‘’, views.index, name=’index’) ]
---
6. 前端页面**index.html**显示的逻辑大致如下:
1)先判断有没有前一页,如果有,则显示“前一页”这个按钮链接,否则不显示;<br />2)一个for循环判断当前页,如果是当前页我们就改变他的显示样式(比如给按钮挂个灰色什么,这里是class="active"),否则就是普通样式;<br />3)最后判断有没有下一页,如果有,则显示“下一页”这个按钮链接,否则不显示<br />下面是前端模板一个例子,是需要替换**<li>**部分,根据结构填充即可
```html
<nav aria-label="Page navigation">
<ul class="pagination pull-right">
<!-- 上一页 -->
{% if page_obj.has_previous %}
<li class="long"><a href="?{{ page_obj.previous_page_number.querystring }}" aria-label="Previous"><span
aria-hidden="true">«</span></a></li>
{% endif %}
<!-- 遍历页数 -->
{% for page in page_obj.pages %}
{% if page %}
{% ifequal page page_obj.number %}
<li class="active"><a href="?{{ page.querystring }}">{{ page }}</a></li>
{% else %}
<li><a href="?{{ page.querystring }}">{{ page }}</a></li>
{% endifequal %}
{% else %}
<li class="none"><a href="">...</a></li>
{% endif %}
{% endfor %}
<!--有下一页-->
{% if page_obj.has_next %}
<li class="long"><a href="?{{ page_obj.next_page_number.querystring }}" aria-label="Next"><span
aria-hidden="true">»</span></a></li>
{% endif %}
</ul>
</nav>
(1) 用到了bootstrap分页样式:https://v3.bootcss.com/components/#pagination
(2) Page常用属性和方法:
has_next:是否还有下一页。
has_previous:是否还有上一页。
next_page_number:下一页的页码。
previous_page_number:上一页的页码。
number:当前页。
3.2 类视图(官方推荐姿势)使用方法
views.py
from pure_pagination.mixins import PaginationMixin
from django.views.generic import ListView
class IndexView(PaginationMixin,ListView):
# 模型
model = Inventory
# 模板
template_name = 'inventory/index.html'
# 一个多少条数据
paginate_by = 15
当我们使用了类视图后,Django会自动的生成3个上下文对象:
- paginator: 这是一个Paginator的实例,就是普通视图里面的paginator对象
- page_obj: 这是一个Page的实例
- is_paginated: 这是一个布尔值,表示是否已经分页
如果不加PaginationMixin。前端页面的页数不显示
urls.py
from inventory import views
urlpatterns = [
path('', views.IndexView.as_view(), name='index')
]
四 分页之跳转页面
在第三章的基础上,增加跳转页面的功能
- index.html新增代码
上面使用了bootstrap<li style="font-size: 15px">跳至<input type="text" size="1" id="pageNum">页 <button type="button" class="btn btn-default btn-sm" id="skipPage"> <span class="glyphicon glyphicon-share-alt" aria-hidden="true"></span> </button> </li>
js代码 ```javascript
(1)使用jQuery为**id**是**skipPage**的**button**按钮绑定事件<br />(2)`page_obj.paginator.num_pages`是总页数<br />(3)_Location_._assign_() 方法会触发窗口加载并显示指定的URL的内容。<br />(4)`location.assign("{% url 'inventory:index' %}?page=" + pageNum)`:js方法来控制向后端发送GET请求,链接末尾加上pageNum,发送给后端,后端代码同第三章: ```python def index(request): inventories = Inventory.get_all() try: page = request.GET.get('page', 1) except PageNotAnInteger: page = 1 p = Paginator(inventories, 15,request=request) page_obj = p.page(page) return render(request, 'inventory/index.html', context={'page_obj': page_obj})
五 使用pure_pagination进行分页关键字查询
需求:在表单中输入查询关键字以及选择查询字段,将查询的数据返回,并可以进行分页
此部分需要结合第三、四、十一章,使用了bootstrap表单验证功能前端form表单
<!--查询一栏--> <form action="{% url 'inventory:index' %}" method="get"> <div class="row" style="margin-left: auto;margin-right: 20px"> <div class="panel panel-primary"> <div class="panel-heading"> <h3 class="panel-title">条件查询</h3> </div> <div class="panel-body"> <div style="display:inline-block;"> <div style="float:left;padding:6px;"> <span>关键字:</span> </div> <div style="float:left;"> <div class="form-group"> <input id="keyword" name="keyword" class="form-control" style="width:200px;" placeholder="请输入关键字"/> </div> </div> <div style="float:left;padding:6px;"> <span>查询字段:</span> </div> <div style="float:left;"> <div class="form-group"> <select id="queryField" name="queryField" class="form-control" style="width:200px;"> <option value="">请选择</option> <option value="m_name">物料名称</option> <option value="m_number">物料号</option> <option value="type">规格型号</option> <option value="person">责任人</option> <option value="parts_classlification">备件分类</option> </select> </div> </div> <div style="float:left;margin-left:20px;"> <div class="form-group"> <button type="submit" id="query" class="btn btn-primary">查询</button> </div> </div> </div> </div> </div> </div> </form>
使用bootstrap的表单验证功能,具体请看十一章(https://www.yuque.com/u1046159/lp12n4/pn8619#bXfaP)
form表单将含有name属性的元通过get方法传递给后台函数indexindex.py
def index(request): try: page = request.GET.get('page', 1) except PageNotAnInteger: page = 1 keyword = request.GET.get('keyword') query_field = request.GET.get(('queryField')) if keyword and query_field is not None: inventories = Inventory.get_all().filter(**{query_field + '__contains': keyword}) else: inventories = Inventory.get_all() p = Paginator(inventories, 15, request=request) page_obj = p.page(page) return render(request, 'inventory/index.html', context={'page_obj': page_obj})
分页代码和第三章分页代码相似,只是添加了处理逻辑:如果获取的前端查询参数不为空(说明用于点击了查询功能,那么这时候返回查询的结果,即对数据库数据进行过滤【如果用户点击查询,传递给后端的参数一定不为空,因为使用了bootstrap进行了表单验证,一定不为空才让点击】);如果后台获取到的查询参数为空,那么说明用户没有使用查询功能,返回数据库所有数据
查询代码
if keyword and query_field is not None: inventories = Inventory.get_all().filter(**{query_field + '__contains': keyword})
@classmethod def get_all(cls): return cls.objects.all()
- 不使用get_all()方法,可以使用: ```python inventories = Inventory.objects.all().filter(**{query_field + '__contains': keyword})
没有使用查询功能
else: inventories = Inventory.get_all()
六 使用JavaScript触发bootstrap的模态框
需求:为一个按钮绑定事件,点击后bootstrap弹窗提示
html页面<button id="skipPage>点击</button> <div class="modal" id="mymodal"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button> <h4 class="modal-title">提示</h4> </div> <div class="modal-body"> <p>请输入正确的页码!</p> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">确认</button> </div> </div> </div> </div>
<div class="modal-body">
里面可以放一些提示信息,如放警示框<div class="modal-body"> <div class="alert alert-danger" role="alert"><p>请输入正确的页码!</p></div> </div>
JavaScript
<script type="text/javascript"> $(function () { $("#skipPage").click(function () { $("#mymodal").modal() } }) }) </script>
七 jQuery获取点击元素的父元素id
html
<ul class="nav navbar-nav"> <li id="t1"><a href="">备件管理</a></li> <li id="t2"><a href="">库存汇总</a></li> <li id="t3"><a href="">入库管理</a></li> <li id="t4"><a href="">出库管理</a></li> </ul>
jquery
<script> $(function () { $(document).click(function (e) { var li_id = $(e.target).parent().attr('id') alert(li_id) }) }) </script>
八 Django 使用外部JS文件导致模板变量和{% url %}失效的问题
https://blog.csdn.net/qq_41475058/article/details/103435763
解决方法:能不用模板变量就尽量不用,例如有些只能从页面上获取就直接用jquery从页面上获取吧,如下第一张图。例如ajax里面的url这种,可以直接使用路径/restartdo/,如果真的想使用url变量的话(怕资源更改麻烦),可以在html中将url的值定义为一个变量,然后在JS文件中将ajax中的url设为这个变量。入下第二三张图。大概就这样吧,目前没发现更好的方法,JS能不用模板变量就尽量不用吧。九 Django模糊查询(字段名为变量)
参考:https://blog.csdn.net/w710537643/article/details/108520484
需求:前端使用ajax将查询参数传递给django后台,现在想要实现模糊查询,查询某个数据库字段等于查询参数,原SQL语句样例:
SELECT * FROM "inventory" where type LIKE '%16A%'
- type 是数据库字段名,16A 是关键字
Django模糊查询代码:
keyword = query_data['keyword'] queryField = query_data['queryField'] page_obj = Inventory.objects.filter(**{queryField + '__contains':keyword})
- 即字段名和关键字都是变量
Django视图函数完整代码:
def index(request): if request.method == 'POST': # 接收ajax传递过来的数据,是字典格式 query_data = request.POST keyword = query_data['keyword'] queryField = query_data['queryField'] page_obj = Inventory.objects.filter(**{queryField + '__contains':keyword})
之前使用flask查询代码:
condition = {field: q} if field == "m_name": condition = Inventory.m_name.like('%%%s%%' % q) elif field == "m_number": # condition = Inventory.m_number.like('%%%s%%' % q) search = "%{}%".format(q) condition = Inventory.m_number.like(search) elif field == "person": condition = Inventory.person.like('%%%s%%' % q) elif field == "parts_classlification": condition = Inventory.parts_classlification.like('%%%s%%' % q) elif field == "type": condition = Inventory.type.like('%%%s%%' % q) else: condition = Inventory.id
发现改造后,简洁许多
10 django+ajax使用
和前端交互全部使用JSON,如何将数据库查询结果转换成JSON格式 https://blog.csdn.net/EverXerxes/article/details/84316645
前端
function edit(obj){ var $td= $(obj).parents('tr').children('td'); var m_number = $td.eq(1).text(); console.log(m_number); data = { 'm_number':m_number }; $.ajax({ type:'GET', url:"{% url 'inventory:edit' %}", data:data, dataType:'json', success:function (data){ console.log(data) }, error:function () {alert('数据返回错误!')} }) }
方法一:(django自带的serializers序列化model)(推荐使用此方法)
def edit(request): # ajax传值 m_number = request.GET.get('m_number') inventory= Inventory.objects.filter(m_number=m_number) json_data = serializers.serialize('json', inventory) return HttpResponse(inventory, content_type="application/json")
返回的数据格式:
[ { "model": "inventory.inventory", "pk": 1, "fields": { "type": "KNB32CM55", "m_number": "Pow-001", "m_name": "插接箱", "m_cate": "电气", "kuwei": "0902C1", "quantity": 3, "limit": 16, "life_time": 0, "batch_number": 0, "price": 500, "total_price": 2500, "supply_period": 45, "scarp": "", "parts_classlification": "Spare parts", "person": "Yao Sheng", "comments": "301、302洁净室" } } ]
想要的数据在fields字段里面,有点难受的是,每条数据对象包含 fields,model,pk三个对象,分别代表字段、模型、主键,我更想要一个只包含所有字段的字典对象。虽然也可以处理,但还是省点性能,交给前端解析吧。
ajax使用
m_number = data[0]['fields']['m_number']
$.ajax({ type:'GET', url:"{% url 'inventory:edit' %}", data:data, dataType:'json', async: false, success:function (data) { m_number = data[0]['fields']['m_number'] console.log(m_number) }, error:function () {alert('数据返回错误!')} })
方法二:(model_to_dict方法)
def edit(request): # 获取前端传过来的值 m_number = request.GET.get('m_number') inventory= Inventory.objects.filter(m_number=m_number).first() # 返回单个对象 # 将对象转化为字典 inventory = model_to_dict(inventory) return HttpResponse(json.dumps(inventory), content_type="application/json")
Inventory.objects.filter(m_number=m_number).first()
:返回单个对象model_to_dict(inventory)
:对象转化为字典
返回的数据格式:
{ "id": 1, "type": "KNB32CM55", "m_number": "Pow-001", "m_name": "插接箱", "m_cate": "电气", "kuwei": "0902C1", "quantity": 3, "limit": 16, "life_time": 0, "batch_number": 0, "price": 500, "total_price": 2500, "supply_period": 45, "scarp": "", "parts_classlification": "Spare parts", "person": "Yao Sheng", "comments": "301、302洁净室" }
ajax使用
m_number = data['m_number']
$.ajax({ type:'GET', url:"{% url 'inventory:edit' %}", data:data, dataType:'json', async: false, success:function (data) { m_number = data['m_number'] console.log(m_number) }, error:function () {alert('数据返回错误!')} })
11 bootstrap表单
11.1 表单验证bootstrapValidator
https://www.jianshu.com/p/756b225d480d https://www.cnblogs.com/huangcong/p/5335376.html
- 首先导入包 ```html
2. 如果想对某一个字段添加验证规则,需要<div class="form-group"></div>包裹,input标签必须有name值,此值为验证匹配的字段。其实就是要符合bootstrap表单结构 ```html <form action="" method="get"> <div class="form-group"> <input id="keyword" name="keyword" class="form-control" style="width:200px;" placeholder="请输入关键字"/> </div> <div class="form-group"> <select id="queryField" name="queryField" class="form-control" style="width:200px;"> <option value="">请选择</option> <option value="m_name">物料名称</option> <option value="m_number">物料号</option> <option value="type">规格型号</option> <option value="person">责任人</option> <option value="parts_classlification">备件分类</option> </select> </div> <div class="form-group"> <button type="submit" id="query" class="btn btn-primary">查询</button> </div> </form>
- JavaScript
notEmpty 验证字段不为空
<script> $(function () { $('form').bootstrapValidator({ feedbackIcons: { valid: 'glyphicon glyphicon-ok', invalid: 'glyphicon glyphicon-remove', validating: 'glyphicon glyphicon-refresh' }, fields: { keyword: { validators: { notEmpty: { message: '请输入要查询的关键字' } } }, queryField: { validators: { notEmpty: { message: '请选择要查询的字段' } } } } }); }); </script>
11.2 表单重置
需求:点击重置按钮,恢复模态框中表单未修改前的数据(向模态框中form表单传值请看第13章:https://www.yuque.com/u1046159/lp12n4/pn8619#vFUuD)
11.3 模态框关闭后,销毁表单验证
模态框里面嵌套表单,表单验证后,关闭模态框,再次打开模态框,之前的表单验证规则还在
首次打开模态框,表单验证
此时关闭模态框,再次打开模态框,验证规则还在
解决办法:https://blog.csdn.net/weixin_40886648/article/details/83379069//去除模态框之前的表单验证 $('#modifymodal').on('hide.bs.modal', function () { $('#modifyForm').bootstrapValidator('resetForm'); });
完整案例:
// 弹出模态框 $("#modifymodal").modal(); //去除模态框之前的表单验证 $('#modifymodal').on('hide.bs.modal', function () { $('#modifyForm').bootstrapValidator('resetForm'); }); //表单验证 $(function () { $('#modifyForm').bootstrapValidator({ message: "this is not valid field", feedbackIcons: { valid: 'glyphicon glyphicon-ok', invalid: 'glyphicon glyphicon-remove', validating: 'glyphicon glyphicon-refresh' }, fields: { quantity: { validators: { notEmpty: { message: '库存数量不能为空' }, digits: { message: '库存数量必须为整数' } } }, limit: { validators:{ notEmpty: { message: '库存数量不能为空' }, digits: { message: '库存数量必须为整数' } } } } }) });
12 bootstrap table api使用
引用文件
<link rel="stylesheet" href="https://unpkg.com/bootstrap-table@1.15.3/dist/bootstrap-table.min.css"> <script src="https://unpkg.com/bootstrap-table@1.15.3/dist/bootstrap-table.min.js"></script> <script src="https://unpkg.com/bootstrap-table@1.15.3/dist/locale/bootstrap-table-zh-CN.min.js"></script>
页面定义table
<table id="inventoryTable"></table>
jQuery
$("#inventoryTable").bootstrapTable({ search: true, //获得一个搜索框 striped: true, //开启斑马线 showColumns: true, //获得一个能选择显示某些列的按钮 showRefresh: true, //获得一个刷新数据按钮 });
13 获取表格当前行数据+向bootstrap模态框传值
需求:点击表格操作按钮,获取当前行数据,传入bootstrap的模态框中,弹出模态框(并进行表单验证),修改数据后,将数据传递给django后台
表格 ```html
{% for inventory in page_obj.object_list %} {% endfor %}id 物料号 物料名称 规格型号 物料分类 库位 库存数量 最低库存数量 {{ inventory.id }} {{ inventory.m_number }} {{ inventory.m_name }} {{ inventory.type }} {{ inventory.m_cate }} {{ inventory.kuwei }} {{ inventory.quantity }} {{ inventory.limit }}
表格中数据是从Django后台返回的 2. 模态框代码 ```html <!--修改按钮弹出框--> <div class="modal" id="modifymodal"> <div class="modal-dialog modal-dialog-centered modal-dialog-scrollable"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button> <h4 class="modal-title">备件信息修改</h4> </div> <form action="" method="get" class="form-horizontal"> <div class="modal-body"> <!--id--> <div class="form-group"> <label class="col-sm-2 control-label">id</label> <div class="col-sm-10"> <input type="text" class="form-control" id="id" disabled value=""> </div> </div> <!--物料号--> <div class="form-group"> <label class="col-sm-2 control-label">物料号</label> <div class="col-sm-10"> <input type="text" class="form-control" id="m_number" value="" disabled> </div> </div> <!--其他字段--> </div> </form> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">确认</button> </div> </div> </div> </div>
方法一:jQuery获取
$(document).on('click','#modify',function () { // 获取表格当前行数据 $("#inventoryTable tbody").on("click", "tr", function () { var data = new Array(); var td = $(this).find("td"); for (var i = 0; i < td.length - 1; i++) { data.push(td.eq(i).text()); } console.log(data); // 向模态框中插值 $("#id").val(data[0]); $("#m_number").val(data[1]); $("#m_name").val(data[2]); $("#type").val(data[3]); $("#m_cate").val(data[4]); $("#kuwei").val(data[5]); $("#quantity").val(data[6]); $("#limit").val(data[7]); $("#parts_classlification").val(data[8]); $("#person").val(data[9]); $("#comments").val(data[10]); }); // 弹出模态框 $("#modifymodal").modal(); });
td.length-1
:取出操作列中的修改、出库申请文字,只获取前面内容
这种情况下,如果希望有个表单重置按钮,时不能恢复未修改前的数据的!
获取到的数据
效果图:使用这种方法,发现一个bug,页面刷新后,首次点击,模态框中是没有数据的,只有再次点击,模态框才有数据
首次点击
再次点击暂时没有找到解决方法,使用原生js可解决这个问题!
<button id="modify" type="button" class="btn btn-primary btn-sm" onclick="modify()">修改</button> // 修改功能 function modify(){ // 获取表格当前行数据 $("#inventoryTable tbody").on("click", "tr", function () { var data = new Array(); var td = $(this).find("td"); for (var i = 0; i < td.length - 1; i++) { data.push(td.eq(i).text()); } console.log(data); // 向模态框中插值 $("#id").val(data[0]); $("#m_number").val(data[1]); $("#m_name").val(data[2]); $("#type").val(data[3]); $("#m_cate").val(data[4]); $("#kuwei").val(data[5]); $("#quantity").val(data[6]); $("#limit").val(data[7]); $("#parts_classlification").val(data[8]); $("#person").val(data[9]); $("#comments").val(data[10]); }); // 弹出模态框 $("#modifymodal").modal(); }
方法二 :ajax
table
<table> <thead> <tr> <th scope="col">备件类型</th> <th scope="col">物料责任人</th> <th scope="col">备注</th> <th scope="col">操作</th> </tr> </thead> <tbody> {% for inventory in page_obj.object_list %} <tr> <td>{{ inventory.parts_classlification }}</td> <td>{{ inventory.person }}</td> <td>{{ inventory.comments }}</td> <td> <button id="modify" type="button" class="btn btn-primary btn-sm" onclick="edit(this)">修改</button> <button id="apply" type="button" class="btn btn-primary btn-sm" style="margin-left: 3px">出库申请 </button> </td> </tr> {% endfor %} </tbody> </table>
- 给修改按钮绑定点击事件:
onclick="edit(this)"
,获取当前表格关键字,ajax将值传给后端,django后端查询后,返回给ajax,然后使用jQuery为=赋值
ajax
// 修改功能 function edit(obj){ var $td= $(obj).parents('tr').children('td'); var m_number = $td.eq(1).text(); console.log(m_number); data = { 'm_number':m_number }; $.ajax({ type:'GET', url:"{% url 'inventory:edit' %}", data:data, dataType:'json', async: false, success:function (data) { $("#id").val(data['id']); $("#m_number").val(data['m_number']); $("#m_name").val(data['m_name']); $("#type").val(data['type']); $("#m_cate").val(data['m_cate']); $("#kuwei").val(data['kuwei']); $("#quantity").val(data['quantity']); $("#limit").val(data['limit']); $("#parts_classlification").val(data['parts_classlification']); $("#person").val(data['person']); $("#comments").val(data['comments']); }, error:function () {alert('数据返回错误!')} }); // 弹出模态框 $("#modifymodal").modal(); }
14 django更新数据库数据
需求:前端form表单将修改后的数据,使用post方法传递给后端,django后端接收前端的请求参数,在数据库查询该行数据,更改数据
14.1 方法一
使用以下方法
inventory = Inventory.objects.get(id=id) inventory.m_name = m_name # ... inventory.save()
注意: 对于form表单, 将{% csrf_token %} 添加到您创建的每个使用 POST 提交数据的 Django 模板中。这将减少恶意用户劫持表单的可能性。
<form action="{% url 'inventory:edit' %}" method="post" > {% csrf_token %} </form>
id = request.POST.get('id')
def edit(request): if request.method == 'POST': id = request.POST.get('id') # ...
还有一种方法 :
id = request.POST['id']
重要: 虽然您也可以通过请求直接访问表单数据(例如request.POST[‘renewal_date’] 或 request.GET[‘renewal_date’](如果使用 GET 请求),但不建议这样做。清理后的数据是无害的、验证过的、并转换为 Python 友好类型。
当使用第二种方法时,如果表单字段设置了disabled(input控件被忽略,没有提交内容到后台),会报错:
https://blog.csdn.net/xiaotuwai8/article/details/110958441<input type="text" class="form-control" id="id" name="id" disabled value="">
报错:
django.utils.datastructures.MultiValueDictKeyError: 'id'
更新数据库数据
def edit(request): if request.method == 'POST': id = request.POST.get('id') m_name = request.POST.get('m_name') # 其他 inventory = Inventory.objects.get(id=id) inventory.m_name = m_name # ... inventory.save() return redirect('inventory:index')
- 修改先要查找,然后再修改
- 一定要使用
.save()
方法,否则数据不会保存到数据库,修改不成功14.2 方法二
使用: ```python m_number = request.POST.get(‘m_number’)
Inventory.objects.filter(m_number=m_number).update( m_name=m_name, type=type, m_cate=m_cate, kuwei=kuwei, quantity=quantity, limit=limit, parts_classlification=parts_classlification, person=person, comments=comments )
- **update**只能结合**filter**一起用 - `m_number=m_number`:前面是数据库字段,后面是赋值的变量名(即要更改的数据) 方法一适合更新一条数据,也只能更新一条数据,当只有一条数据更新时推荐使用此方法<br />方法二适合更新一批数据,类似于mysql语句update user set username='nick' where id = 1 <a name="qV1gq"></a> # 15 jQuery给表格每一行按钮绑定点击事件不生效 表格 ```html <table> <thead> <tr> <th scope="col">物料号</th> //其他 </tr> </thead> <tbody> {% for inventory in page_obj.object_list %} <tr> <td>{{ inventory.m_number }}</td> //其他 <td> <button id="modify" type="button" class="btn btn-primary btn-sm">修改</button> </td> </tr> {% endfor %} </tbody> </table>
为修改按钮绑定点击事件,只有表格第一行的修改按钮点击有反应,其他行修改按钮点击没反应,也没报错,下面是jQuery代码:
$('#modify').click(function () { alert('test') })
解决方法:使用on
$(document).on('click','#modify',function () { alert('test') })
- on方法的第一个参数为click,第二个是按钮id,第三个是function
原因:https://www.cnblogs.com/leiting/p/9323539.html
16 django中外键ForeignKey
有两张表,一张用户表,一张角色表,用户表中字段role_id是角色表中的主键role_id
模型类
class User(models.Model): """用户""" domain_name = models.CharField(max_length=125) real_name = models.CharField(max_length=125) department = models.CharField(max_length=125) email = models.CharField(max_length=125) role_id = models.ForeignKey('Role',on_delete=models.CASCADE) status = models.IntegerField() first_login = models.IntegerField() class Role(models.Model): '''角色''' role_id = models.AutoField(primary_key=True) name = models.CharField(max_length=125) description = models.CharField(max_length=125) status = models.IntegerField()
ForeignKey ( othermodel, on_delete, _options _)**
- 有两个必选参数,第一个参数为关联的表格(主表)在默认的情况下,外键储存的是主表的主键(Primary key),上述案例user表中role_id会自动关联role表中主键role_id;第二个参数:CASCADE,当主表的字段被删除时,和他有关的子表字段也会被删除
数据库迁移后,两张表结构
user表
role表17 django会话(session)
https://www.liujiangblog.com/course/django/168 https://docs.djangoproject.com/zh-hans/3.2/topics/http/sessions/
需求:用户登录时获取当前用户名,从数据库中查询用户名对应的信息,存入session中
# 首页 def index(request): user = User.objects.filter(domain_name='zxy').first() user = model_to_dict(user) request.session['domain_name'] = 'zxy' request.session['role_id'] = user['role_id'] request.session['status'] = user['status'] request.session['first_login'] = user['first_login']
- 为了方便测试,设置了一个假的用户名 zxy
当会话中间件启用后,传递给视图request参数的HttpRequest对象将包含一个session属性,这个属性的值是一个类似字典的对象。你可以在视图的任何地方读写request.session属性
request.session['domain_name'] = 'zxy
: 设置值request.session['domain_name']
:取值