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‘: ‘16‘}
            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)
}

这就是添加、修改页面的主要功能了。

原文地址:https://www.cnblogs.com/shenjianping/p/10911605.html

时间: 2024-10-08 06:27:03

stark组件之添加、修改页面内容搭建(七)的相关文章

phpcms v9 后台添加修改页面空白页问题解决方法

phpcms v9 添加修改页面空白页的解决方法 找一个正常运行的phpcms 将caches\caches_model\caches_data 目录下的 content_form.class.php content_input.class.php content_output.class.php content_update.class.php 上传覆盖. 问题引发原因为更新缓存,缓存更新后记得重新覆盖. 这个问题真神奇,问题解决请留言点赞~~

stark组件之删除页面内容搭建(八)

删除页面没有太多的内容和功能 def del_view(self, request,pk,*args,**kwargs): """ 处理删除表弟 :param request: :param pk: :return: """ obj = self.model_class.objects.filter(pk=pk).first() if not obj: return HttpResponse('该内容不存在') if request.method

FileSystemObject组件新建读取添加修改删除功能实例

<%@LANGUAGE="VBSCRIPT" CODEPAGE="936"%> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312"> <title>FileSystemObject组件应该实例</title> </head> <

Flex4_Tree组件2(添加多选框、修改树图标)

1.新建AS类,用于为Tree生成复选框,及一些选择事件. package com.th.myUtils { import flash.events.Event; import flash.events.MouseEvent; import mx.controls.Alert; import mx.controls.CheckBox; import mx.controls.Tree; import mx.controls.treeClasses.TreeItemRenderer; import

Web浏览器中动态添加修改HTML页面代码的问题分析

引言:在Web的世界里,浏览器加载页面,展示给用户最终的内容,可是最终展示的HTML代码与服务器上存储的代码一致吗? 1.  xpath为什么不能正常工作? XPath是用来快速定位页面元素的方式和方法,忽然有一天,发现在页面中截取的XPath在代码的匹配中是无法工作的,那问题出在哪里呢? 页面地址:http://www.66ip.cn/ 截取匹配页面中的IP地址,基于Chrome浏览器自带的开发者工具,我们截取到某一个匹配的XPath路径为: //*[@id="main"]/div/

打通前后端全栈开发node+vue进阶【课程学习系统项目实战详细讲解】(3):用户添加/修改/删除 vue表格组件 vue分页组件

第三章 建议学习时间8小时      总项目预计10章 学习方式:详细阅读,并手动实现相关代码(如果没有node和vue基础,请学习前面的vue和node基础博客[共10章] 演示地址:后台:demoback.lalalaweb.com  前台:demo.lalalaweb.com 演示过程中可能会发现bug,希望即时留言反馈,谢谢 源码下载:https://github.com/sutianbinde/classweb               //不是全部的代码,每次更新博客才更新代码 学

vue把输入框的内容添加到页面(简单留言板)

文章地址:https://www.cnblogs.com/sandraryan/ vue最最最简单的demo(记得引入) 实例化一个vue,绑定#app的元素,要渲染的数组arr作为data. 把arr的item渲染到页面,输入内容点击按钮把用户输入的内容添加到页面以及数组 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title&

动态添加修改删除html表格内容

1.需求 需要实现收银台上添加修改删除商品信息时顾显可以实时看到其变化 2.解决 收银台和顾显通过tcp传输进行数据通信,顾显通过操作html中的表格进行数据添加修改和删除操作 3.代码 mytest.html <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Dynamic Table<

vue组件样式添加scoped属性之后,无法被父组件修改。或者无法在本组件修改element UI样式

在vue开发中,需要使用scoped属性避免样式的全局干扰,但是这样在父组件中是无法被修改的,不仅如此如果项目中用了UI框架比如element Ui,这个时候在本组件也无法修改样式,因为权重问题.但是想要修改还是有方法的: 1. 在不去掉scoped的情况下,在全局样式中覆盖,这种解法,有弊端,可能会污染全局样式. 2. 如果项目用到了预处理器,可以通过vue-loader提供的新写法 vue-loader 写法如下: <style scoped> .a >>> .b { /