Django基于Admin原理實現(xiàn)的CURD組件

Django基于Admin原理實現(xiàn)的CURD組件


Django管理后臺admin

常用共29個功能: 參考

  1. 在項目的app中的admin.py文件中注冊models類晌该,示例如下:
# cat app_name/admin.py

from django.contrib import admin
from django.contrib.admin import ModelAdmin
from . import models
from django.shortcuts import HttpResponse
from django.forms import ModelForm
from django.forms import fields
from django.forms import widgets

# 用戶表,自定義admin后臺錯誤信息提示
class UserModelForm(ModelForm):
    others = fields.CharField()
    class Meta:
        model = models.UserInfo
        fields = "__all__"
        error_messages = {
            'name':{'required':'用戶名不能問空'}
        }
        
class UserInfoModelAdmin(ModelAdmin):
    # 使用自定義的form表單驗證功能
    form = UserModelForm

    # 1.定義列表頁面,顯示列數(shù)據(jù)
    list_display = ['name','pwd','email']

    def email(self, obj):
        return obj.name + obj.pwd

    email.empty_value_display = "默認(rèn)為空時顯示的值"

    # 2.定義列表頁面,列可以進(jìn)行點擊進(jìn)入編輯頁面
    list_display_links = ['pwd']
    
    # 3.定義列表頁面商蕴,快速搜索
    list_filter = ['ut']
    
    # 4.定義列表頁面,分頁功能
    list_per_page = 10
    
    # 5. 列是否可編輯
    list_editable = ['name']

    # 6. 查詢列
    search_fields = ['name','pwd']

    # 7. 是否在頁面頂端顯示保存按鈕
    # save_on_top = True

    # 8. 下拉選項的批量操作夭禽,類似于批量刪除功能
    def func(self, request, queryset):
        print(self, request, queryset)
        id_list = request.POST.getlist('_selected_action')
        # models.UserInfo.objects.filter(id__in=id_list).delete()

    func.short_description = "批量初始化"

    actions = [func, ]

    # 9. 列表頁面使用模板文件
    change_list_template = ['xxx.html']
    
    # raw_id_fields = ['ut',]
    # fields = ['name']
    # exclude = ['name',]
    
    # 10. 分類展示
    # fieldsets = (
    #     ('基本數(shù)據(jù)', {
    #         'fields': ('name',)
    #     }),
    #     ('其他', {
    #         'classes': ('collapse', 'wide', 'extrapretty'),  # 'collapse','wide', 'extrapretty'
    #         'fields': ('pwd', 'ut'),
    #     }),
    # )

    # 11.快速過濾
    # filter_vertical = ("roles",)
    filter_horizontal = ("roles",)
    
    # 12. 排序
    ordering = ['-id']

# 注冊使用自定義的UserInfoModelAdmin類的頁面展示規(guī)則
admin.site.register(models.UserInfo,UserInfoModelAdmin)


# 2. 用戶類型表(基于ModelAdmin類)
class UserTypeModelAdmin(ModelAdmin):
    list_display = ['title']
    
admin.site.register(models.UserType,UserTypeModelAdmin)     

注: 默認(rèn)使用ModelAdmin類進(jìn)行后臺操作或颊,可以定義自己的calss砸紊,通過繼承ModelAdmin類實現(xiàn)定制頁面展示功能

  1. Django自帶Admin原理
    2.1 每注冊一個model類,Django內(nèi)部會生成4個對應(yīng)的增刪改查URL囱挑,如下所示:
URL:
    /admin/app_name/model_name/
    /admin/app_name/model_name/add/
    /admin/app_name/model_name/1/change/
    /admin/app_name/model_name/1/delete/
    例:/admin/app01/userinfo/

2.2 內(nèi)部實現(xiàn)機(jī)制

  • 在app下面的admin.py文件中注冊models類;
  • Django程序在啟動時會循環(huán)所有app下面的admin文件中注冊的models類醉顽,為每個models類生成對應(yīng)的增刪改查4個URL;
  • 每個注冊的model類會封裝一個用于處理當(dāng)前類所對應(yīng)的URL的view對象,用于處理CURD操作,默認(rèn)為ModelAdmin類對象;
1. self.model=models.UserInfo
/admin/app01/userinfo/                obj1.changelist_view
/admin/app01/userinfo/add/            obj1.add_view
/admin/app01/userinfo/(\d+)/delete/   obj1.delete_view
/admin/app01/userinfo/(\d+)/change/   obj1.change_view

2. self.model=models.UserType
/admin/app01/usertype/                obj2.changelist_view
/admin/app01/usertype/add/            obj2.add_view
/admin/app01/usertype/(\d+)/delete/   obj2.delete_view
/admin/app01/usertype/(\d+)/change/   obj2.change_view
                                                          

</br>

自定義實現(xiàn)CURD類似Admin功能

步驟

  • 了解django啟動時執(zhí)行的啟動文件順序
  • 制作啟動文件
  • settings.py配置文件中注冊啟動文件使全局生效
  • 實現(xiàn)組件CURD業(yè)務(wù)邏輯
  • 主要參考Django Admin的實現(xiàn)平挑,利用單利模式和include原理實現(xiàn)路由分發(fā)

實現(xiàn)

假設(shè)組件app名稱為: arya

  1. Django程序啟動順序
    在程序啟動時游添,django會根據(jù)配置項INSTALLED_APPS中注冊的啟動文件,遍歷每個App下面對應(yīng)的注冊啟動文件,在arya組件下面的app.py文件中實現(xiàn)ready方法激活啟動文件,如下:
# arya/app.py

from django.apps import AppConfig

class AryaConfig(AppConfig):
    name = 'arya'

    # Django啟動時自動掃描所有app下面的arya模塊
    def ready(self):
        from django.utils.module_loading import autodiscover_modules
        autodiscover_modules('arya')
  1. 在項目的setting.py文件中配置通熄,激活組件否淤,使全局生效,此時Django啟動時棠隐,在完全啟動前,便會掃描所有app下面的arya.py文件并加載生效
INSTALLED_APPS = [
    ...
    'arya.apps.AryaConfig',
    ...
]
  1. 核心代碼邏輯實現(xiàn)
# cat arya/seevice/v1.py

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

class AryaConfig(object):
    """
    每個models類的URL對應(yīng)處理的View實現(xiàn)
    """

    def __init__(self, model_class, site):
        self.model_class = model_class
        # View對象
        self.site = site

    @property
    def urls(self):
        partterns = [
            url(r'^$', self.changelist_view),
            url(r'^add/', self.add_view),
            url(r'^(\d+)/change/$', self.change_view),
            url(r'^(\d+)/delete/$', self.delete_view)
        ]
        return partterns

    def changelist_view(self, request):
        """
        列表試圖
        :param request:
        :return:
        """
        # return HttpResponse("列表頁面")
        return render(request, 'arya/changelist.html')

    def add_view(self, request):
        """
        添加試圖
        :param request:
        :return:
        """
        return HttpResponse("添加試圖")

    def change_view(self, request):
        """
        修改試圖
        :param request:
        :return:
        """
        return HttpResponse("修改試圖")

    def delete_view(self, request):
        """
        刪除試圖
        :param request:
        :return:
        """
        return HttpResponse("刪除試圖")


class AryaSite(object):
    """
    實現(xiàn)類似于admin.site.register()功能
    """

    # 存放所有的models類及對應(yīng)處理UTRL的的view對象
    def __init__(self):
        self._registry = {}

    def register(self, class_name, config_class):
        """
        注冊方法,封裝對象
        self._registry = {
            module.UserInfo: obj1,  # obj1 = AryaConfig(models.UserInfo,site),
            module.UserType: obj2,  # obj2 = AryaConfig(models.UserType,site),
        }
        :param class_name: models類
        :param config_class: 對應(yīng)的View類(AryaConfig)
        :return:
        """
        self._registry[class_name] = config_class(class_name, self)

    @property
    def urls(self):
        """
        處理子路由
        :return:
        """
        partterns = [
            url(r'^login/$', self.login),
            url(r'^logout/$', self.logout),
        ]
        # 循環(huán)self._registry屬性里面的每一個元素檐嚣,key為models類助泽,value為URLS對應(yīng)處理的類obj對象
        for model_class, arya_config_obj in self._registry.items():
            # 分別為app名稱和models的類名稱
            print("*" * 50)
            print(model_class._meta.app_label, model_class._meta.model_name)
            app_model_name_urls = r'^{0}/{1}/'.format(model_class._meta.app_label, model_class._meta.model_name)
            # arya_config_obj.urls self._registry字典中存放的values對象obj下面的urls方法
            pt = url(app_model_name_urls, (arya_config_obj.urls, None, None))
            partterns.append(pt)
        # 3元組
        return partterns, None, None

    def login(self):
        """
        登陸
        :return:
        """
        return redirect('login')

    def logout(self):
        """
        退出
        :return:
        """
        return redirect('login')


# 實例化啰扛,利用單例模式
site = AryaSite()

</br>

引入arya組件并使用

  1. 創(chuàng)建app,引入arya組件
創(chuàng)建多個app嗡贺,并在每個app下面創(chuàng)建arya.py文件隐解,用于實現(xiàn)CURD操作
django startapp app01
...
  1. 在app01下面創(chuàng)建models模型
# cat app01/models.py

from django.db import models

class UserType(models.Model):
    """
    用戶類型表
    """
    title = models.CharField(max_length=32, verbose_name="用戶類型")

    class Meta:
        verbose_name_plural = "用戶類型表"

    def __str__(self):
        return self.title


class Role(models.Model):
    """
    角色表
    """
    caption = models.CharField(max_length=32, verbose_name="角色名")

    class Meta:
        verbose_name_plural = "角色表"

    def __str__(self):
        return self.caption


class UserInfo(models.Model):
    """
    用戶表
    """
    username = models.CharField(max_length=32, verbose_name="用戶名")
    password = models.CharField(max_length=64, verbose_name="密碼")
    email = models.CharField(max_length=32, verbose_name="郵箱")
    ut = models.ForeignKey(to="UserType", blank=True, verbose_name="用戶類型")
    roles = models.ManyToManyField(to="Role", blank=True, verbose_name="所屬角色")

    class Meta:
        verbose_name_plural = "用戶表"

    def __str__(self):
        return self.username
  1. 生成表結(jié)構(gòu)并制作部分展示數(shù)據(jù),可以直接在表中添加诫睬,也可以通過admin后臺進(jìn)行添加

  2. 在app01中的arya.py文件中注冊models類并自定義實現(xiàn)展示UI

# cat app01/arya.py

from arya.service import v1
from . import models
 

# 自定義屬性控制UI展示
class UserInfoConfig(v1.AryaConfig):
    """
    自定義用戶信息UI
    """
    list_display = ['username', 'ut', 'roles', 'email']


class UserTypeConfig(v1.AryaConfig):
    """
    自定義用戶類型UI
    """
    list_display = ['title']


class RoleConfig(v1.AryaConfig):
    """
    自定義角色UI
    """
    list_display = ['caption']

# 注冊models
v1.site.register(models.UserInfo, UserInfoConfig)
v1.site.register(models.UserType, UserTypeConfig)
v1.site.register(models.Role, RoleConfig)
  1. 在項目中應(yīng)用arya組件煞茫,使URL生效
#cat project_name/urls.py

from django.contrib import admin
from django.conf.urls import url
from arya.service import v1
from . import views

# url的第二個參數(shù)返回類型為([],None,None)的元組,源碼見include方法
# 此處的login和logut也可以使用arya/service/v1.py文件中定義的路由,示例為自己實現(xiàn)
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    # 此處會生成對應(yīng)的多個URL子路由
    url(r'^arya/', v1.site.urls),
    url(r'^index/$', views.index, name="index"),
    url(r'^login/$', views.login, name="login"),
    url(r'^logout/$', views.logout, name="logout"),
]
  1. 路由試圖處理
# cat project_name/views.py

from django.shortcuts import render, redirect
from app01 import models

def login(request):
    """
    登陸
    :param request:
    :return:
    """
    if request.method == "GET":
        return render(request, 'login.html')
    else:
        username = request.POST.get('username')
        password = request.POST.get('password')
        obj = models.UserInfo.objects.filter(username=username, password=password).first()
        if obj:
            request.session['userinfo'] = {'username': obj.username, 'is_login': True}
            return redirect('index')
        return render(request, 'login.html', {'msg': '用戶名或密碼錯誤'})


def logout(request):
    """
    退出
    :param request:
    :return:
    """
    if request.method == "GET":
        return redirect('login')


def index(request):
    """
    首頁
    :param request:
    :return:
    """
    if request.method == "GET":
        return render(request, 'index.html')
  1. 項目URL
    此時在項目的路由中已經(jīng)存在對應(yīng)增刪改查的4個URL摄凡,如下所示:
# app_nmae 應(yīng)用名
# models_name models類名小寫
arya/app_name/models_name/
arya/app_name/models_name/add/
arya/app_name/models_name/(\d+)/change/
arya/app_name/models_name/(\d+)/delete/
# 在該示例中為: 
http://127.0.0.1:8000/arya/app01/userinfo/
http://127.0.0.1:8000/arya/app01/userinfo/add/
http://127.0.0.1:8000/arya/app01/userinfo/()
....
  1. 擴(kuò)展
    在每個app下面的arya.py文件中繼承arya組件中的service.v1.AryaConfig類续徽,自己內(nèi)部實現(xiàn)處理URL的view以及定制化操作
    </br>

總結(jié)

至此,自定義實現(xiàn)的類似Django admin組件基本開發(fā)完成亲澡,能夠滿足models模型數(shù)據(jù)的CURD操作钦扭。在Django中作為app引入CustAdmin組件,然后在settings文件中注冊后就
可以生效使用了,engoy it!

github

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末床绪,一起剝皮案震驚了整個濱河市客情,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌癞己,老刑警劉巖膀斋,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異痹雅,居然都是意外死亡仰担,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進(jìn)店門练慕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來惰匙,“玉大人,你說我怎么就攤上這事铃将∠罟恚” “怎么了?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵劲阎,是天一觀的道長绘盟。 經(jīng)常有香客問我,道長悯仙,這世上最難降的妖魔是什么龄毡? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮锡垄,結(jié)果婚禮上沦零,老公的妹妹穿的比我還像新娘。我一直安慰自己货岭,他們只是感情好路操,可當(dāng)我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布疾渴。 她就那樣靜靜地躺著,像睡著了一般屯仗。 火紅的嫁衣襯著肌膚如雪搞坝。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天魁袜,我揣著相機(jī)與錄音桩撮,去河邊找鬼。 笑死峰弹,一個胖子當(dāng)著我的面吹牛店量,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播垮卓,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼垫桂,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了粟按?” 一聲冷哼從身側(cè)響起诬滩,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎灭将,沒想到半個月后疼鸟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡庙曙,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年空镜,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片捌朴。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡吴攒,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出砂蔽,到底是詐尸還是另有隱情洼怔,我是刑警寧澤,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布左驾,位于F島的核電站镣隶,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏诡右。R本人自食惡果不足惜安岂,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望帆吻。 院中可真熱鬧域那,春花似錦、人聲如沸猜煮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至翠肘,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間辫秧,已是汗流浹背束倍。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留盟戏,地道東北人绪妹。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像柿究,于是被迫代替她去往敵國和親邮旷。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,976評論 2 355

推薦閱讀更多精彩內(nèi)容