stark组件之添加、修改页面内容搭建(七)
如何快速的进行数据的添加以及修改呢?modelform来实现是可以达到效果的,在这里就是应用了modelform,每一个表都不同,所以需要创建不同的modelform。
def get_model_form_class(self, is_add,request,pk, *args,**kwargs):
"""
获取添加、修改功能的modelform
:return:
"""
if self.model_form_class:
return self.model_form_class class AddModelForm(BaseModelForm,forms.ModelForm):
class Meta:
model = self.model_class
fields = '__all__' return AddModelForm
是否注意到创建modelform时继承了BaseModelForm,实际上就是将request对象传入modelform中
class BaseRequestModelForm(object):
def __init__(self, request, *args, **kwargs):
self.request = request
super(BaseRequestModelForm, self).__init__(*args, **kwargs) class BaseModelForm(BaseRequestModelForm,forms.ModelForm): def __init__(self,request,*args,**kwargs):
super().__init__(request,*args,**kwargs)
#####给modelform字段加样式
for name,field in self.fields.items():
attrs_dict={'class':'form-control'}
if 'DateTimeField' in field.__repr__():
attrs_dict = {'class': 'form-control', 'date_time': 'datetimepicker', 'size': ''}
field.widget.attrs.update(attrs_dict)
这就是在之前提到过的在执行视图函数之前装饰器的作用。
def wrapper(self, func): # 将视图函数加上装饰器,这样可以在处理视图之前之后都可以加上一定的功能
@functools.wraps(func) # 保留原函数的信息
def inner(request, *args, **kwargs):
self.request = request # 将request传给当前对象,在处理视图函数之前
BaseRequestForm(request)
BaseRequestModelForm(request)
return func(request, *args, **kwargs) return inner
那么为什么要这样做呢?给一个场景就是客户付款的订单只是自己所有的订单,并不包括其他客户的订单。
class PaymentRecordModelForm(BaseModelForm):
class Meta:
model=models.PaymentRecord
exclude=['confirm_date','confirm_user'] def __init__(self,request,*args, **kwargs): #form中没有传入request对象
super().__init__(request,*args, **kwargs)
current_user_id = self.request.session['user_info']['id']
customer=models.Customer.objects.filter(name=models.UserInfo.objects.filter(id=current_user_id).first().username).first()
self.fields['order'].queryset = models.Order.objects.filter(customer=customer)
接下来就是添加、修改的视图函数
def add_view(self,request,*args,**kwargs):
# 处理所有添加功能,使用ModelForm来实现
Add_Model_Form = self.get_model_form_class(True,request,None,*args,**kwargs)
if request.method == 'GET':
form = Add_Model_Form(request=request)
return render(request, 'stark/change.html', {'form': form,'starkclass':self})
form = Add_Model_Form(request=request,data=request.POST)
if form.is_valid():
obj=self.save(request,form,False,*args,**kwargs)
# obj=form.save()
pop_post_id=request.GET.get('pop_id')
if pop_post_id:
res={'pop_post_id':pop_post_id,'pk':obj.pk,'obj':str(obj)}
return render(request,'stark/pop.html',res) return redirect(self.reverse_changelist_url(*args,**kwargs))
return render(request, 'stark/change.html', {'form': form})
def change_view(self, request,pk,*args,**kwargs):
"""
处理所有修改表单
:param request:
:param pk:
:return:
"""
Edit_Model_Form = self.get_model_form_class(False,request,pk,*args,**kwargs)
obj = self.model_class.objects.filter(pk=pk).first()
if not obj:
return HttpResponse('该用户不存在')
if request.method == 'GET':
form = Edit_Model_Form(request,instance=obj)
return render(request, 'stark/change.html', {'form': form})
form = Edit_Model_Form(request=request,data=request.POST,instance=obj)
if form.is_valid():
self.save(request,form,True,*args,**kwargs)
return redirect(self.reverse_changelist_url(*args,**kwargs))
filter_horizontal=self.get_filter_horizontal()
el=EditList(self,request,pk,filter_horizontal,*args,**kwargs)#修改和添加共用一个页面,所以form没有进行封装
return render(request, 'stark/change.html', {'form': form,'el':el})
注意在保存时并没有直接保存,而是预留了保存的钩子函数,这样在保存前还可以做一些其它动作。
####对于一些排除字段,重新此方法进行添加
def save(self,request,form,is_modify,*args,**kwargs): return form.save()
在这里添加和修改共用了一个模板页面,添加中包括了pop功能,和djangoadmin类似,凡是foreignkey字段都可以进行点击添加。修改页面中有filter_horizontal功能,主要就是针对ManyToMany字段。
<form class="change" method="post" novalidate>
{% csrf_token %}
{% for filed in form %}
<div class="form-group" style="position: relative">
{% if field.name in el.filter_horizontal %}
<label>{{ filed.label }}</label>
{% m2m_all_data form field el.stark_class %}
<span class="errors pull-right" style="color: red">{{ filed.errors.0 }}</span>
{% else %} <label>{{ filed.label }}</label>
{% gen_is_pop filed starkclass %}
<span class="errors pull-right" style="color: red">{{ filed.errors.0 }}</span>
{% endif %}
</div>
{% endfor %}
<button type="submit" class="btn btn-primary">保存</button> </form>
在添加页面中对后台传递的form字段进行判断,如果是ManyToMany就执行m2m_all_data 标签方法。
@register.inclusion_tag('stark/m2m.html')
def m2m_all_data(form,field,stark_class):
return {'m2m_data':m2m_data(form,field,stark_class),'m2m_un_data':m2m_un_data(form,field,stark_class),'field':field}
@register.simple_tag()
def m2m_data(form,field,stark_class):
"""
出项在左侧的可选项
:param form:
:param field:
:param stark_class:
:return:
"""
field_name=field.name
field_obj=stark_class.model_class._meta.get_field(field_name)
if isinstance(field_obj,ManyToManyField):
data_set = set(field_obj.remote_field.model.objects.all())
if form.instance.id:
selected_data_set=set(getattr(form.instance,field_obj.name).all())
queryset=data_set-selected_data_set
return queryset
return data_set @register.simple_tag()
def m2m_un_data(form,field,stark_class):
"""
出项在右侧已选项
:param form:
:param field:
:return:
"""
field_name = field.name
field_obj=stark_class.model_class._meta.get_field(field_name)
if isinstance(field_obj,ManyToManyField):
if form.instance.id:
selected_data_set = getattr(form.instance, field_obj.name).all()
return selected_data_set
else:
return []
这里利用了inclusion_tag方法
{% load stark %}
<div class="row">
<div class="col-lg-6">
<input type="search" oninput="M2mSearch(this)" class="form-control">
<select id="id_{{ field.name }}_from" multiple class="multiselect" class="form-control">
{% for row in m2m_data %}
<option ondblclick="MoveElement(this,'id_{{ field.name }}_to')" value="{{ row.id }}">{{ row }}</option>
{% endfor %}
</select>
<p><a onclick="MoveAllElements('id_{{ field.name }}_from','id_{{ field.name }}_to')">全选</a></p>
</div> <div class="col-lg-6">
<input type="search" oninput="M2mSearch(this)" class="form-control">
<select id="id_{{ field.name }}_to" selected_data="selected_m2m" multiple class="multiselect" name="{{ field.name }}" class="form-control">
{% for row in m2m_un_data %}
<option ondblclick="MoveElement(this,'id_{{ field.name }}_from')"
value="{{ row.id }}">{{ row }}</option>
{% endfor %}
</select>
<p><a onclick="MoveAllElements('id_{{ field.name }}_to','id_{{ field.name }}_from')">移除</a></p>
</div>
</div>
需要用到的script代码
function readysubmit() { $('select[selected_data] option').prop('selected', true);
} function MoveElement(ths, target_id) {
var $target_from_id = $(ths).parent().attr('id');
var op = $('<option></option>');
op.attr('ondblclick', 'MoveElement(this,"' + $target_from_id + '")');
op[0].value = $(ths).val();
op[0].text = $(ths).text();
$('#' + target_id).append(op);
$(ths).remove()
} function MoveAllElements(from_id, target_id) {
$('#' + from_id).children().each(function () {
MoveElement($(this), target_id)
})
} function M2mSearch(ths) {
var $searchText = $(ths).val().toUpperCase();
$(ths).next().children().each(function () {
var $matchText = $(this).text().toUpperCase().search($searchText);
if ($matchText != -1) {
$(this).show()
} else {
$(this).hide()
}
}) }
另外一个就是pop功能了,主要解决Foreignkey的问题
@register.simple_tag()
def gen_is_pop(bfield,starkclass):
if isinstance(bfield.field,ModelChoiceField):
namespace=starkclass.site.namespace
related_app_lebel=bfield.field.queryset.model._meta.app_label
related_model_name=bfield.field.queryset.model._meta.model_name
url_name='%s:%s_%s_add'%(namespace,related_app_lebel,related_model_name)
add_url=reverse(url_name)
add_url=add_url+'?pop_id=id_%s'%bfield.name
return mark_safe("""<a onclick="pop('%s')" style="position: absolute;right: -30px;top: 20px"><span style="font-size: 28px">+</span></a>"""%add_url)
return bfield
后台返回的数据先返回给另一个html页面,在这个页面中执行父窗口中的js代码
{% extends 'layout.html' %} {% block js %}
<script>
(function () {
opener.get_data('{{ pop_post_id }}','{{ pk }}','{{ obj }}');
window.close()
})() </script> {% endblock %}
父窗口中的js代码实际就是get_data()函数了
function pop(url) {
window.open(url,'PopName',"width=600,height=400,top=100,left=100")
} function get_data(pop_post_id,pk,obj) {
var $option=$('<option>');
$option.html(obj);
$option.val(pk);
$option.attr('selected','selected');
$('#'+pop_post_id).append($option)
}
这就是添加、修改页面的主要功能了。
stark组件之添加、修改页面内容搭建(七)的更多相关文章
- stark组件开发之列表页面定制列
先看一张页面展示的效果图: 看一看我的 model 表!是什么样子: 看一看数据库是什么样子: 看 页面展示图,有表头. 有数据.模型表中,每一个字段, 都指定了 verbose_name. 如何解 ...
- phpcms v9 后台添加修改页面空白页问题解决方法
phpcms v9 添加修改页面空白页的解决方法 找一个正常运行的phpcms 将caches\caches_model\caches_data 目录下的 content_form.class.php ...
- stark组件开发之列表页面应用示例
已经解决的,自定义的扩展函数,功能.但是 不可能返回. 一个 固定的页面把! 应该是,点击那条 记录之后的编辑, 就会跳转到相应的,编辑页面.所以 这个标签的 <a href="/ ...
- stark组件之删除页面内容搭建(八)
删除页面没有太多的内容和功能 def del_view(self, request,pk,*args,**kwargs): """ 处理删除表弟 :param reque ...
- stark组件之显示页面内容搭建(六)
之前主要介绍了前端页面list_fiter功能的显示,但是list_display功能的展示并没有过多介绍,这里介绍一下是如何实现的. 可以看到凡是蓝线圈起来的都是通过字段名反射一个个取出来的,红线的 ...
- JQuery DataTables Editor---只修改页面内容
近来在工作中需要对JQuery DataTables进行增,删,改的操作,在网上找了一些资料,感觉比较的好的就是(http://editor.datatables.net/)文章中所展示的操作方法(如 ...
- stark组件开发之列表页面自定义函数扩展
对于展示页面, 可能需要显示一些. 数据库中,没有的字段. 比如, 删除按钮, 编辑按钮. 这个数据库,是没有的. 所以,可能就需要, 添加一个这个东西. 比如我在渲染的时候, 给他添加两个函数进 ...
- stark组件开发之列表页面预留钩子方法。 可根据用户的不同,显示不同的列
要实现,这个方法.子类中 list_diplay 这个列表, 就不能够写死.他应该是 可以根据.用户的不同,返回不同的值. 所以 就需要一个函数, 可以进行判断当前用户是谁. 并且往这个列表中添加,他 ...
- Python-S9-Day88——stark组件之设计urls
03 stark组件之设计urls 04 stark组件之设计urls2 05 stark组件之设计list_display 06 stark组件之z查看页面的数据展示 03 stark组件之设计ur ...
随机推荐
- 洛谷P1552 [APIO2012]派遣(左偏树)
传送门 做这题的时候现学了一波左偏树2333(好吧其实是当初打完板子就给忘了) 不难发现肯定是选子树里权值最小的点且选得越多越好 但如果在每一个点维护一个小根堆,我们得一直找知道权值大于m为止,时间会 ...
- Word Cloud (词云) - R
在前面已经陆续总结了如何用 Python 和 JavaScript 创建词云了,今天要说的是 R.其实 SPSS 和 SAS 的 Word Cloud 扩展模板都是基于 R 实现的. >> ...
- docker 中部署一个springBoot项目
docker 中部署一个springBoot项目 (1)介绍 springBoot项目 1.项目结构 2.pom.xml <?xml version="1.0" encodi ...
- Qt事件系统之五:事件过滤器和事件的发送
Qt提供了事件过滤器来实现在一个部件中监控其他多个部件的事件.事件过滤器与其他部件不同,它不是一个类,只是由两个函数组成的一种操作,用来完成一个部件对其他部件的事件的监视.这两个函数分别是 insta ...
- jmeter(九)分布式测试
Jmeter 是java 应用,对于CPU和内存的消耗比较大,因此,当需要模拟数以千计的并发用户时,使用单台机器模拟所有的并发用户就有些力不从心,甚至会引起JAVA内存溢出错误.为了让jmeter工具 ...
- 455 Assign Cookies 分发饼干
假设你是一位很棒的家长,想要给你的孩子们一些小饼干.但是,每个孩子最多只能给一块饼干.对每个孩子 i ,都有一个胃口值 gi ,这是能让孩子们满足胃口的饼干的最小尺寸:并且每块饼干 j ,都有一个尺寸 ...
- ambari集群里如何正确删除历史修改记录(图文详解)
不多说,直接上干货! 答:这些你想删除的话得得去数据库里删除,最好别删除 . 现在默认就是使用好的配置 欢迎大家,加入我的微信公众号:大数据躺过的坑 人工智 ...
- oracle数据库常用的99条查询语句
1. select * from emp; 2. select empno, ename, job from emp; 3. select empno 编号, ename 姓名, job 工作 fro ...
- Docker安装jenkins(六)
这里是在linux环境下安装docker之后,在doucer内安装jenkins --------------------docker 安装 jenkins---------------------- ...
- 函数的返回值return
'''1.什么是返回值 返回值是一个函数的处理结果 2.为什么要有返回值 如果我们需要在程序中拿到函数的处理结果做进一步的处理,则需要函数必须有返回值 3.函数的返回值的应用 函数的返回值用retur ...