注意点

<form class="form-horizontal" method="post" novalidate>
method="post" : 指定form表单提交方式
novalidate : 去除前端校验
field_obj.widget.attrs['class'] = 'form-control' : 添加class='form-control'属性
<span style="color: red">{{ form_obj.hostname.errors.0 }}</span> # 渲染错误信息 # 如何区分编辑还是新增就是看有没有instance参数
form_obj = ServerModeForm(data=request.POST) # 新增
form_obj = ServerModeForm(instance=edit_obj) # 渲染标签,渲染数据
form_obj = ServerModeForm(data=request.POST,instance=edit_obj) # 编辑 <a href="{% url 'server_edit' server_obj.pk %}">编辑</a>

form.html 添加编辑页面

{% extends 'base.html' %}

{% block content %}
<form class="form-horizontal" method="post" novalidate>
{% csrf_token %}
{% for foo in form_obj %}
<div class="form-group">
<label for="{{ foo.id_for_label }}"
class="col-sm-2 control-label">{{ foo.label }}</label>
<div class="col-sm-10">
{{ foo}}
<span style="color: red">{{ foo.errors.0 }}</span>
</div>
</div>
{% endfor %}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-success">提交</button>
</div>
</div>
</form>
{% endblock %}

ModelForm

from django.forms import ModelForm
from app01 import models class ServerModeForm(ModelForm):
class Meta:
model = models.Server
fields = "__all__" def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# OrderedDict([('hostname', <django.forms.fields.CharField object at 0x0000029EBC724518>)])
# print(self.fields)
# 给所有的字段加class的属性
for k, field_obj in self.fields.items():
field_obj.widget.attrs['class'] = 'form-control'

添加

html

<a href="{% url 'server_add'%}" class="btn btn-danger" style="margin: 10px 0">添加数据</a>
def server_add(request):
# 1 先生成一个modelform的空对象
form_obj = ServerModeForm() # 渲染标签
if request.method == 'POST':
form_obj = ServerModeForm(data=request.POST) # 新增
# 3 判断是否合法
if form_obj.is_valid():
# 保存数据
form_obj.save()
# 跳转到服务器的展示页
# return redirect('/server/list')
return redirect('server_list') # 还可以写别名 但是如果出现有名无名分组的反响解析 则必须使用reverse方法
# 2 将该对象传给html
return render(request, 'form.html', locals())

编辑

html

{% for server_obj in server_queryset %}
<tr>
<td>{{ server_obj.pk }}</td>
<td>{{ server_obj.hostname }}</td>
<td>
<a href="{% url 'server_edit' server_obj.pk %}">编辑</a>
<a href="" onclick="removeDate(this,{{ server_obj.pk }})" >删除</a>
</td>
</tr>
{% endfor %}

py

def server_edit(request, edit_id):
edit_obj = models.Server.objects.filter(pk=edit_id).first()
# 生成待编辑的modeform对象
form_obj = ServerModeForm(instance=edit_obj) # 渲染标签,渲染数据 if request.method == 'POST':
form_obj = ServerModeForm(data=request.POST, instance=edit_obj) # 编辑
if form_obj.is_valid():
form_obj.save()
return redirect('server_list')
return render(request, 'form.html', locals())

删除

html

{% for server_obj in server_queryset %}
<tr>
<td>{{ server_obj.pk }}</td>
<td>{{ server_obj.hostname }}</td>
<td>
<a href="{% url 'server_edit' server_obj.pk %}">编辑</a>
<a href="" onclick="removeDate(this,{{ server_obj.pk }})" >删除</a>
</td>
</tr>
{% endfor %} # 删除Js
function removeDate(ths,sid) {
var res = confirm('确定删除吗?');
if (res){
$.ajax({
url:'/server/delete/'+sid+'/',
type:'get',
success:function (args) {
if (args.status){
$(ths).parent.parent.remove() # DOM操作,删除标签
}
}
})
}
}

py

def server_delete(request, delete_id):
models.Server.objects.filter(pk=delete_id).delete()
return JsonResponse({'status': True}) # 返回给前端,表示已经删除

代码优化

优化1

将所有的modelform单独抽取出来

将modelform类中所有公共的部分抽取出来形成基类

# 父类
from django.forms import ModelForm class BaseModelForm(ModelForm):
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
# print(self.fields) # OrderedDict([('hostname', <django.forms.fields.CharField object at 0x10c99c198>)])
# 给所有的字段加class属性
for k,field_obj in self.fields.items():
field_obj.widget.attrs['class'] = 'form-control' # 子类
from app01.myforms.base import BaseModelForm
from app01 import models class ServerModelForm(BaseModelForm):
class Meta:
model = models.Server
fields = "__all__"

优化2

当模型表字段特别多的时候,并且并不是所有的字段都需要展示到前端给用户观看

from django.forms import ModelForm

class BaseModelForm(ModelForm):
# 自定义字段是否需要加额外属性的配置
exclude_bootstrap = [] def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
# print(self.fields) # OrderedDict([('hostname', <django.forms.fields.CharField object at 0x10c99c198>)])
# 给所有的字段加class属性
for k,field_obj in self.fields.items():
if k in self.exclude_bootstrap:
continue # 排除在外不添加样式
field_obj.widget.attrs['class'] = 'form-control'

优化3

项目表需要额外添加字段

    # 线上服务器地址
path = models.CharField(verbose_name='线上地址',max_length=64)
# 关联服务器
"""
一个项目可以跑在多个服务器上
一个服务器其实也可以跑多个项目 (公司服务器不够的时候 可以混用)
"""
servers = models.ManyToManyField(to='Server',verbose_name='关联服务器') # 项目展示页面额外展示当前两个字段 <th>线上地址</th>
<th>线上关联服务器</th> <td>{{ project_obj.path }}</td>
<td>
{% for server_obj in project_obj.server.all %}
<span style="border: 1px solid black;padding: 5px">{{ server_obj.hostname }}</span>
{% endfor %}
</td>

modelform+代码发布系统前奏的更多相关文章

  1. 【运维工具】Git代码发布系统

    引言 代码发布系统是互联网公司必备的运维系统,作用主要用户发布业务代码 到 业务服务器 为什么需要代码发布系统 有的同学可能说,我们公司服务器就那么一台,做个发布系统太麻烦了? 不认同这说法 发布系统 ...

  2. Walle代码发布系统

    Walle 一个web部署系统工具,配置简单.功能完善.界面流畅.开箱即用!支持git.svn版本管理,支持各种web代码发布,PHP,Python,JAVA等代码的发布.回滚,可以通过web来一键完 ...

  3. svn 结合rsync 的代码发布系统

    由开发提交到测试环境,经测试,在由运维统一上线.试验需求一台测试服务器,一台线上(生产环境)服务器.测试服务器上跑svn是开发用于代码管理,而线上跑的svn是运维用来代码上线的.结合rsync保持测试 ...

  4. walle代码发布系统配置

    walle Walle 一个web部署系统工具,配置简单.功能完善.界面流畅.开箱即用! 支持git.svn版本管理,支持各种web代码发布, PHP,Python,JAVA等代码的发布.回滚,可以通 ...

  5. 【手把手】JavaWeb 入门级项目实战 -- 文章发布系统 (第十二节)

    好的,那么在上一节中呢,评论功能的后台已经写好了,这一节,先把这部分后台代码和前台对接一下. 1.评论功能实现 我们修改一下保存评论按钮的点击事件,用jQuery的方式获取文本框中的值,然后通过aja ...

  6. ASP.NET MVC5+EF6+EasyUI 后台管理系统(35)-文章发布系统②-构建项目

    系列目录 注:阅读本文,需要阅读本系列的之前文章 代码生成器下载地址(文章开头处) 接下来我们建立数据库的表和各层的代码 我们只需要两张表,文章列表(MIS_Article)和类别表(MIS_Arti ...

  7. 【NodeJS 学习笔记04】新闻发布系统

    前言 昨天,我们跟着这位大哥的博客(https://github.com/nswbmw/N-blog/wiki/_pages)进行了nodeJS初步的学习,最后也能将数据插入数据库了 但是一味的跟着别 ...

  8. 完成一个MVC+Nhibernate+Jquery-EasyUI信息发布系统

    一.最近学习了Jquery-EasyUI框架,结合之前用过的MVC3+Nhibernate做一个信息发布系统,对工作一年半的自己做一个总结吧!(也正好 供初学者学习!) 二.先上截图(系统简介),让大 ...

  9. 安卓项目-利用Sqlite数据库,开发新闻发布系统

    本教程致力于程序员可以快速的学习安卓移动端手机开发. 适合于已经习得一种编程语言的同仁. 更多志同道合,想要学习更多编程技术的大神们. 小弟不才,麻烦关注一下我的今日头条号-做全栈攻城狮. 本文章是基 ...

随机推荐

  1. HTML基本标签,表格标签,框架标签

    1.html简介 1.1什么是html html全称:Hyper Text Markup Language(超文本标记语言) 备注:           a.超文本:页面内可以包含图片.链接,甚至音乐 ...

  2. sleep()和wait()方法的区别

    1,sleep()声明在Thread类中,而且是静态方法: wait()声明在Object类中,而且必须由锁对象调用. 2,sleep()时间达到后恢复: wait()可以设置事件自动恢复,如果没有设 ...

  3. hdu2112 dijkstra

    题目链接:http://icpc.njust.edu.cn/Problem/Hdu/2112/ 只要需处理一下字符串,给他个编号再跑一半dijkstra就行. 代码如下: #include<bi ...

  4. 回文串的Manacher算法

    Manacher算法较传统算法的优化之处在于它对每个回文中心寻找回文半径的时候并不是都从半径为1开始找的,而是利用前面已经完成的任务,寻找一个初始的开始搜索的半径大小,复杂度是线性的. 参考博客:ht ...

  5. ThinkPHP的几种路由形式总结

    本篇文章总结了ThinkPHP的几种路由形式,分别是普通模式.PATHINFO.REWRITE和兼容模式,希望对各位学习thinkphp的朋友有帮助! thinkphp官方文档里有详细的说明: Thi ...

  6. 动态规划/MinMax-Predict the Winner

    2018-04-22 19:19:47 问题描述: Given an array of scores that are non-negative integers. Player 1 picks on ...

  7. [暴力] Educational Codeforces Round 71 (Rated for Div. 2) B. Square Filling (1207B)

    题目:http://codeforces.com/contest/1207/problem/B   B. Square Filling time limit per test 1 second mem ...

  8. 基于树莓派与YOLOv3模型的人体目标检测小车(一)

    项目介绍: 本科毕业选的深度学习的毕设,一开始只是学习了一下YOLOv3模型, 按照作者的指示在官网上下载下来权重,配好环境跑出来Demo,后来想着只是跑模型会不会太单薄,于是想了能不能做出来个比较实 ...

  9. Servlet读取前端的request payload

    这几天遇见了一个很头疼的事,当我想用表单上传文件时,后端servlet读取不到文件的信息 网上搜索,说是要将form添加这个属性enctype="multipart/form-data&qu ...

  10. iOS 设备尺寸与系统信息

    参考 http://blog.csdn.net/newbieprogrammer/article/details/50569384 http://blog.csdn.net/developer_zha ...