美文网首页
django项目--通用视图

django项目--通用视图

作者: 昆仑草莽 | 来源:发表于2019-09-16 11:43 被阅读0次

    自定义通用视图

    web后端开发的工作就是对数据的增删改查!回顾前面的各种功能的代码,会发现有很多的代码冗余。我们在做重复的事情。django框架的一个强大的功能就是提供了一个即插即用的管理后台,django-admin。接下来,我去做一些代码的优化,抽取代码,自定义通用视图。

    一、MyListView

    后台管理功能中,总是需要以数据表的形式展示数据。复杂一点会有过滤,查询,分页等操作。但它们的业务逻辑一致,都是接收请求,然后去数据库中获取数据,再进行过滤,分页,然后展示。抽象出一个MyListView来完成这些通用功能,我们只需要做少量配置就可以实现对不同的模型的数据展示。

    1. 通用的类属性

    找出通用属性,定义在类属性中,子视图类通过覆盖这些属性来完成自定义。

    class MyListView(View):
        model = None                            # 模型
        template_name = None                    # 模板名称
        is_paginate = False                     # 是否分页
        per_page = None                         # 每页条数
        page_header = None                      # 页头大标题
        page_option = None                      # 页头小标题
        table_title = None                      # 内容标题
    
        fields = None                           # 需要展示的字段
    

    2.方法

    2.1 get

    get方法是用来响应get请求的,根据请求,调用相应模型,查询数据然后渲染模板。

        def get(self, request):
            context = self.get_context_data()
            return render(request, self.get_template_name(), context=context)
    

    2.2 get_queryset

    获取查询集,根据是否提供fields属性,来确定返回的数据。如果有搜索,过滤,可以复写该方法。

        def get_queryset(self):
            """获取查询集,如需过滤,请复写此方法"""
            if self.model is not None:
                queryset = self.model._default_manager.all()
            else:
                raise ImproperlyConfigured(
                    "%(cls)s 是不是傻,你没有指定model,我怎么知道呢?" % {
                        'cls': self.__class__.__name__
                    }
                )
            if self.fields:
                queryset = queryset.only(*self.fields)
            return queryset
    

    2.3 get_context_data

    获取视图的上下文变量,如果需要额外添加,可以复写次方法。

        def get_context_data(self, **kwargs):
            """获取视图的上下文变量,如要添加额外变量,请复写此方法"""
            queryset = self.get_queryset()
            if self.is_paginate:
                page_size = self.per_page
    
                if page_size:
                    page = self.paginate_queryset(queryset, page_size)
    
                else:
                    page = self.paginate_queryset(queryset, 10)
            else:
                page = queryset
    
            context = {
                'page_obj': page,
                'page_header': self.page_header,
                'page_option': self.page_option,
                'table_title': self.table_title
            }
    
            context.update(kwargs)
            return context
    

    2.4 get_template_name

    获取模板名称,如果不提供类属性template_name,会根据模型名称拼接出默认的模板myadmin/model_name/model_name_list.html

        def get_template_name(self):
            """获取模板名"""
            if self.template_name is None:
                self.template_name = 'myadmin/{0}/{0}_list.html'.format(self.model._meta.model_name)
    
            return self.template_name
    

    2.5 paginate_queryset

    分页

        def paginate_queryset(self, queryset, page_size):
            """如果需要进行分页"""
            paginator = Paginator(queryset, page_size)
            try:
                page_number = int(self.request.GET.get('page', 1))
            except Exception as e:
                page_number = 1
            page = paginator.get_page(page_number)
            return page
    

    3. 模板

    在模板中将自定义的地方挖坑。obj_list.html

    {% load static %}
    {% load news_customer_filters %}
    <section class="content-header">
        <h1>
            {{ page_header }}
            <small>{{ page_option }}</small>
        </h1>
    
    </section>
    
    <!-- Main content -->
    <section class="content container-fluid">
        <div class="box">
            <div class="box-header with-border">
                <h3 class="box-title">{{ table_title }}</h3>
                <div class="box-tools">
                    {% block add_button %}
                       
                    {% endblock %}
                </div>
            </div>
    
            <!-- /.box-header -->
    
            <div class="box-body">
                {% block search_form %}
                    
                {% endblock %}
                <table class="table table-bordered">
                    <tbody>
                    {% block table_content %}
                      
                    {% endblock %}
                    </tbody>
                </table>
    
    
            </div>
            <!-- 分页 -->
            {% if page_obj.paginator %}
                <div class="box-footer clearfix">
                    <div class="row">
                        <div class="col-sm-6">
                            <div class="dataTables_info" id="example2_info" role="status" aria-live="polite">
                                总共:{{ page_obj.paginator.count }}条 第{{ page_obj.start_index }}到{{ page_obj.end_index }}条
                            </div>
                        </div>
                        <div class="col-sm-6">
                            <ul class="pagination pagination-sm no-margin pull-right">
                                <li {% if not page_obj.has_previous %}class="disabled"{% endif %}
                                    data-page="{{ page_obj.number|add:-1 }}"><a href="#">«</a></li>
                                {% for n in page_obj|page_bar %}
                                    <li {% if n == page_obj.number %}class="active" {% endif %} data-page="{{ n }}"><a
                                            href="#">{{ n }}</a></li>
                                {% endfor %}
                                <li {% if not page_obj.has_next %}class="disabled"{% endif %}
                                    data-page="{{ page_obj.number|add:1 }}"><a href="#">»</a></li>
                            </ul>
                        </div>
                    </div>
    
                </div>
    
    
            {% endif %}
        </div>
    </section>
    {% block script %}
        <script>
            $(() => {
                {% block query_script %}
                    let $queryForm = $('form.user-query');       // 查询表单
                    let $queryBtn = $('form.user-query button.query');    // 查询按钮
                    let $resetBtn = $('form.user-query button.reset');    // 重置按钮
                    // 查询
                    $queryBtn.click(() => {
                        let url = $('.sidebar-menu li.active a').data('url');
                        if (!url) {
                            return
                        }
                        $
                            .ajax({
                                url: url,
                                data: $queryForm.serialize(),
                                type: 'GET'
                            })
                            .done((res) => {
                                $('#content').html(res)
                            })
                            .fail(() => {
                                message.showError('服务器超时,请重试!')
                            })
                    });
    
                    // 重置
                    $resetBtn.click(() => {
                        $queryForm[0].reset();
                        let url = $('.sidebar-menu li.active a').data('url');
                        if (!url) {
                            return
                        }
                        $
                            .ajax({
                                url: url,
                                type: 'GET'
                            })
                            .done((res) => {
                                $('#content').html(res)
                            })
                            .fail(() => {
                                message.showError('服务器超时,请重试!')
                            })
                    });
                {% endblock query_script %}
                // 分页
                let $pageLi = $('ul.pagination li').not('.active').not('.disabled');
                $pageLi.click(function () {
                    let $this = $(this);
    
                    $
                        .ajax({
                            url: $('.sidebar-menu li.active a').data('url'),
                            data: $queryForm.serialize() + '&page=' + $this.data('page'),
                            type: 'GET'
                        })
                        .done((res) => {
                            $('#content').html(res)
                        })
                        .fail(() => {
                            message.showError('服务器超时,请重试!')
                        })
    
                });
    
                // 实例详情
                $('tr').each(function () {
                    $(this).children('td:first').click(function () {
                        let url = $(this).data('url');
                        if (!url) {
                            return
                        }
                        $
                            .ajax({
                                url: url,
                                type: 'GET'
                            })
                            .done((res) => {
                                if (res.errno === '4105') {
                                    message.showError(res.errmsg)
                                } else if (res.errno === '4101') {
                                    message.showError(res.errmsg);
                                    setTimeout(() => {
                                        window.location.href = res.data.url
                                    }, 1000)
    
                                } else {
                                    $('#content').html(res)
                                }
                            })
                            .fail(() => {
                                message.showError('服务器超时,请重试!')
                            })
    
                    })
                });
    
                // 添加实例
                $('.box-tools button').click(function () {
                    let url = $(this).data('url');
                    if (!url) {
                        return
                    }
                    $
                        .ajax({
                            url: url,
                            type: 'GET'
                        })
                        .done((res) => {
                            if (res.errno === '4105') {
                                message.showError(res.errmsg)
                            } else if (res.errno === '4101') {
                                message.showError(res.errmsg);
                                setTimeout(() => {
                                    window.location.href = res.data.url
                                }, 1000)
    
                            } else {
                                $('#content').html(res)
                            }
                        })
                        .fail(() => {
                            message.showError('服务器超时,请重试!')
                        })
                });
            });
        </script>
    {% endblock %}
    
    <!-- /.content -->
    

    4. 自定义过滤器

    4.1 page_bar

    根据分页页面对象生成分页页码

    from django import template
    
    register = template.Library()
    
    
    @register.filter
    def page_bar(page):
        page_list = []
        if page.number != 1:
            page_list.append(1)
        if page.number - 3 > 1:
            page_list.append('...')
        if page.number - 2 > 1:
            page_list.append(page.number - 2)
        if page.number - 1 > 1:
            page_list.append(page.number - 1)
        page_list.append(page.number)
        if page.paginator.num_pages > page.number + 1:
            page_list.append(page.number + 1)
        if page.paginator.num_pages > page.number + 2:
            page_list.append(page.number + 2)
        if page.paginator.num_pages > page.number + 3:
            page_list.append('...')
        if page.paginator.num_pages != page.number:
            page_list.append(page.paginator.num_pages)
        return page_list
    
    

    二、UpdateView

    1. 通用的类属性

    找出通用属性,定义在类属性中,子视图类通过覆盖这些属性来完成自定义。

    class UpdateView(View):
        model = None
        form_class = None
        template_name = None
        fields = None       # 需要修改的字段
        page_header = None  # 页头大标题
        page_option = None  # 页头小标题
        table_title = None  # 内容标题
    
        pk = None           # url路径参数名,默认pk 对象的pk字段
    

    2.方法

    2.1 get

    get方法是用来响应get请求的,根据请求,获取模型对象,生成表单,渲染页面。

        def get(self, request, **kwargs):
            self.obj = self.get_obj(**kwargs)
            context = self.get_context_data()
            return render(request, self.get_template_name(), context=context)
    

    2.2 put

    put方法是用来响应put请求的,根据请求,获取模型对象,获取参数,填充表单,校验,修改对象。

        def put(self, request, **kwargs):
            self.obj = self.get_obj(**kwargs)
            self.form_class = self.get_form_class()
            form = self.form_class(QueryDict(request.body), instance=self.obj)
            if form.is_valid():
                self.save(form)
                return json_response(errmsg='修改数据成功!')
            else:
                context = self.get_context_data(form=form)
    
                return render(request, self.get_template_name(), context=context)
    

    2.3 get_obj_id

    获取传入的对象主键

        def get_obj_id(self, **kwargs):
            if self.pk is None:
                self.obj_id = kwargs.get('pk')
            else:
                self.obj_id = kwargs.get(self.pk)
    

    2.4 get_obj

    根据传入的对象主键获取需要修改的对象

        def get_obj(self, **kwargs):
            self.get_obj_id(**kwargs)
            if self.model is None:
                raise ImproperlyConfigured('没有设置模型')
            obj = self.model.objects.filter(pk=self.obj_id).first()
            if not obj:
                raise ObjectDoesNotExist('找不到pk=%s的对象' % self.obj_id)
            return obj
    

    2.5 get_template_name

    获取模板名称,如果不提供类属性template_name,会根据模型名称拼接出默认的模板myadmin/model_name/model_name_detail.html

        def get_template_name(self):
            """获取模板名"""
            if self.template_name is None:
                self.template_name = 'myadmin/{0}/{0}_detail.html'.format(self.model._meta.model_name)
    
            return self.template_name
    

    2.6 get_context_data

    获取视图的上下文变量,如果需要额外添加,可以复写次方法。

        def get_context_data(self, **kwargs):
    
            self.form_class = self.get_form_class()
            form = self.form_class(instance=self.obj)
            context = {
                'form': form,
                'page_header': self.page_header,
                'page_option': self.page_option,
                'table_title': self.table_title
            }
            context.update(kwargs)
            return context
    

    2.7get_form_class

    获取表单类,如果没有提供,通过给定字段属性自动生成

        def get_form_class(self):
            if self.form_class is None:
                if self.fields is None:
                    raise ImproperlyConfigured('你有不设置form,又不设置fields字段,那怎么生成表单呢?')
                return modelform_factory(self.model, fields=self.fields)
            else:
                return self.form_class
    

    2.8 save

    保存对象,如果有额外操作,复写此方法。

        def save(self, form):
            if form.has_changed():
                instance = form.save(commit=False)
                instance.save(update_fields=form.changed_data)
    

    3.模板

    {% load static %}
    {% load news_customer_filters %}
    {% load admin_customer_tags %}
    {% load admin_customer_filters %}
    <section class="content-header">
        <h1>
            {{ page_header }}
            <small>{{ page_option }}</small>
        </h1>
    
    </section>
    
    <!-- Main content -->
    <section class="content container-fluid">
        <div class="box">
            <div class="box-header with-border">
                <h3 class="box-title">{{ table_title }}</h3>
            </div>
    
            <!-- /.box-header -->
    
            <div class="box-body">
                <form class="form-horizontal">
                    {% csrf_token %}
                    {% block form_content %}
                        {% for field in form %}
                            {% if field|is_checkbox %}
                                <div class="form-group">
    
                                    <div class="col-sm-offset-1 col-sm-11">
    
                                        <div class="checkbox">
                                            <label for="{{ field.id_for_label }}">{{ field }}{{ field.label }}</label>
                                        </div>
                                    </div>
    
                                </div>
                            {% elif field|is_url_field %}
                                <div class="form-group {% if field.errors %}has-error{% endif %}">
                                    <label for="{{ field.id_for_label }}"
                                           class="col-sm-1 control-label">{{ field.label }}</label>
                                    <div class="col-sm-11">
                                        {% for error in field.errors %}
                                            <label class="control-label"
                                                   for="{{ field.id_for_label }}">{{ error }}</label>
                                        {% endfor %}
                                        <div class="input-group">
                                            {% add_class field 'form-control' %}
                                            <span class="input-group-btn"><input class="hidden" type="file">
                          <button type="button" class="btn btn-info btn-flat">上传文件</button>
                        </span>
                                        </div>
    
                                    </div>
                                </div>
                            {% else %}
                                <div class="form-group {% if field.errors %}has-error{% endif %}">
    
                                    <label for="{{ field.id_for_label }}"
                                           class="col-sm-1 control-label">{{ field.label }}</label>
    
                                    <div class="col-sm-11">
                                        {% for error in field.errors %}
                                            <label class="control-label"
                                                   for="{{ field.id_for_label }}">{{ error }}</label>
                                        {% endfor %}
                                        {% add_class field 'form-control' %}
                                    </div>
                                </div>
                            {% endif %}
                        {% endfor %}
                    {% endblock %}
                </form>
    
    
            </div>
            <div class="box-footer">
    
                <button type="button" class="btn btn-default back">返回</button>
                <button type="button" {% if form.instance.id %}
                        data-url="{% block update_url %}{% endblock %}"
                        data-type="PUT"
                {% else %}
                        data-url="{% block add_url %}{% endblock %}"
                        data-type="POST"
                {% endif %}
                        class="btn btn-primary pull-right save">保存
                </button>
    
    
            </div>
    
        </div>
    </section>
    {% block script %}
        <script>
            $(() => {
                {% block back_button %}
                    // 返回按钮
                    $('.box-footer button.back').click(() => {
                        let url = $('.sidebar-menu li.active a').data('url');
                        if (!url) {
                            return
                        }
                        $('#content').load(
                            url,
                            (response, status, xhr) => {
                                if (status !== 'success') {
                                    message.showError('服务器超时,请重试!')
                                }
                            }
                        );
                    });
                {% endblock %}
    
                {% block save_button %}
                    $('.box-footer button.save').click(function () {
                        let url = $(this).data('url');
                        if (!url) {
                            return
                        }
                        $
                            .ajax({
                                url: url,
                                data: $('form').serialize(),
                                type: $(this).data('type')
                            })
                            .done((res) => {
                                if (res.errno === '0') {
                                    message.showSuccess(res.errmsg);
                                    $('#content').load(
                                        $('.sidebar-menu li.active a').data('url'),
                                        (response, status, xhr) => {
                                            if (status !== 'success') {
                                                message.showError('服务器超时,请重试!')
                                            }
                                        }
                                    );
                                } else {
                                    $('#content').html(res)
                                }
                            })
                            .fail((res) => {
                                message.showError('服务器超时,请重试!')
                            })
                    });
                {% endblock %}
    
                {% block upload %}
                    // 上传文件input
                    let $fileInput = $('.input-group-btn input');
                    let $uploadBtn = $('.input-group-btn button');
                    $uploadBtn.click(function () {
                            $(this).prev('input[type="file"]').click()
                        }
                    );
                    // 自动上传文件
                    $fileInput.change(function () {
                        $this = $(this);
                        if ($this.val() !== '') {
                            let formData = new FormData();
                            formData.append('upload', $this[0].files[0]);
                            formData.append('csrfmiddlewaretoken', $('input[name="csrfmiddlewaretoken"]').val());
                            $
                                .ajax({
                                    url: '/admin/upload/',
                                    // 使用ckeditor_uploader 就使用下面的url
                                    // url: '/ckeditor/upload/&responseType=json',
                                    type: 'POST',
                                    data: formData,
                                    processData: false,
                                    contentType: false
                                })
                                .done((res) => {
                                    if (res.uploaded === '1') {
                                        message.showSuccess('封面图片上传成功!');
                                        $this.parent().prev('input').val(res.url);
                                        // 清空一下
                                        $this.val('')
                                    } else {
                                        message.showError('封面图片上传失败!')
                                    }
                                })
                                .fail(() => {
                                    message.showError('服务器超时, 请重新尝试!')
                                })
                        }
                    });
                {% endblock %}
    
            });
        </script>
    {% endblock %}
    
    <!-- /.content -->
    

    模板中用到了自定义过滤器和自定义标签

    4. 自定义过滤器和自定义标签

    4.1 is_checkbox

    判断字段是否checkbox 类型,决定渲染方式

    from django.template import Library
    from django.forms.widgets import CheckboxInput
    
    register = Library()
    
    
    @register.filter()
    def is_checkbox(field):
        return isinstance(field.field.widget, CheckboxInput)
    

    4.2 is_url_field

    判断字段是否url类型,决定渲染方式

    @register.filter()
    def is_url_field(field):
        return True if 'url' in field.label else False
    

    4.3add_class

    给form字段添加class样式

    from django.template import Library
    from django.shortcuts import reverse
    
    register = Library()
    
    
    @register.simple_tag()
    def add_class(field, class_str):
        return field.as_widget(attrs={'class': class_str})
    

    三、AddView

    1.通用类属性

    class AddView(View):
        model = None
        form_class = None
        template_name = None
        fields = None       # 新建对象需要的字段
        page_header = None  # 页头大标题
        page_option = None  # 页头小标题
        table_title = None
    

    2.方法

    2.1 get

    渲染一个对于模型的表单页面返回。

        def get(self, request):
            context = self.get_context_data()
            return render(request, self.get_template_name(), context=context)
    

    2.2 post

    根据post参数生成表单,校验,创建新对象。

        def post(self, request):
            self.form_class = self.get_form_class()
            form = self.form_class(request.POST)
            if form.is_valid():
                self.save(form)
                return json_response(errmsg='添加数据成功!')
            else:
                context = self.get_context_data(form=form)
    
                return render(request, self.get_template_name(), context=context)
    

    2.3 get_context_data

    获取视图的上下文变量,如果需要额外添加,可以复写次方法。

        def get_context_data(self, **kwargs):
    
            self.form_class = self.get_form_class()
            form = self.form_class()
            context = {
                'form': form,
                'page_header': self.page_header,
                'page_option': self.page_option,
                'table_title': self.table_title
            }
            context.update(kwargs)
            return context
    

    2.4 get_template_name

    获取模板名称,如果不提供类属性template_name,会根据模型名称拼接出默认的模板`myadmin/model_name/model_name_detail.html

        def get_template_name(self):
            """获取模板名"""
            if self.template_name is None:
                self.template_name = 'myadmin/{0}/{0}_detail.html'.format(self.model._meta.model_name)
    
            return self.template_name
    

    2.5 get_form_class

    获取表单类,如果没有提供,通过给定字段属性自动生成

        def get_form_class(self):
            if self.form_class is None:
                if self.fields is None:
                    raise ImproperlyConfigured('你有不设置form,又不设置fields字段,那怎么生成表单呢?')
                return modelform_factory(self.model, fields=self.fields)
            else:
                return self.form_class
    

    2.6 save

    保存对象,如果有额外操作,复写此方法。

        def save(self, form):
            form.save()
    

    3. 模板

    与UpdateView视图一致

    四、继续抽象

    仔细观察上面的三个视图,发现有很多共同的方法,还需要将这些代码进一步的抽离,然后通过继承来达到减少冗余和解耦的作用。

    1.TemplateView

    class TemplateView(View):
        model = None  # 模型
        template_name = None
        page_header = None  # 页头大标题
        page_option = None  # 页头小标题
        table_title = None  # 内容标题
        fields = None  # 需要展示的字段
    
        def get(self, request):
            context = self.get_context_data()
            return render(request, self.get_template_name(), context=context)
    
        def get_context_data(self, **kwargs):
            context = {
                'page_header': self.page_header,
                'page_option': self.page_option,
                'table_title': self.table_title
            }
    
            context.update(kwargs)
            return context
    
        def get_template_name(self):
            """获取模板名"""
            if self.template_name is None:
                if isinstance(self, MyListView):
                    self.template_name = 'myadmin/{0}/{0}_list.html'.format(self.model._meta.model_name)
                else:
                    self.template_name = 'myadmin/{0}/{0}_detail.html'.format(self.model._meta.model_name)
            return self.template_name
    

    2. DetailView

    class DetailView(View):
        form_class = None
    
        def get_form_class(self):
            if self.form_class is None:
                if self.fields is None:
                    raise ImproperlyConfigured('你有不设置form,又不设置fields字段,那怎么生成表单呢?')
                return modelform_factory(self.model, fields=self.fields)
            else:
                return self.form_class
    
        def save(self, form):
            form.save()
    

    3.MyListView

    class MyListView(TemplateView):
    
        is_paginate = False                     # 是否分页
        per_page = None                         # 每页条数
    
        def get_queryset(self):
            """获取查询集,如需过滤,请复写此方法"""
            if self.model is not None:
                queryset = self.model._default_manager.all()
            else:
                raise ImproperlyConfigured(
                    "%(cls)s 是不是傻,你没有指定model,我怎么知道呢?" % {
                        'cls': self.__class__.__name__
                    }
                )
            if self.fields:
                queryset = queryset.only(*self.fields)
            return queryset
    
        def get_context_data(self, **kwargs):
            """获取视图的上下文变量,如要添加额外变量,请继承此方法"""
            queryset = self.get_queryset()
            if self.is_paginate:
                page_size = self.per_page
    
                if page_size:
                    page = self.paginate_queryset(queryset, page_size)
    
                else:
                    page = self.paginate_queryset(queryset, 10)
            else:
                page = queryset
            return super().get_context_data(page_obj=page)
    
    
        def paginate_queryset(self, queryset, page_size):
            """如果需要进行分页"""
            paginator = Paginator(queryset, page_size)
            try:
                page_number = int(self.request.GET.get('page', 1))
            except Exception as e:
                page_number = 1
            page = paginator.get_page(page_number)
            return page
    

    4.UpdateView

    class UpdateView(TemplateView, DetailView):
    
        pk = None           # url路径参数名,默认pk 对象的pk字段
    
        def get(self, request, **kwargs):
            self.obj = self.get_obj(**kwargs)
            return super().get(request)
    
        def put(self, request, **kwargs):
            self.obj = self.get_obj(**kwargs)
            self.form_class = self.get_form_class()
            form = self.form_class(QueryDict(request.body), instance=self.obj)
            if form.is_valid():
                self.save(form)
                return json_response(errmsg='修改数据成功!')
            else:
                context = self.get_context_data(form=form)
    
                return render(request, self.get_template_name(), context=context)
    
        def get_obj_pk(self, **kwargs):
            if self.pk is None:
                self.obj_id = kwargs.get('pk')
            else:
                self.obj_id = kwargs.get(self.pk)
    
        def get_obj(self, **kwargs):
            self.get_obj_pk(**kwargs)
            if self.model is None:
                raise ImproperlyConfigured('没有设置模型')
            obj = self.model.objects.filter(pk=self.obj_id).first()
            if not obj:
                raise ObjectDoesNotExist('找不到pk=%s的对象' % self.obj_id)
            return self.model.objects.filter(pk=self.obj_id).first()
    
        def get_context_data(self, **kwargs):
    
            self.form_class = self.get_form_class()
            form = self.form_class(instance=self.obj)
            context = super().get_context_data(form=form)
            context.update(**kwargs)
            return context
    
        def save(self, form):
            if form.has_changed():
                instance = form.save(commit=False)
                instance.save(update_fields=form.changed_data)
    

    5. AddView

    class AddView(TemplateView, DetailView):
    
        def post(self, request):
            self.form_class = self.get_form_class()
            form = self.form_class(request.POST)
            if form.is_valid():
                self.save(form)
                return json_response(errmsg='添加数据成功!')
            else:
                context = self.get_context_data(form=form)
    
                return render(request, self.get_template_name(), context=context)
    
        def get_context_data(self, **kwargs):
    
            self.form_class = self.get_form_class()
            form = self.form_class()
            context = super().get_context_data(form=form)
            context.update(**kwargs)
            return context
    

    相关文章

      网友评论

          本文标题:django项目--通用视图

          本文链接:https://www.haomeiwen.com/subject/gwpiyctx.html