模仿admin写一个类似功能的组件,叫做stark

admin流程之启动

单例模式

单例:只允许一个类实例化出一个对象

使用 new

为了使类只能出现一个实例,我们可以使用 new 来控制实例的创建过程,代码如下:

class Singleton(object):_instance = Nonedef __new__(cls, *args, **kw):if not cls._instance:cls._instance = super(Singleton, cls).__new__(cls, *args, **kw)  # 构建一个实例对象return cls._instance  egon=Animal()
alex=Animal()
wupeiqi=Animal()print(id(egon))
print(id(alex))
print(id(wupeiqi))
#三者完全相同

在上面的代码中,我们将类的实例和一个类变量 _instance 关联起来,
如果 cls._instance 为 None 则创建实例,否则直接返回 cls._instance。

使用模块

其实,Python 的模块就是天然的单例模式,因为模块在第一次导入时,会生成.pyc文件,当第二次导入时,就会直接加载 .pyc 文件,而不会再次执行模块代码。
因此,我们只需把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了。
如果我们真的想要一个单例类,可以考虑这样做:
#mysingleton.py

class My_Singleton(object):def foo(self):passmy_singleton = My_Singleton()

将上面的代码保存在文件 mysingleton.py 中,然后这样使用:

from mysingleton import my_singletonmy_singleton.foo()

启动

(settings---->installapp------>admin)

        def autodiscover():autodiscover_modules('admin', register_to=site)

admin流程之注册

admin.site : 单例对象

class AdminSite():def __init__(self, name='admin'):self._registry = {} #model就是表对象(Book),admin_class就是表的配置类(BookConfig)   def register(self, model, admin_class=None, **options):if not admin_class:#配置类admin_class = ModelAdminself._registry[model] = admin_class(model, self)site=AdminSite()admin.site.register(Book,BookConfig)
admin.site.register(Book)    #  site._registry:{Book:ModelAdmin(Book)}
admin.site.register(Publish) #  site._registry:{Book:ModelAdmin(Book),Publish:ModelAdmin(Publish)}

#site._registry:{模型类:该模型类的配置类对象,........}

知识点:url分发扩展

url()方法的扩展应用

from django.shortcuts import HttpResponseurl(r'^index/', index), # 一旦匹配成功, index(request)urlpatterns = [url(r'^admin/', admin.site.urls),url(r'^yuan/', ([url(r'^test01/', ([url(r'^test1_1/', test01),url(r'^test1_2/', test01),],None,None)),url(r'^test02/', test02),url(r'^test03/', test03),],None,None)),] 

格式,元祖里面是一个列表+None+None

admin流程之设计url

admin中:

from app01 import modelsadmin.site.register(models.Book)
admin.site.register(models.Publish)
admin.site.register(models.Author)

urls.py中:

from django.conf.urls import url
from django.contrib import admin
from django.shortcuts import render, HttpResponse, redirectdef list_view(request):return HttpResponse("list_view")def change(request, id):return HttpResponse("change")def delete(request, id):return HttpResponse("delete")def add(request):return HttpResponse("add")def get_urls2():temp = [url("^add/$", add),url("^$", list_view),url("^(\d+)/change/$", change),url("^(\d+)/delete/$", delete)]return tempdef get_urls():temp = []print("_registry==>", admin.site._registry.items())#{Book:ModelAdmin(Book),....}#(<class 'app01.models.Book'>, <django.contrib.admin.options.ModelAdmin object at 0x00000234441F99B0>)#Django启动会先加载settings,因此_registry中有值for model, model_class_obj in admin.site._registry.items():app_name = model._meta.app_label#model._meta.app_label可以获取当前model所在app的名字model_name = model._meta.model_name#model._meta.model_name可以获得当前model的名称字符串#用stark+app的名字+模型表的名字#举例:http://127.0.0.1:8000/stark/app01/book/02/change/temp.append(url(r"%s/%s/" % (app_name, model_name), (get_urls2(), None, None)))return tempurlpatterns = [url(r'^admin/', admin.site.urls),# [#    url(r'^test01/', test01),#    url(r'^test02/', test02),#                 ]url(r"^stark",(get_urls(),None,None))
]

最终url示例:

^stark auth/group/
^stark auth/user/
^stark app01/book/ ^add/$
^stark app01/book/ ^$
^stark app01/book/ ^(\d+)/change/$
^stark app01/book/ ^(\d+)/delete/$
^stark app01/publish/
^stark app01/author/

知识点回顾

函数和实例方法的区别

class Animal():def running(self):print("running...")
#从实例对象调
alex = Animal()
#alex会作为self参数传进去
alex.running()
#结果:
#running...
#当做函数调,必须传个参数
Animal.running(123)
#结果:
#running...

合并列表

temp = []
temp.append(1)l = [2, 3, 4]
temp.extend(l)
print(temp)
#结果:
[1, 2, 3, 4]

根据字符串名称拿字段对象和数据

Model _meta API
它提供的方法可用于:
检索模型的所有字段实例
按名称检索模型的单个字段实例

from django.contrib.auth.models import User
# A field on the model
User._meta.get_field('username')
<django.db.models.fields.CharField: username># A field from another model that has a relation with the current model
User._meta.get_field('logentry')
<ManyToOneRel: admin.logentry>

按名称(字符串)检索模型的单个字段实例

filter_field_obj = self.model._meta.get_field(filter_field)
print("filter_field_obj==>", filter_field_obj)
得到app01.Book.publish和app01.Book.authors

拿对象下面的数据
.rel .to 来自于ForeignKey和ManyToManyField这俩类
.rel可以看到对象的数据类型,加上.to可以拿到对象下面的数据,.to只对一对一,一对多,多对多有效

print(filter_field_obj.rel.to)
结果:
< class 'app01.models.Publish'>
< class 'app01.models.Author'>data_list = filter_field_obj.rel.to.objects.all()
print(filter_field_obj.rel.to)
结果:
< QuerySet[ < Publish: 图灵新知 >, < Publish: dzm >, < Publish: 老男孩出版社 >] >
< QuerySet[ < Author: egon >, < Author: alex >] >

获取字段对象的中文名

from app01.models import Book
#price是book表中一个字段对象
obj = Book._meta.get_field("price")
obj.verbose_name

结果:

'价格'

没有单独设置verbose_name时,则返回英文名,若想使用中文名则要在models定义verbose_name
例:

class Book(models.Model):nid = models.AutoField(primary_key=True, verbose_name="编号")title = models.CharField(max_length=32, verbose_name="名称")price = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="价格")

总结:自制Admin组件

这里我们叫它Stark

从访问说起:下面的思路是模拟Django原生Admin的写法

url流程

1.urls.py中:

from stark.service.sites import site
urlpatterns = [# url(r"^stark",(get_urls(),None,None))url(r'^stark/', site.urls)
]

2.site是StarkSite这个类的实例化结果,如下面

site = StarkSite()

3.site调用urls,返回的是get_urls中的temp列表

model的注册

在app01目录下面有stark.py文件
我们在这个文件中对model进行注册
在Django启动的时候会遍历每个app中是否有stark.py文件(settings中设置的),找到后会运行,
因此里面的内容在Django启动时就运行过了

1.site.register(Book) 注册Book表
2.register方法会执行:

self._registry[model] = admin_class(model, self)

3.也就是向_registry = {}这个字典中添加了如上内容
内容简单理解为:{Book:ModelStark(Book)},这里的键Book是model对象
此时_registry = {}中就有了内容

访问,url分发开始

1.循环_registry = {},使用site._registry.items()分别得到表的对象和配置类
2.用表对象得到app的名字和表的名字,由此拼出一级分发
3.二级分发用配置类调用urls2得出
配置类对象是ModelStark(Book)
接下来我们去找ModelStark这个类来看一下

class ModelStark()就是默认的配置类,如果注册表的时候没有自定义配置类则走这里,
同时自定义配置类也要继承ModelStark作为父类
在这个类下面:

class ModelStark():  #配置类list_display = ["__str__", ]def __init__(self, model, site):self.model = model

这个self.model = model是关键,谁调用的它self.model就是那个表对象
如果是Book的话,那么self.model = Book

我们回到urls2

urls2返回值构建了一个return self.get_urls2(), None, None的格式
我们再去找get_urls2()这个函数
get_urls2和urls2都是class ModelStark下面的方法

get_urls2里面负责处理二级分发
这里举例访问到视图函数list_view中

    def list_view(self, request):data_list = self.model.objects.all()

此时model是Book,所以可以进行查询

self.model是谁

注:在视图函数中self.model到底是谁?这里是原生Admin组件写法的关键
这要看self是谁,一层一层往上找,最后会找到model_class_obj.urls2
model_class_obj来自于site._registry循环结果中的配置类,配置类是stark.py中注册的一个个模型的配置类
循环到谁就是谁调用urls2,self.model也就是那个对应的模型对象

注:我们无法确定用户访问那个url,因此提前准备好所有url,此时访问book,后面的model就是book,因此可以拿到相应数据

表单数据之多对多字段的处理

方法1 使用函数

在stark.py的BookConfig类中再增加一个函数

def display_atuhors(self, obj=None, is_header=False):#判断is_header有没有值,有值的话就表示这是标题行,直接返回一个固定标题名if is_header:return "作者"s = []#obj是传过来的一个个的对象<Book: go语言第二版>, <Book: linux>,#把这个对象中authors字段所有的内容循环起来分别添加到一个列表中for author in obj.authors.all():s.append(author.name)return ",".join(s)list_display = ["nid", "title", "price", "publish", display_atuhors,]

方法2

通过判断是不是多对多函数来做处理

data_list = self.model.objects.all()for obj in data_list:temp = []#循环需要显示的字段for field in self.list_display:#判断这个字段是不是字符串if isinstance(field, str):try:#引入ManyToManyFieldfrom django.db.models.fields.related import ManyToManyField#获取相应名称字段的对象field_obj = self.model._meta.get_field(field)  #注意,这里没法找出__str__,因此会报错#判断这个对象是不是多对多if isinstance(field_obj, ManyToManyField):l = []#利用反射,循环obj.field.all(),例如<Book: Book object>.authors,再加上.all()取这个对象下authors字段的全部内容for i in getattr(obj, field).all():#把循环结果添加到l列表l.append(str(i)) #l==> ['egon', 'alex']#用逗号把列表里面的元素拼起来val = ",".join(l)except Exception as e:val = getattr(obj, field)#添加到temp列表temp.append(val)

转载于:https://blog.51cto.com/dzm911/2129467

Python Day23 stark组件1相关推荐

  1. python 全栈开发,Day112(内容回顾,单例模式,路由系统,stark组件)

    python 全栈开发,Day112(内容回顾,单例模式,路由系统,stark组件) 一.内容回顾 类可否作为字典的key 初级 举例: class Foo(object):pass_registry ...

  2. python Stark 组件

    Django Admin 是对model中 对应的数据表进行增删改查的组件,对每个APP下面已注册的model表进行增删改查.而stark组件仿照Admin组件开发. Admin的常用配置:  Fil ...

  3. Stark 组件:快速开发神器 —— 自动生成 URL

    说道 Stark 你是不是不会想到他--Tony Stark,超级英雄钢铁侠,这也是我的偶像. 不过我们今天要开发的 Stark 组件,倒是跟他的人工智能助手 JARVIS 有些类似,是帮助我们快速开 ...

  4. Django基于admin的stark组件创建(一)

    首先创建一个名为stark_test的Django项目,创建2个app一个名为app01用来测试stark组件,一个就叫做stark,用来放stark组件 如图: 我们这里使用的是Django自带的数 ...

  5. Django——stark组件

    stark组件是仿照django的admin模块开发的一套组件,它的作用是在网页上对注册的数据表进行增删改查操作. 一.配置 1.创建stark应用,在settings.py中注册stark应用 st ...

  6. Django之stark组件1

    stark组件 stark组件是根据Django admin为原型写的一个组件,能够让我们告别增删改查.stark组件是可插拔试的组件, 移植性强,而且只用配置文件就能够得到想要的数据 一.stark ...

  7. Stark 组件:快速开发神器 —— 锦上添花

    Stark 组件:快速开发神器 -- 锦上添花 一.分页 二.排序 三.搜索 1.关键字搜索 2.组合搜索 四.批量操作 经过前面几个篇章,我们的 Stark 组件已经能够批量生成 URL,快速实现增 ...

  8. Stark 组件:快速开发神器 —— 页面显示

    说道 Stark 你是不是不会想到他--Tony Stark,超级英雄钢铁侠,这也是我的偶像. 不过我们今天要开发的 Stark 组件,倒是跟他的人工智能助手 JARVIS 有些类似,是帮助我们快速开 ...

  9. Stark 组件:快速开发神器 —— 模板设计

    说道 Stark 你是不是不会想到他--Tony Stark,超级英雄钢铁侠,这也是我的偶像. 不过我们今天要开发的 Stark 组件,倒是跟他的人工智能助手 JARVIS 有些类似,是帮助我们快速开 ...

最新文章

  1. 贪心:Jump Game 跳跃游戏
  2. C#进行MapX二次开发之控件基本操作
  3. spring中Constructor、@Autowired、@PostConstruct的顺序
  4. 【IT资讯】阿里新推出“阿里云网盘” 速度10MBs,百度网盘或迎来最强对手!
  5. malloc的内存分配之 malloc(0)的内存分配情况
  6. Apache Spark Job的剖析
  7. 分享3段平时很实用的微代码,高手莫喷
  8. 拼多多九鼎:信息披露无瑕疵 “注水”的是竞争对手
  9. odbc数据源的配置
  10. 20135210——信息安全系统设计基础第一周学习总结
  11. 官方 mysql管理工具下载_飘云mysql管理工具
  12. 一些特殊字符(如:←↑→↓等箭头符号)的Unicode码值
  13. python pdb调试多进程_PDB远程调试Python多进程子程序
  14. 一个springboot 项目a集成另一个springboot 项目b
  15. 关于含税单价和不含税单价的关系记录
  16. 简单的 JSONParser
  17. 百度开源了一款黑科技!超轻量级目标检测算法,网友:这也太好用了!
  18. 中国宠物泌尿系统处方粮行业销售动态与营销前景预测报告(2022-2027)
  19. substance painter中的粒子笔刷重力方向错乱问题
  20. 2-6_Cleaning_Data清洗数据

热门文章

  1. 【结果很简单,过程很艰辛】记阿里云Ons消息队列服务.NET接口填坑过程
  2. 杭电2682--Tree(Prim)
  3. 模拟系统照相机图片裁剪的功能
  4. CISSP备考系列之行政性管理[10-37]
  5. 重新认识vue之事件阻止冒泡
  6. python日期时间
  7. autofac 用法总结
  8. 在SQL Server中将数据导出为XML和Json
  9. 移动端web页面列表类上拉加载,查看详情,iframe嵌套第三方页面遇到的问题以及解决办法...
  10. Go -- 一致性哈希算法