stark 增删改

  • 优雅装饰器
import functools

def wrapper(func):
    @functools.wraps(func)
    # 保留原函数的信息
    def inner(*args, **kwargs):
        return func(*args, **kwargs)
    return inner
@wrapper
def f1():
    print('f1')

@wrapper
def f2():
    print('f1')

print(f1.__name__)
print(f2.__name__)
"""
之前
inner
inner
"""


"""
之后
f1
f2
"""
装饰器保留原函数的信息

  • 判断是函数,还是变量
    判断arg是函数则打印1,arg是方法则打印2
from types import MethodType,FunctionType
def check(arg):
    """
    判断arg是函数则打印1,arg是方法则打印2
    :param arg:
    :return:
    """
    if isinstance(arg,MethodType):
        print(2)
    elif isinstance(arg,FunctionType):
        print(1)
    else:
        print('不认识')

def func():
    pass

class Foo(object):
    def display(self):
        pass

check(func)
check(Foo.display)
check(Foo().display)

"""
1
1
2
"""
from types import MethodType,FunctionType

  • 类传变量的一种方式

   实例方法传参,要传实例对象本身

class RoleConfig(object):

    def f1(self, arg):
        print('f1', arg)

    def f2(self, arg):
        print('f2', arg)

    list_display = [f1, f2]


obj = RoleConfig()
for item in RoleConfig.list_display:
    item(obj, 2)
 # obj就是self,实例变量本身
    # 传变量的一种方式
view


  • 利用列表储存函数对象
   一个进程两次调用类变量
class RoleConfig(object):

    def f1(self, arg):
        print('f1', arg)

    def f2(self, arg):
        print('f2', arg)

    def f3(self, arg):
        print('f3', arg)

    list_display = [f1, f2]

    def get_list_display(self):
        self.list_display.insert(0, RoleConfig.f3)
        return self.list_display
obj1 = RoleConfig()
for item in obj1.get_list_display():
    item(obj1, 2)   # 刚开始这时候列表里还没有,加进f3,

obj2 = RoleConfig()
for item in obj2.get_list_display():
    print('obj2----')
    item(obj2, 6)   # 这时候列表里有了f3,再插入一个f3反回。所以此处列表里有四个


# 利用类的变量列表,储存对象
# 一个进程对类操作了两次
"""
f3 2
f1 2
f2 2
f3 6
f3 6
f1 6
f2 6
"""
view
class RoleConfig(object):

    def f1(self, arg):
        print('f1', arg)

    def f2(self, arg):
        print('f2', arg)

    def f3(self, arg):
        print('f3', arg)

    list_display = [f1, f2]

    def get_list_display(self):
        v = []
        v.extend(self.list_display)
        v.insert(0, RoleConfig.f3)
        return v


obj1 = RoleConfig()#[f1,f2]
for item in obj1.get_list_display():# [f3,f1,f2]
    item(obj1, 2)

    print('---------------')
    obj2 = RoleConfig()#[f1,f2]
    for item in obj2.get_list_display(): #[f3,f1,f2]
        item(obj2, 6)
    print('+++++')

"""
f3 2
---------------
f3 6
f1 6
f2 6
+++++
f1 2
---------------
f3 6
f1 6
f2 6
+++++
f2 2
---------------
f3 6
f1 6
f2 6
+++++
"""
view


  • 利用yield取数据
不要一次性取出来,占内存
   以前的:
      def func(request):
         result = []

         data_list = models.Users.objects.all()
         for row in data_list:
            temp = "%s%s" (row.name,row.pwd,)
            result.append(temp)

         return render(request,'xxx.html',{'result':result})

      xxx.html

         {% for row in result %}
            {{row}}
         {% endfor%}

   现在的:

      def get_result(data_list):
         for row in data_list:
            temp = "%s%s" (row.name,row.pwd,)
            yield temp

      def func(request):

         data_list = models.Users.objects.all()
         result = get_result(data_list)

         return render(request,'xxx.html',{'result':result})

      xxx.html
         {# 生成器,不断去调用#}
         {% for row in result %}
            {{row}}
         {% endfor%}
view


复选框实现

  • 复选框函数 mark_safe
def display_checkbox(self, row=None, header=False):
    # 选择框功能             默认None,表头   如果是表头,则显示相应字段
    if header:
        return "选择"  # 表头第一个字段,可以自定制
    return mark_safe("<input type='checkbox' name='pk' value='%s' />" % row.pk)
    #     安全渲染****                                   选中行数据pk
view
  • 复选框函数实现与显示

调用复选框函数,拿到标签渲染

def changelist_view(self, request):
    # 所有URL的查看列表页面
    # 获取表所有数据
    queryset = self.model_class.objects.all().order_by(*self.get_order_by())

    # 要显示的字段
    list_display = self.list_display

    header_list = []  # 表头列表
    if list_display:  # 判断有没有显示字段
        for name_or_func in list_display:
            if isinstance(name_or_func, FunctionType):  # 判断是不是函数,是则执行
                verbose_name = name_or_func(self, header=True)
            else:  # 不是函数,则按规则去取字段的名称
                verbose_name = self.model_class._meta.get_field(name_or_func).verbose_name
            header_list.append(verbose_name)
    else:  # 没有显示字段列表,取表名作为表头
        header_list.append(self.model_class._meta.model_name)

    body_list = []  # 表体列表
    for row in queryset:  # 从查找到的queryset对象里取
        row_list = []  # 行列表
        if not list_display:  # 没有规定显示的字段
            row_list.append(row)  # 直接将一条queryset 放到行列表里面
            body_list.append(row_list)  # 再放到表体
            continue
        for name_or_func in list_display:  # 按照要显示的字段,取数据,遇到函数就执行显示复选框,并返回该行对象
            if isinstance(name_or_func, FunctionType):  # 判断是否是功能函数
                val = name_or_func(self, row=row)  # 执行函数反回功能内容
            else:  # 其他字段的数据正常取
                val = getattr(row, name_or_func)  # getattr 映射 每个要显示字段名 ,取queryset里面的字段值
            row_list.append(val)  # 添加到行
        body_list.append(row_list)  # 添加到表体
    #  反回渲染页面
    return render(request, 'stark/changelist.html', {'header_list': header_list, 'body_list': body_list})
view
  • 前端页面

    循环取值

<div>
    <table class="table table-bordered"> {# 基于bootstrap 创建table表 #}
        <thead>  {# 表头 #}
            <tr>
                {% for item in header_list %}
                <th>{{ item }}</th>
                {% endfor %}
            </tr>
        </thead>
        <tbody>   {# 表体 #}
            {% for row_list in body_list %}
            <tr>
                {% for col in row_list %}
                    <td>{{ col }}</td>
                {% endfor %}

            </tr>
            {% endfor %}
        </tbody>
    </table>

</div>
view
  • 自定义的配置类
from stark.service.stark import site, StarkConfig
from app01 import models

site.register(models.UserInfo)


class DepartConfig(StarkConfig):
    # 自定义的配置类
    list_display = [StarkConfig.display_checkbox,'id', 'name', 'user']
    #        自定义的显示字段

site.register(models.Depart, DepartConfig)
view




编辑删除功能函数实现

利用函数封装名称标签,组装表每行时 Functiontype判断,取不同值放入row_list
def display_edit(self, row=None, header=False):
    if header:
        return "编辑"

    return mark_safe('<a href="%s"><i class="fa fa-edit" aria-hidden="true"></i></a></a>' % self.reverse_edit_url(row))

def display_del(self, row=None, header=False):
    if header:
        return "删除"

    return mark_safe('<a href="%s"><i class="fa fa-trash-o" aria-hidden="true"></i></a>' % self.reverse_del_url(row))

def display_edit_del(self, row=None, header=False):
    if header:
        return "操作"
    tpl = """<a href="%s"><i class="fa fa-edit" aria-hidden="true"></i></a></a> |
    <a href="%s"><i class="fa fa-trash-o" aria-hidden="true"></i></a>
    """ %(self.reverse_edit_url(row),self.reverse_del_url(row),)
    return mark_safe(tpl)
list display function


前端循环取组装好的列表里面的值即可
{% block content %}
    <div>
        {% if add_btn %}
        <div style="margin: 5px 0;">
            {{ add_btn }}
        </div>
        {% endif %}
        <table class="table table-bordered">
            <thead>
                <tr>
                    {% for item in header_list %}
                    <th>{{ item }}</th>
                    {% endfor %}
                </tr>
            </thead>
            <tbody>
                {% for row_list in body_list %}
                <tr>
                    {% for col in row_list %}
                        <td>{{ col }}</td>
                    {% endfor %}
                </tr>
                {% endfor %}
            </tbody>
        </table>
    </div>
{% endblock %}
view

添加数据功能实现

modeform 实现表单更改验证

model_form_class = None


def get_add_btn(self):
    return mark_safe('<a href="%s" class="btn btn-success">添加</a>' % self.reverse_add_url())



def get_model_form_class(self):
    """
    获取ModelForm类  # 用于编辑 和 添加数据的表单 
       :return: #根据是否有自定义配置,返回不同表单
    """
    if self.model_form_class:
        return self.model_form_class  #    其他表的配置,如果有自定义的表单则返回自定义的

    class AddModelForm(forms.ModelForm):       # 添加功能的表单,所有数据都需要填写,所以默认所有字段都要
        class Meta:
            model = self.model_class
            fields = "__all__"

    return AddModelForm


ModelForm


def changelist_view(self, request):
    """
    所有URL的查看列表页面 # 将添加按钮功能,添加到这页面视图
    :param request:
    :return:
    """
    queryset = self.model_class.objects.all().order_by(*self.get_order_by())

    # ##### 添加按钮 ######
    add_btn = self.get_add_btn()
    ......


def add_view(self, request):
    """
    所有添加页面,都在此函数处理
    使用ModelForm实现
    :param request:
    :return:
    """
    AddModelForm = self.get_model_form_class()
    if request.method == "GET":
        form = AddModelForm()
        return render(request, 'stark/change.html', {'form':form})

    form = AddModelForm(request.POST) # 校验数据
    if form.is_valid():
        form.save()                 # 保存
        return redirect(self.reverse_list_url())   # 添加完反回主页面
    return render(request, 'stark/change.html', {'form': form})
add_view


class AdminSite(object):
    def __init__(self):
        self._registry = {}
        self.app_name = 'stark'
        self.namespace = 'stark'

    def register(self, model_class, stark_config=None):
        """
        注册表类
        :param model_class: 表类class
        :param stark_config: 自定义配置
        :return:
        """
        if not stark_config:
            stark_config = StarkConfig

        self._registry[model_class] = stark_config(model_class, self)  # 实例对象传参
              """
        {
            models.UserInfo: StarkConfig(models.UserInfo), # 封装:model_class=UserInfo,site=site对象
            models.Role: RoleConfig(models.Role)           # 封装:model_class=Role,site=site对象
        }
        """

    def get_urls(self):
        # 获取url
        urlpatterns = []  #url 列表

        # urlpatterns.append(url(r'^x3/', ([
        #                                      url(r'^add/', self.x1),
        #                                      url(r'^change/', self.x1),
        #                                      url(r'^del/', self.x1),
        #                                      url(r'^edit/', self.x1),
        #                                  ],None,None)))

        for k, v in self._registry.items():
            # k=modes.UserInfo,v=StarkConfig(models.UserInfo), # 封装:model_class=UserInfo,site=site对象
            # k=modes.Role,v=RoleConfig(models.Role)           # 封装:model_class=Role,site=site对象
            app_label = k._meta.app_label
            model_name = k._meta.model_name
            urlpatterns.append(url(r'^%s/%s/' % (app_label, model_name,), (v.urls, None, None)))
            #                    表类所在app/表类名的组装                   一个表类绑定的操作url
        return urlpatterns

    @property
    def urls(self):
        return self.get_urls(), self.app_name, self.namespace
        #          url列表 
        # 返回的元组

site = AdminSite()

AdminSite


编辑视图函数
def change_view(self, request, pk):
    """
    所有编辑页面
    :param request:
    :param pk: 操作该条数据的pk,路由有设置
    :return:
    """
    obj = self.model_class.objects.filter(pk=pk).first()
    if not obj:
        return HttpResponse('数据不存在')

    ModelFormClass = self.get_model_form_class()
    if request.method == 'GET':
        form = ModelFormClass(instance=obj)    # instance=obj 默认原先的编辑数据
        return render(request,'stark/change.html',{'form':form})
    form = ModelFormClass(data=request.POST,instance=obj)
    if form.is_valid():
        form.save()
        return redirect(self.reverse_list_url())
    return render(request, 'stark/change.html', {'form': form})
编辑视图处理函数
{% block content %}
    <div style="width: 680px;margin: 0 auto;">
        <form class="change" method="post">
            {% csrf_token %}
            {% for filed in form %}
                <div class="form-group">
                    <label>{{ filed.label }}</label>
                    {{ filed }}
                    {{ filed.errors.0 }}
                </div>
            {% endfor %}

            <button type="submit" class="btn btn-default">Submit</button>
        </form>
    </div>
{% endblock %}
编辑前端页面


def delete_view(self, request, pk):
    """
    所有删除页面
    :param request:
    :param pk:
    :return:
    """
    if request.method == "GET":
        return render(request,'stark/delete.html',{'cancel_url':self.reverse_list_url()})
    #                   跳转到确认页面                 # 取消反回的url
    self.model_class.objects.filter(pk=pk).delete()   # 不是GET请求,说明确认删除
    return redirect(self.reverse_list_url())
删除视图处理函数


{% extends 'stark/layout.html' %}
{% block css %}


{% endblock %}
{% block content %}
    <div >
        <form method="post">
            {% csrf_token %}
            <p>是否确定要删除?</p>
            <a href="{{ cancel_url }}" class="btn btn-default">取消</a>
            <button type="submit" class="btn btn-danger">确 认</button>
        </form>
    </div>
{% endblock %}

删除确认页面


def get_urls(self):
    info = self.model_class._meta.app_label, self.model_class._meta.model_name

    urlpatterns = [
        url(r'^list/$', self.wrapper(self.changelist_view), name='%s_%s_changelist' % info),
        url(r'^add/$', self.wrapper(self.add_view), name='%s_%s_add' % info),
        url(r'^(?P<pk>\d+)/change/', self.wrapper(self.change_view), name='%s_%s_change' % info),
        url(r'^(?P<pk>\d+)/del/', self.wrapper(self.delete_view), name='%s_%s_del' % info),
    ]

    extra = self.extra_url()
    if extra:
        urlpatterns.extend(extra)

    return urlpatterns
def extra_url(self):
    pass
每张表类绑定的路由

反向解析,前端提交变更的路由路径

def reverse_list_url(self):
    app_label = self.model_class._meta.app_label
    model_name = self.model_class._meta.model_name
    namespace = self.site.namespace
    name = '%s:%s_%s_changelist' % (namespace, app_label, model_name)
    list_url = reverse(name)
    return list_url

def reverse_add_url(self):
    app_label = self.model_class._meta.app_label
    model_name = self.model_class._meta.model_name
    namespace = self.site.namespace
    name = '%s:%s_%s_add' % (namespace, app_label, model_name)
    add_url = reverse(name)
    return add_url

def reverse_edit_url(self,row):
    app_label = self.model_class._meta.app_label
    model_name = self.model_class._meta.model_name
    namespace = self.site.namespace
    name = '%s:%s_%s_change' % (namespace, app_label, model_name)
    edit_url = reverse(name, kwargs={'pk': row.pk})
    return edit_url

def reverse_del_url(self,row):
    app_label = self.model_class._meta.app_label
    model_name = self.model_class._meta.model_name
    namespace = self.site.namespace
    name = '%s:%s_%s_del' % (namespace, app_label, model_name)
    del_url = reverse(name, kwargs={'pk': row.pk})
    return del_url

@property
def urls(self):
    return self.get_urls()
路由解析



应用配置app01/stark.py
class DepartModelForm(forms.ModelForm):
    class Meta:
        model = models.Depart
        fields = "__all__"

    def clean_name(self):
        return self.cleaned_data['name']


class DepartConfig(StarkConfig):   #继承默认配置类
    list_display = [StarkConfig.display_checkbox, 'id', 'name', 'tel', 'user', StarkConfig.display_edit_del]
    model_form_class = DepartModelForm

    def changelist_view(self, request):
        return HttpResponse('自定义列表页面')


site.register(models.Depart, DepartConfig)
view








注册类入口

class AdminSite(object):
    def __init__(self):
        self._registry = {}
        self.app_name = 'stark'
        self.namespace = 'stark'

    def register(self, model_class, stark_config=None):
        """
        注册表类
        :param model_class: 表类class
        :param stark_config: 自定义配置
        :return:
        """
        if not stark_config:
            stark_config = StarkConfig

        self._registry[model_class] = stark_config(model_class, self)  # 实例对象传参
              """
        {
            models.UserInfo: StarkConfig(models.UserInfo), # 封装:model_class=UserInfo,site=site对象
            models.Role: RoleConfig(models.Role)           # 封装:model_class=Role,site=site对象
        }
        """

    def get_urls(self):
        # 获取url
        urlpatterns = []  #url 列表

        # urlpatterns.append(url(r'^x3/', ([
        #                                      url(r'^add/', self.x1),
        #                                      url(r'^change/', self.x1),
        #                                      url(r'^del/', self.x1),
        #                                      url(r'^edit/', self.x1),
        #                                  ],None,None)))

        for k, v in self._registry.items():
            # k=modes.UserInfo,v=StarkConfig(models.UserInfo), # 封装:model_class=UserInfo,site=site对象
            # k=modes.Role,v=RoleConfig(models.Role)           # 封装:model_class=Role,site=site对象
            app_label = k._meta.app_label
            model_name = k._meta.model_name
            urlpatterns.append(url(r'^%s/%s/' % (app_label, model_name,), (v.urls, None, None)))
            #                    表类所在app/表类名的组装                   一个表类绑定的操作url
        return urlpatterns

    @property
    def urls(self):
        return self.get_urls(), self.app_name, self.namespace
        #          url列表 
        # 返回的元组

site = AdminSite()




class AdminSite


自定义思路
a.有自定义配置类的,重写继承的默认类变量,然后再由类方法自己去调用
b. 在自定义配置类,直接重写继承配置类的默认方法

1. 排序规则

2. 显示列
   第一种方法:
      class UserInfoConfig(StarkConfig):
         list_display = ['id','title',StarkConfig.display_edit,StarkConfig.display_del]
      site.register(models.UserInfo,UserInfoConfig)
   第二种方法:
      class UserInfoConfig(StarkConfig):
         order_by = ['-id']

         def get_list_display(self):
            return  ['id','title',StarkConfig.display_edit,StarkConfig.display_del]
1. 排序规则

3. 添加按钮
      class UserInfoConfig(StarkConfig):
         list_display = ['id','title',StarkConfig.display_edit,StarkConfig.display_del]
         def get_add_btn(self):
            # 显示 
            # return mark_safe('<a href="%s" class="btn btn-success">添加</a>' % self.reverse_add_url())

            # 不显示
            return None

      site.register(models.UserInfo,UserInfoConfig)
3. 添加按钮
4. 定制ModelForm
   第一种方法:
          class DepartModelForm(forms.ModelForm):
         class Meta:
            model = models.Depart
            fields = "__all__"

         def clean_name(self):
            return self.cleaned_data['name']

      class DepartConfig(StarkConfig):
         list_display = [StarkConfig.display_checkbox,'id', 'name', 'tel', 'user',StarkConfig.display_edit_del]
         model_form_class = DepartModelForm
   第二种方法:
          class DepartModelForm(forms.ModelForm):
         class Meta:
            model = models.Depart
            fields = "__all__"

         def clean_name(self):
            return self.cleaned_data['name']

      class DepartConfig(StarkConfig):
         list_display = [StarkConfig.display_checkbox,'id', 'name', 'tel', 'user',StarkConfig.display_edit_del]

         def get_model_form_class(self):

            return DepartModelForm
4. 定制ModelForm

5. 自定义列表页面
   class DepartConfig(StarkConfig):
      list_display = [StarkConfig.display_checkbox,'id', 'name', 'tel', 'user',StarkConfig.display_edit_del]
      model_form_class = DepartModelForm


      def changelist_view(self, request):
         return HttpResponse('自定义列表页面')


   site.register(models.Depart, DepartConfig)

6. 增加URL
   class RoleConfig(StarkConfig):

      order_by = ['-id', ]
      list_display = [StarkConfig.display_checkbox,'id','title',StarkConfig.display_edit,StarkConfig.display_del]

      def extra_url(self):
         data = [
            url(r'^xxxxxxx/$', self.xxxxxx),
         ]

         return data

      def xxxxxx(self,request):
         print('....')

         return HttpResponse('xxxxx')


   site.register(models.Role,RoleConfig)

7. 自定制URL

   class RoleConfig(StarkConfig):

      order_by = ['-id', ]
      list_display = [StarkConfig.display_checkbox,'id','title']


      def get_add_btn(self):
         return False

      def extra_url(self):
         data = [
            url(r'^xxxxxxx/$', self.xxxxxx),
         ]

         return data

      def xxxxxx(self,request):
         print('....')

         return HttpResponse('xxxxx')


      def get_urls(self):
         info = self.model_class._meta.app_label, self.model_class._meta.model_name

         urlpatterns = [
            url(r'^list/$', self.wrapper(self.changelist_view), name='%s_%s_changelist' % info),
         ]

         extra = self.extra_url()
         if extra:
            urlpatterns.extend(extra)

         return urlpatterns

   site.register(models.Role,RoleConfig)
5. 自定义列表页面

posted @ 2018-11-07 19:03  前海渔文乐  阅读(195)  评论(0编辑  收藏  举报