stark——查看頁面編輯刪除按鈕

1、數據列表

  設計查頁面,主要展現兩部份內容,表頭部分和數據部分, 表頭經過遍歷list_display和默認要顯示的編輯和刪除字段。javascript

一、數據構建

(1)service/stark.py,後臺數據構建

class ModelStark(object):
    """定製配置類"""
    list_display = []

    def __init__(self, model, site):
        self.model = model
        self.site = site
    '''省略其餘代碼'''

    def list_view(self, request):
        print("self.model:", self.model)   # self.model: <class 'app01.models.UserInfo'>
        print("list_display", self.list_display)    # list_display ['pk', 'name', 'age']
        data_list = self.model.objects.all()  # 拿到對應表全部的對象

        new_data_list = []
        for obj in data_list:   # 所查詢表中的一個個對象
            temp = []
            for field in self.list_display:  # field爲一個個字段字符串
                val = getattr(obj, field)   # obj.name  obj.age
                temp.append(val)
          new_data_list.append(temp)

        return render(request, "list_view.html", locals())
        
    '''省略其餘代碼'''

(2)list_view.html模板展現

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.css">
</head>
<body>
<h4>數據列表</h4>
<div class="container">
    <div class="row">
        <div class="col-md-9">
            <table class="table table-bordered table-striped">
                <thead></thead>
                <tbody>
                    {% for data in new_data_list %}
                        <tr>
                            {% for item in data %}
                                <td>{{ item }}</td>
                            {% endfor %}
                        </tr>
                    {% endfor %}

                </tbody>
            </table>
        </div>
    </div>
</div>
</body>
</html>

  顯示效果:css

  

注意:html

(1)因爲UserConfig類是ModelStark類的子類,且兩邊都有list_display變量。

  若是list_display有值就按裏面的字段展現,若是沒有值按照默認的obj展現。java

app01/stark.py:python

# 自定義配置類
class UserConfig(ModelStark):   # UserConfig是ModelStark的一個子類
    list_display = ["pk", "name", "age"]

  根據父類子類關係,從調用者類裏去找x,若是調用者中沒有x,去父類找:jquery

class A(object):
    x = 12

    def func(self):
        print(self.x)

class B(A):
    x = 5


b = B()
b.func()  # 5

(2)字符串找對象的屬性,反射

data_list = self.model.objects.all()  # 拿到對應表全部的對象
new_data_list = []
for obj in data_list:   # 所查詢表中的一個個對象
    temp = []
    for field in self.list_display:  # field爲一個個字段字符串
        val = getattr(obj, field)   # obj.name  obj.age

        temp.append(val)

  new_data_list.append(temp)
 

  字符串不是變量名稱,沒法進行點字符串操做。django

class Person(object):
    def __init__(self, name):
        self.name = name

alex = Person("alex")

s = "name"

# 直接alex.s  或者alex."name"都是取不到值的
print(getattr(alex, s))   # alex

二、編輯按鈕構建

from django.conf.urls import url
from django.shortcuts import HttpResponse,render


class ModelStark(object):
    """定製配置類"""
    list_display = []

    def __init__(self, model, site):
        self.model = model
        self.site = site

    def add(self, request):
        return HttpResponse("add")

    def delete(self, request, id):
        return HttpResponse("delete")

    def change(self, request, id):
        return HttpResponse("change")

    def list_view(self, request):
        print("self.model:", self.model)   # self.model: <class 'app01.models.UserInfo'>

        print("list_display", self.list_display)    # list_display ['pk', 'name', 'age']

        data_list = self.model.objects.all()  # 拿到對應表全部的對象

        new_data_list = []
        for obj in data_list:   # 所查詢表中的一個個對象
            temp = []
            for field in self.list_display:  # field爲一個個字段字符串  ['pk', 'name', 'age', edit]
                if callable(field):   # 用於判斷是不是函數,可調用的是方法,不可調用的是屬性
                    val = field(self, obj)   # edit(self, obj)  obj是當前正在處理的這個記錄
                else:
                    val = getattr(obj, field)   # 必定要是屬性才能這麼去調用, obj.name  obj.age

                temp.append(val)

            new_data_list.append(temp)

        return render(request, "list_view.html", locals())

    def get_urls_2(self):
        temp = []

        # 用name取別名app名+model名+操做名能夠保證別名不會重複
        model_name = self.model._meta.model_name
        app_label = self.model._meta.app_label
        temp.append(url(r"^add/", self.add, name="%s_%s_add" % (app_label, model_name)))
        temp.append(url(r"^(\d+)/delete/", self.delete, name="%s_%s_delete" % (app_label, model_name)))
        temp.append(url(r"^(\d+)/change/", self.change, name="%s_%s_change" % (app_label, model_name)))
        temp.append(url(r"^$", self.list_view, name="%s_%s_list" % (app_label, model_name)))
        return temp

    @property
    def urls_2(self):
        return self.get_urls_2(), None, None  # [], None, None


class StarkSite(object):
    """site單例類"""
    def __init__(self):
        self._registry = {}

    def register(self, model, stark_class=None, **options):
        """註冊"""
        if not stark_class:
            # 若是註冊的時候沒有自定義配置類,執行
            stark_class = ModelStark   # 配置類

        # 將配置類對象加到_registry字典中,鍵爲模型類
        self._registry[model] = stark_class(model, self)   # _registry={'model':admin_class(model)}

    def get_urls(self):
        """構造一層url"""
        temp = []
        for model, stark_class_obj in self._registry.items():
            # model:一個模型表
            # stark_class_obj:當前模型表相應的配置類對象

            model_name = model._meta.model_name
            app_label = model._meta.app_label

            # 分發增刪改查
            temp.append(url(r"^%s/%s/" % (app_label, model_name), stark_class_obj.urls_2))
            """
               path('app01/userinfo/',UserConfig(Userinfo,site).urls2),
               path('app01/book/',ModelStark(Book,site).urls2),
            """

        return temp

    @property
    def urls(self):
        return self.get_urls(), None, None


site = StarkSite()    # 單例對象
/stark/service/stark.py
from app01 import models
from stark.service.stark import site, ModelStark
from django.utils.safestring import mark_safe
from django.urls import reverse


# 自定義配置類
class UserConfig(ModelStark):   # UserConfig是ModelStark的一個子類

    def edit(self, obj):
        # 方法一:
        # return mark_safe("<a href='/stark/app01/userinfo/%s/change'>編輯</a>" % obj.pk)
        # 方法二:前面不加/就是和前面的路徑拼接
        # return mark_safe("<a href='%s/change'>編輯</a>" % obj.pk)
        # 方法三:反向解析
        model_name = self.model._meta.model_name
        app_label = self.model._meta.app_label
        # _url = reverse("%s_%s_add" % (app_label, model_name))
        # print("_url", _url)   # _url /stark/app01/userinfo/add/

        # stark/app01/userinfo/(/d+)/change
        _url = reverse("%s_%s_change" % (app_label, model_name), args=(obj.pk, ))
        print("_url", _url)  # _url /stark/app01/userinfo/3/change/
        return mark_safe("<a href='%s/change'>編輯</a>" % obj.pk)

    def deletes(self, obj):
        model_name = self.model._meta.model_name
        app_label = self.model._meta.app_label
        _url = reverse("%s_%s_delete" % (app_label, model_name), args=(obj.pk, ))
        print("_url", _url)  # _url /stark/app01/userinfo/3/change/
        return mark_safe("<a href='%s/change'>刪除</a>" % obj.pk)

    list_display = ["pk", "name", "age", edit, deletes]


site.register(models.UserInfo, UserConfig)
site.register(models.Book)

print("_registry", site._registry)
app01/stark.py

注意:bootstrap

(1)利用callable方法判斷是函數仍是屬性

if callable(field):   # 用於判斷是不是函數,可調用的是方法,不可調用的是屬性
    val = field(self)
else:
    val = getattr(obj, field)   # 必定要是屬性才能這麼去調用, obj.name  obj.age
temp.append(val)

(2)區分類的實例方法與函數調用及self參數

class Person(object):
    def __init__(self, name):
        self.name = name

    def eat(self):
        print(self)
        print("eat.....")

# 實例方法
egon = Person("egon")
egon.eat()
"""
<__main__.Person object at 0x10401ae48>
eat.....
"""

# 函數
Person.eat(123)
"""
123
eat.....
"""

(3)阻止<a>編輯</a>轉義

from django.utils.safestring import mark_safe

# 自定義配置類
class UserConfig(ModelStark):   # UserConfig是ModelStark的一個子類

    def edit(self):
        return mark_safe("<a>編輯</a>")

    list_display = ["pk", "name", "age", edit]

   顯示效果:app

  

(4)實現點擊編輯進入編輯頁面

  startk/service/stark.py中的list_view函數中,在判斷filed是函數時,給這個函數還傳入一個obj也就是當前正在處理的記錄對象:ide

class ModelStark(object):
    def list_view(self, request):
        for obj in data_list:   # 所查詢表中的一個個對象
            temp = []
            for field in self.list_display:  # field爲一個個字段字符串  ['pk', 'name', 'age', edit]
                if callable(field):   # 用於判斷是不是函數,可調用的是方法,不可調用的是屬性
                    val = field(self, obj)   # edit(self, obj)  obj是當前正在處理的這個記錄
                else:
                    val = getattr(obj, field)   # 必定要是屬性才能這麼去調用, obj.name  obj.age

                temp.append(val)

            new_data_list.append(temp)

   前面已經實現實現了編輯按鈕,如今須要在app01/stark.py中爲edit方法返回值配好返回的a標籤的href路徑:

from app01 import models
from stark.service.stark import site, ModelStark
from django.utils.safestring import mark_safe

# 自定義配置類
class UserConfig(ModelStark):   # UserConfig是ModelStark的一個子類
    def edit(self, obj):
        # 方法一:
        # return mark_safe("<a href='/stark/app01/userinfo/%s/change'>編輯</a>" % obj.pk)
        # 方法二:前面不加/就是和前面的路徑拼接
        return mark_safe("<a href='%s/change'>編輯</a>" % obj.pk)

    list_display = ["pk", "name", "age", edit]

  顯示效果:

  

(5)用反向解析實現路徑返回

   https://www.cnblogs.com/yuanchenqi/articles/7629939.html

  首先給urls用name添加別名:app名+model名+操做名能夠保證別名不重複

class ModelStark(object):
    """定製配置類"""
    '''省略內容'''
    def get_urls_2(self):
        temp = []

        # 用name取別名app名+model名+操做名能夠保證別名不會重複
        model_name = self.model._meta.model_name
        app_label = self.model._meta.app_label
        temp.append(url(r"^add/", self.add, name="%s_%s_add" % (app_label, model_name)))
        temp.append(url(r"^(\d+)/delete/", self.delete, name="%s_%s_delete" % (app_label, model_name)))
        temp.append(url(r"^(\d+)/change/", self.change, name="%s_%s_change" % (app_label, model_name)))
        temp.append(url(r"^$", self.list_view, name="%s_%s_list" % (app_label, model_name)))
        return temp

  路由效果以下所示:

  

  再在app01/stark.py中edit方法以反向解析解析路徑:

from app01 import models
from stark.service.stark import site, ModelStark
from django.utils.safestring import mark_safe
from django.urls import reverse

# 自定義配置類
class UserConfig(ModelStark):   # UserConfig是ModelStark的一個子類
    def edit(self, obj):
        # 方法一:
        # return mark_safe("<a href='/stark/app01/userinfo/%s/change'>編輯</a>" % obj.pk)
        # 方法二:前面不加/就是和前面的路徑拼接
        # return mark_safe("<a href='%s/change'>編輯</a>" % obj.pk)
        # 方法三:反向解析
        model_name = self.model._meta.model_name
        app_label = self.model._meta.app_label
        # _url = reverse("%s_%s_add" % (app_label, model_name))
        # print("_url", _url)   # _url /stark/app01/userinfo/add/

        # stark/app01/userinfo/(/d+)/change
        _url = reverse("%s_%s_change" % (app_label, model_name), args=(obj.pk, ))
        print("_url", _url)  # _url /stark/app01/userinfo/3/change/
        return mark_safe("<a href='%s/change'>編輯</a>" % obj.pk)

    list_display = ["pk", "name", "age", edit]

site.register(models.UserInfo, UserConfig)

  點擊按鈕顯示效果同上。

(6)添加刪除功能

class UserConfig(ModelStark):   # UserConfig是ModelStark的一個子類

    def edit(self, obj):...

    def deletes(self, obj):
        model_name = self.model._meta.model_name
        app_label = self.model._meta.app_label
        _url = reverse("%s_%s_delete" % (app_label, model_name), args=(obj.pk, ))
        print("_url", _url)  # _url /stark/app01/userinfo/3/change/
        return mark_safe("<a href='%s/change'>刪除</a>" % obj.pk)

    list_display = ["pk", "name", "age", edit, deletes]

  顯示效果以下:

  

(7)添加複選框按鈕

def checkbox(self, obj):
    """複選框"""
    return mark_safe("<input type='checkbox'>")

   顯示效果:

  

2、構建表頭並應用於全部列表對象

一、編輯編輯、刪除、複選框函數,同時要實現每一個表都能實現這些操做

class ModelStark(object):
    """默認類,定製配置類"""
    list_display = ["__str__",]

    def __init__(self, model, site):
        self.model = model
        self.site = site

    # 刪除、編輯,複選框
    def edit(self, obj):
        """編輯"""
        # 方法三:反向解析
        model_name = self.model._meta.model_name
        app_label = self.model._meta.app_label
        _url = reverse("%s_%s_change" % (app_label, model_name), args=(obj.pk, ))
        print("_url", _url)
        return mark_safe("<a href='%s/change'>編輯</a>" % obj.pk)

    def deletes(self, obj):
        """刪除"""
        model_name = self.model._meta.model_name
        app_label = self.model._meta.app_label
        _url = reverse("%s_%s_delete" % (app_label, model_name), args=(obj.pk, ))
        print("_url", _url)
        return mark_safe("<a href='%s/change'>刪除</a>" % obj.pk)

    def checkbox(self, obj):
        """複選框"""
        return mark_safe("<input type='checkbox'>")

    '''代碼省略'''

    def new_list_display(self):
        """返回新的列表"""
        temp = []
        temp.append(ModelStark.checkbox)  # 在列表中放一個checkbox名字
        temp.extend(self.list_display)  # 擴展進一個列表["pk","name","age"]
        temp.append(ModelStark.edit)    # edit函數名
        temp.append(ModelStark.deletes)   # deletes函數名

        return temp   # 返回新的列表

    def list_view(self, request):
        """循環展現"""
        print("self.model:", self.model)   # self.model: <class 'app01.models.UserInfo'>

        print("list_display", self.list_display)    # list_display ['pk', 'name', 'age']

        data_list = self.model.objects.all()  # 拿到對應表全部的對象

        """構建表單數據"""
        new_data_list = []

        for obj in data_list:
            temp = []

            for field in self.new_list_display():   # ["__str__", ]   ["pk","name","age",edit]

                if callable(field):
                    val = field(self, obj)
                else:
                    val = getattr(obj, field)

                temp.append(val)

            new_data_list.append(temp)

        return render(request, "list_view.html", locals())

(1)不一樣的表都須要有這些按鈕功能

  將這些函數從自定義配置類(app01/stark.py裏的UserConfig)剪切到默認類(stark/service/stark.py裏的ModelStark),剩下的app01/stark.py代碼以下所示:

from app01 import models
from stark.service.stark import site, ModelStark

class UserConfig(ModelStark):   # UserConfig是ModelStark的一個子類
    """自定義配置類"""
    list_display = ["pk", "name", "age"]

site.register(models.UserInfo, UserConfig)


class BookConfig(ModelStark):
    list_display = ['pk', 'title']

site.register(models.Book)

print("_registry", site._registry)

(2)self.list_display裏如今只剩下普通字段,須要拼接出新的列表

  能夠注意到自定義配置類的list_display已經沒有了edit,delete等函數, 所以須要返回新的列表。

class ModelStark(object):
    '''省略代碼''''
    def new_list_display(self):
        """返回新的列表"""
        temp = []
        temp.append(ModelStark.checkbox)  # 在列表中放一個checkbox名字
        temp.extend(self.list_display)  # 擴展進一個列表["pk","name","age"]
        temp.append(ModelStark.edit)    # edit函數名
        temp.append(ModelStark.deletes)   # deletes函數名

        return temp   # 返回新的列表

  在list_view中調用新的的列表:

def list_view(self, request):
    """構建表單數據"""
    new_data_list = []
    for obj in data_list:
        temp = []
        for field in self.new_list_display():   # ["__str__", ]   ["pk","name","age",edit]
            if callable(field):
                val = field(self, obj)
            else:
                val = getattr(obj, field)
            temp.append(val)
        new_data_list.append(temp)
    return render(request, "list_view.html", locals())

(3)不一樣的表具備不一樣的自定義配置類,每一個的list_display都不相同,對應表取對應的list_display

##################stark/service/stark.py###############
class ModelStark(object):
    """默認類,定製配置類"""
    list_display = ["__str__",]


##################app01/stark.py##################
class UserConfig(ModelStark):   # UserConfig是ModelStark的一個子類
    """自定義配置類"""
    list_display = ["pk", "name", "age"]

class BookConfig(ModelStark):
    list_display = ['pk', 'title']

  這裏涉及到類的__str__方法使用,示例以下:

class Persoon(object):

    def __init__(self, name):
        self.name = name

    def __str__(self):
        return self.name


alex = Persoon("alex")
print(alex.__str__)
print(alex.__str__())
print(str(alex))
"""'
<bound method Persoon.__str__ of <__main__.Persoon object at 0x10401ae48>>
alex
alex
"""

(4)根據models.py中模型是否具備def __str__(self),頁面上字段顯示不一樣

  

  

二、構建表頭

# -*- coding:utf-8 -*-
__author__ = 'Qiushi Huang'


from django.conf.urls import url
from django.shortcuts import HttpResponse, render
from django.utils.safestring import mark_safe
from django.urls import reverse


class ModelStark(object):
    """默認類,定製配置類"""
    list_display = ["__str__",]

    def __init__(self, model, site):
        self.model = model
        self.site = site

    # 刪除、編輯,複選框
    def edit(self, obj=None, header=False):
        """編輯"""
        if header:
            # 若是是表頭顯示操做
            return "操做"

        # 方法三:反向解析
        model_name = self.model._meta.model_name
        app_label = self.model._meta.app_label
        _url = reverse("%s_%s_change" % (app_label, model_name), args=(obj.pk, ))
        print("_url", _url)
        return mark_safe("<a href='%s/change'>編輯</a>" % obj.pk)

    def deletes(self, obj=None, header=False):
        """刪除"""
        if header:
            # 若是是表頭顯示操做
            return "操做"
        model_name = self.model._meta.model_name
        app_label = self.model._meta.app_label
        _url = reverse("%s_%s_delete" % (app_label, model_name), args=(obj.pk, ))
        print("_url", _url)
        return mark_safe("<a href='%s/change'>刪除</a>" % obj.pk)

    def checkbox(self, obj=None, header=False):
        """複選框"""
        if header:
            # 若是是表頭顯示操做
            return mark_safe("<input id='choice' type='checkbox'>")

        return mark_safe("<input class='choice_item' type='checkbox'>")

    def add(self, request):
        return HttpResponse("add")

    def delete(self, request, id):
        return HttpResponse("delete")

    def change(self, request, id):
        return HttpResponse("change")

    def new_list_display(self):
        """返回新的列表"""
        temp = []
        temp.append(ModelStark.checkbox)  # 在列表中放一個checkbox名字
        temp.extend(self.list_display)  # 擴展進一個列表["pk","name","age"]
        temp.append(ModelStark.edit)    # edit函數名
        temp.append(ModelStark.deletes)   # deletes函數名

        return temp   # 返回新的列表

    def list_view(self, request):
        """循環展現"""
        print("self.model:", self.model)   # self.model: <class 'app01.models.UserInfo'>

        print("list_display", self.list_display)    # list_display ['pk', 'name', 'age']   list_display ['__str__']

        data_list = self.model.objects.all()  # 拿到對應表全部的對象

        """構建表頭"""
        header_list = []
        print("header", self.new_list_display())   # [checkbox ,"__str__", edit ,deletes]

        for field in self.new_list_display():

            if callable(field):
                # 若是是函數
                val = field(self, header=True)
                header_list.append(val)

            else:
                # 若是是字符串
                if field == "__str__":
                    header_list.append(self.model._meta.model_name.upper())  # 當前模型表名
                else:
                    # 若是不是"__str__"
                    # header_list.append(field)
                    val = self.model._meta.get_field(field).verbose_name
                    header_list.append(val)


        """構建表單數據"""
        new_data_list = []

        for obj in data_list:
            temp = []

            for field in self.new_list_display():   # ["__str__", ]   ["pk","name","age",edit]

                if callable(field):
                    val = field(self, obj)
                else:
                    val = getattr(obj, field)

                temp.append(val)

            new_data_list.append(temp)

        return render(request, "list_view.html", locals())

    def get_urls_2(self):
        temp = []

        # 用name取別名app名+model名+操做名能夠保證別名不會重複
        model_name = self.model._meta.model_name
        app_label = self.model._meta.app_label
        temp.append(url(r"^add/", self.add, name="%s_%s_add" % (app_label, model_name)))
        temp.append(url(r"^(\d+)/delete/", self.delete, name="%s_%s_delete" % (app_label, model_name)))
        temp.append(url(r"^(\d+)/change/", self.change, name="%s_%s_change" % (app_label, model_name)))
        temp.append(url(r"^$", self.list_view, name="%s_%s_list" % (app_label, model_name)))
        return temp

    @property
    def urls_2(self):
        return self.get_urls_2(), None, None  # [], None, None


class StarkSite(object):
    """site單例類"""
    def __init__(self):
        self._registry = {}

    def register(self, model, stark_class=None, **options):
        """註冊"""
        if not stark_class:
            # 若是註冊的時候沒有自定義配置類,執行
            stark_class = ModelStark   # 配置類

        # 將配置類對象加到_registry字典中,鍵爲模型類
        self._registry[model] = stark_class(model, self)   # _registry={'model':admin_class(model)}

    def get_urls(self):
        """構造一層url"""
        temp = []
        for model, stark_class_obj in self._registry.items():
            # model:一個模型表
            # stark_class_obj:當前模型表相應的配置類對象

            model_name = model._meta.model_name
            app_label = model._meta.app_label

            # 分發增刪改查
            temp.append(url(r"^%s/%s/" % (app_label, model_name), stark_class_obj.urls_2))
            """
               path('app01/userinfo/',UserConfig(Userinfo,site).urls2),
               path('app01/book/',ModelStark(Book,site).urls2),
            """

        return temp

    @property
    def urls(self):
        return self.get_urls(), None, None


site = StarkSite()    # 單例對象
service/stark.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.css">
    <script src="/static/js/jquery-1.12.4.min.js"></script>
</head>
<body>
<h4>數據列表</h4>
<div class="container">
    <div class="row">
        <div class="col-md-9">
            <table class="table table-bordered table-striped">
                <thead>
                    <tr>
                        {% for item in header_list %}
                            <th>{{ item }}</th>
                        {% endfor %}
                    </tr>
                </thead>
                <tbody>
                    {% for data in new_data_list %}
                        <tr>
                            {% for item in data %}
                                <td>{{ item }}</td>
                            {% endfor %}
                        </tr>
                    {% endfor %}

                </tbody>
            </table>
        </div>
    </div>
</div>
<script>
    // 複選框全選
    $("#choice").click(function () {
        if($(this).prop("checked")) {
            // 若是是選中狀態
            $(".choice_item").prop("checked", true);
        } else {
            $(".choice_item").prop("checked", false)
        }
    })
</script>
</body>
</html>
list_view.html

(1)__name__

  __name__是標識模塊的名字的一個系統變量;__main__通常做爲函數的入口,相似於C語言,尤爲在大型工程中,經常有if __name__ == "__main__":來代表整個工程開始運行的入口。

def foo():
    return

print(foo.__name__)   # foo

(2)將表頭自定義函數顯示改成中文

def list_view(self, request):

    """構建表頭"""
    header_list = []
    print("header", self.new_list_display())   # [checkbox ,"__str__", edit ,deletes]

    for field in self.new_list_display():

        if callable(field):
            # 若是是函數
            val = field(self, header=True)
            header_list.append(val)

        else:
            # 若是是字符串
            if field == "__str__":
                header_list.append(self.model._meta.model_name.upper())  # 當前模型表名
            else:
                # 若是不是"__str__"
                header_list.append(field)

   當callable判斷field是函數時,給函數傳參數header=True。修改編輯、刪除、選擇函數:

# 刪除、編輯,複選框
def edit(self, obj=None, header=False):
    """編輯"""
    if header:
        # 若是是表頭顯示操做
        return "操做"

    # 方法三:反向解析
    model_name = self.model._meta.model_name
    app_label = self.model._meta.app_label
    _url = reverse("%s_%s_change" % (app_label, model_name), args=(obj.pk, ))
    print("_url", _url)
    return mark_safe("<a href='%s/change'>編輯</a>" % obj.pk)

def deletes(self, obj=None, header=False):
    """刪除"""
    if header:
        # 若是是表頭顯示操做
        return "操做"
    model_name = self.model._meta.model_name
    app_label = self.model._meta.app_label
    _url = reverse("%s_%s_delete" % (app_label, model_name), args=(obj.pk, ))
    print("_url", _url)
    return mark_safe("<a href='%s/change'>刪除</a>" % obj.pk)

def checkbox(self, obj=None, header=False):
    """複選框"""
    if header:
        # 若是是表頭顯示操做
        return "選擇"

    return mark_safe("<input type='checkbox'>")

  顯示效果:

  

(3)將普通字段修改成中文

def list_view(self, request):
    """構建表頭"""
    header_list = []
    print("header", self.new_list_display())   # [checkbox ,"__str__", edit ,deletes]
    for field in self.new_list_display():
        if callable(field):
            # 若是是函數
            val = field(self, header=True)
            header_list.append(val)
        else:
            # 若是是字符串
            if field == "__str__":
                header_list.append(self.model._meta.model_name.upper())  # 當前模型表名
            else:
                # 若是不是"__str__"
                # header_list.append(field)
                val = self.model._meta.get_field(field).verbose_name
                header_list.append(val)

  而後在models.py中爲字段添加verbose_name屬性

class UserInfo(models.Model):
    name = models.CharField(verbose_name="姓名", max_length=32)
    age = models.IntegerField(verbose_name="年齡")
    def __str__(self):
        return self.name

class Book(models.Model):
    title = models.CharField(verbose_name="書名",max_length=32)
    def __str__(self):
        return self.title

  顯示效果:

  

  注意在這裏app01/stark.py中的list_display是不能添加「pk」的

class UserConfig(ModelStark):   # UserConfig是ModelStark的一個子類
    """自定義配置類"""
    list_display = ["name", "age"]

site.register(models.UserInfo, UserConfig)

class BookConfig(ModelStark):
    list_display = ['title']

site.register(models.Book)
print("_registry", site._registry)

  由於它的主鍵是"id",「pk」只能是在查詢的時候使用。且若是添加「id」的話,這個值也沒法改成中文。

class UserConfig(ModelStark):   # UserConfig是ModelStark的一個子類
    """自定義配置類"""
    list_display = ["id", "name", "age"]

   顯示效果:

  

(4)複選框點擊全選事件

  將表頭改成複選框,並給一個id:

def checkbox(self, obj=None, header=False):
    """複選框"""
    if header:
        # 若是是表頭顯示操做
        return mark_safe("<input id='choice' type='checkbox'>")

    return mark_safe("<input class='choice_item' type='checkbox'>")

  複選框點擊全選事件:

<script>
    // 複選框全選
    $("#choice").click(function () {
        if($(this).prop("checked")) {
            // 若是是選中狀態
            $(".choice_item").prop("checked", true);
        } else {
            $(".choice_item").prop("checked", false)
        }
    })
</script>

  注意這裏使用js中的prop()方法來查看複選框是否選中,或設置複選框爲選中或未選中狀態。

  

3、設計list_display_links

一、定製列能夠點擊跳轉

class ModelStark(object):
    '''其餘代碼省略'''
    def new_list_display(self):
        """返回新的列表"""
        temp = []
        temp.append(ModelStark.checkbox)  # 在列表中放一個checkbox名字
        temp.extend(self.list_display)  # 擴展進一個列表["pk","name","age"]

        if not self.list_display_links:
            # 若是沒有值
            temp.append(ModelStark.edit)

        # temp.append(ModelStark.edit)    # edit函數名
        temp.append(ModelStark.deletes)   # deletes函數名

        return temp   # 返回新的列表

    def list_view(self, request):
        """循環展現"""
        print("self.model:", self.model)   # self.model: <class 'app01.models.UserInfo'>

        print("list_display", self.list_display)    # list_display ['pk', 'name', 'age']   list_display ['__str__']

        data_list = self.model.objects.all()  # 拿到對應表全部的對象

        """構建表頭"""
        header_list = []
        print("header", self.new_list_display())   # [checkbox ,"__str__", edit ,deletes]

        for field in self.new_list_display():

            if callable(field):
                # 若是是函數
                val = field(self, header=True)
                header_list.append(val)

            else:
                # 若是是字符串
                if field == "__str__":
                    header_list.append(self.model._meta.model_name.upper())  # 當前模型表名
                else:
                    # 若是不是"__str__"
                    # header_list.append(field)
                    val = self.model._meta.get_field(field).verbose_name
                    header_list.append(val)

        """構建表單數據"""
        new_data_list = []

        for obj in data_list:
            temp = []

            for field in self.new_list_display():   # ["__str__", ]   ["pk","name","age",edit]

                if callable(field):
                    val = field(self, obj)
                else:
                    val = getattr(obj, field)
                    if field in self.list_display_links:
                        model_name = self.model._meta.model_name
                        app_label = self.model._meta.app_label
                        _url = reverse("%s_%s_change" % (app_label, model_name), args=(obj.pk,))

                        val = mark_safe("<a href='%s'>%s</a>" % (_url, val))

                temp.append(val)

            new_data_list.append(temp)

        return render(request, "list_view.html", locals())
service/stark.py改動的部分

  再也不拼接edit函數名,直接經過點擊普通字段進入編輯頁面。在構建表單數據時,判斷字段是否在list_display_links中,若是在的話經過反向解析生成a標籤指向的地址。

  再在app01/stark.py的自定義配置類添加list_display_links:

class UserConfig(ModelStark):   # UserConfig是ModelStark的一個子類
    """自定義配置類"""
    list_display = ["id", "name", "age"]
    list_display_links = ["name"]


site.register(models.UserInfo, UserConfig)


class BookConfig(ModelStark):
    list_display = ['title']
    list_display_links = ["title"]

  顯示效果:

  

二、將獲取的應用名、模型名組成url定義爲函數

class ModelStark(object):
    def new_list_display(self):
        """返回新的列表"""
        temp = []
        temp.append(ModelStark.checkbox)  # 在列表中放一個checkbox名字
        temp.extend(self.list_display)  # 擴展進一個列表["pk","name","age"]

        if not self.list_display_links:
            # 若是沒有值
            temp.append(ModelStark.edit)

        # temp.append(ModelStark.edit)    # edit函數名
        temp.append(ModelStark.deletes)   # deletes函數名

        return temp   # 返回新的列表

    def get_change_url(self,obj):
        model_name = self.model._meta.model_name
        app_label = self.model._meta.app_label

        _url = reverse("%s_%s_change" % (app_label, model_name), args=(obj.pk,))

        return _url

    def get_delete_url(self, obj):
        model_name = self.model._meta.model_name
        app_label = self.model._meta.app_label

        _url = reverse("%s_%s_delete" % (app_label, model_name), args=(obj.pk,))

        return _url

    def get_add_url(self):
        model_name = self.model._meta.model_name
        app_label = self.model._meta.app_label

        _url = reverse("%s_%s_add" % (app_label, model_name))

        return _url

    def get_list_url(self):.....

  將刪除、編輯、複選框等函數內的url拼接代碼替換後:

# -*- coding:utf-8 -*-
__author__ = 'Qiushi Huang'


from django.conf.urls import url
from django.shortcuts import HttpResponse, render
from django.utils.safestring import mark_safe
from django.urls import reverse


class ModelStark(object):
    """默認類,定製配置類"""
    list_display = ["__str__",]
    list_display_links = []

    def __init__(self, model, site):
        self.model = model
        self.site = site

    # 刪除、編輯,複選框
    def edit(self, obj=None, header=False):
        """編輯"""
        if header:
            # 若是是表頭顯示操做
            return "操做"

        _url = self.get_change_url(obj)
        return mark_safe("<a href='%s'>編輯</a>" % _url)

    def deletes(self, obj=None, header=False):
        """刪除"""
        if header:
            # 若是是表頭顯示操做
            return "操做"

        _url = self.get_delete_url(obj)
        # return mark_safe("<a href='%s/change'>刪除</a>" % obj.pk)
        return mark_safe("<a href='%s/'>刪除</a>" % _url)

    def checkbox(self, obj=None, header=False):
        """複選框"""
        if header:
            # 若是是表頭顯示操做
            return mark_safe("<input id='choice' type='checkbox'>")

        return mark_safe("<input class='choice_item' type='checkbox'>")

    def add_view(self, request):
        return HttpResponse("add")

    def delete_view(self, request, id):
        return HttpResponse("delete")

    def change_view(self, request, id):
        return HttpResponse("change")

    def new_list_display(self):
        """返回新的列表"""
        temp = []
        temp.append(ModelStark.checkbox)  # 在列表中放一個checkbox名字
        temp.extend(self.list_display)  # 擴展進一個列表["pk","name","age"]

        if not self.list_display_links:
            # 若是沒有值
            temp.append(ModelStark.edit)

        # temp.append(ModelStark.edit)    # edit函數名
        temp.append(ModelStark.deletes)   # deletes函數名

        return temp   # 返回新的列表

    def get_change_url(self,obj):
        model_name = self.model._meta.model_name
        app_label = self.model._meta.app_label

        _url = reverse("%s_%s_change" % (app_label, model_name), args=(obj.pk,))

        return _url

    def get_delete_url(self, obj):
        model_name = self.model._meta.model_name
        app_label = self.model._meta.app_label

        _url = reverse("%s_%s_delete" % (app_label, model_name), args=(obj.pk,))

        return _url

    def get_add_url(self):

        model_name = self.model._meta.model_name
        app_label = self.model._meta.app_label

        _url = reverse("%s_%s_add" % (app_label, model_name))

        return _url

    def get_list_url(self):

        model_name = self.model._meta.model_name
        app_label = self.model._meta.app_label

        _url = reverse("%s_%s_list" % (app_label, model_name))

        return _url

    def list_view(self, request):
        """循環展現"""
        print("self.model:", self.model)   # self.model: <class 'app01.models.UserInfo'>

        print("list_display", self.list_display)    # list_display ['pk', 'name', 'age']   list_display ['__str__']

        data_list = self.model.objects.all()  # 拿到對應表全部的對象

        """構建表頭"""
        header_list = []
        print("header", self.new_list_display())   # [checkbox ,"__str__", edit ,deletes]

        for field in self.new_list_display():

            if callable(field):
                # 若是是函數
                val = field(self, header=True)
                header_list.append(val)

            else:
                # 若是是字符串
                if field == "__str__":
                    header_list.append(self.model._meta.model_name.upper())  # 當前模型表名
                else:
                    # 若是不是"__str__"
                    # header_list.append(field)
                    val = self.model._meta.get_field(field).verbose_name
                    header_list.append(val)


        """構建表單數據"""
        new_data_list = []

        for obj in data_list:
            temp = []

            for field in self.new_list_display():   # ["__str__", ]   ["pk","name","age",edit]

                if callable(field):
                    val = field(self, obj)
                else:
                    val = getattr(obj, field)
                    if field in self.list_display_links:
                        # _url = reverse("%s_%s_change" % (app_label, model_name), args=(obj.pk,))
                        _url = self.get_change_url(obj)

                        val = mark_safe("<a href='%s'>%s</a>" % (_url, val))

                temp.append(val)

            new_data_list.append(temp)

            # 構建一個查看url
            add_url = self.get_add_url()

        return render(request, "list_view.html", locals())

    def get_urls_2(self):
        temp = []

        # 用name取別名app名+model名+操做名能夠保證別名不會重複
        model_name = self.model._meta.model_name
        app_label = self.model._meta.app_label
        temp.append(url(r"^add/", self.add_view, name="%s_%s_add" % (app_label, model_name)))
        temp.append(url(r"^(\d+)/delete/", self.delete_view, name="%s_%s_delete" % (app_label, model_name)))
        temp.append(url(r"^(\d+)/change/", self.change_view, name="%s_%s_change" % (app_label, model_name)))
        temp.append(url(r"^$", self.list_view, name="%s_%s_list" % (app_label, model_name)))
        return temp

    @property
    def urls_2(self):
        return self.get_urls_2(), None, None  # [], None, None


class StarkSite(object):
    """site單例類"""
    def __init__(self):
        self._registry = {}

    def register(self, model, stark_class=None, **options):
        """註冊"""
        if not stark_class:
            # 若是註冊的時候沒有自定義配置類,執行
            stark_class = ModelStark   # 配置類

        # 將配置類對象加到_registry字典中,鍵爲模型類
        self._registry[model] = stark_class(model, self)   # _registry={'model':admin_class(model)}

    def get_urls(self):
        """構造一層url"""
        temp = []
        for model, stark_class_obj in self._registry.items():
            # model:一個模型表
            # stark_class_obj:當前模型表相應的配置類對象

            model_name = model._meta.model_name
            app_label = model._meta.app_label

            # 分發增刪改查
            temp.append(url(r"^%s/%s/" % (app_label, model_name), stark_class_obj.urls_2))
            """
               path('app01/userinfo/',UserConfig(Userinfo,site).urls2),
               path('app01/book/',ModelStark(Book,site).urls2),
            """

        return temp

    @property
    def urls(self):
        return self.get_urls(), None, None


site = StarkSite()    # 單例對象
service/stark.py
相關文章
相關標籤/搜索