现在让我说啥是 stark 组件, 我也说不清楚. 反正从今天讲的知识来看, 今天完成的就是自己写一个模块, 这个模块包含了 admin 后台管理工具的一些比较好用的功能, 我们把它提炼出来, 也就是相当于自己写一个 admin 后台管理工具, 但这个工具不叫 admin 了, 叫 stark. 既然是模仿 admin 的实现功能, 所以整个执行过程和 admin 是一样的. 首先我们得建一个 stark 包, 即一个 stark 文件夹, 在这里, 我们也可以新建一个 App 叫 stark 也行.
第一步, 启动所有 App 下的 stark.py 文件
每当我们创建一个新的 App 时, 文件夹下都会有一个 admin.py 的文件, 这是 django 帮你做的, 但现在的后台管理工具换成 stark 了, 所以我们首先要在每个 App 下新建一个 stark.py 的文件. 怎么才能让 django 启动的时候, 也把每个 App 下的 stark.py 文件执行呢???? 我们知道哈, admin 是在它的__init__.py 文件写了
- def autodiscover():
- autodiscover_modules('admin', register_to=site)
django 项目启动的时候会执行每个 App 下的 apps.py 文件, 我们可以把这句代码写 stark 文件夹下的 apps.py 文件里, 这样就能保证 django 项目启动后会执行这一句代码, 然后通过这句代码, 执行每个 App 下的 stark.py 文件, 这样我们就启动了每个 App 下的 stark.py 文件.
apps.py
- from django.apps import AppConfig
- from django.utils.module_loading import autodiscover_modules
- class StarkConfig(AppConfig):
- name = 'stark'
- def ready(self):
- autodiscover_modules('stark')
第二步, 该写 stark 的源码了, 完成注册功能
我们在 stark 文件夹下新建一个 service 文件夹用来放源码.
sites.py 源码文件
- class ModelStark():
- def __init__(self,model):
- self.model=model
- class StarkSite():
- def __init__(self):
- self._registry={}
- def register(self,model,stark_class=None):
- stark_class = stark_class or ModelStark
- self._registry[model] = stark_class(model)
- site=StarkSite()
我们可以给 app01 下的 Book 表和 Publish 注册
app01 下的 stark.py
- from stark.service.sites import site,ModelStark
- from app01.models import *
- class BookConfig(ModelStark):
- list_dispaly = ['name','price']
- site.register(Book,BookConfig)
- site.register(Publish)
这样就完成注册了
第三步, 实现 url 的二级分发
urls.py
- from django.contrib import admin
- from django.urls import path
- from stark.service.sites import site
- urlpatterns = [
- path('admin/', admin.site.urls),
- path('stark/', site.urls),
- ]
然后再去源码里添加内容
sites.py
- class ModelStark():
- def get_urls(self):
- temp=[
- path('',self.list_view),
- path('add/',self.add_view),
- re_path('(\d+)/delete/',self.delete_view),
- re_path('(\d+)/edit/',self.edit_view),
- ]
- return temp
- @property
- def urls(self):
- return self.get_urls(), None, None
- class StarkSite():
- def get_urls(self):
- temp=[]
- for model,config_obj in self._registry.items():
- model_name = model._meta.model_name
- app_label = model._meta.app_label
- temp.append(path('%s/%s/'%(app_label,model_name),config_obj.urls))
- return temp
- @property
- def urls(self):
- return self.get_urls(),None, None
这个二级分发的想法是很巧秒的, 一级分发在 StarkSite 类里面定义的, 二级分发是在配置类里面定义的. 调用视图函数的对象变成了配置类对象. 在注册模型类的时候, 我们就说了, 我们可以给每个模型类定制一个配置类, 然后去继承 ModelStark, 从而每个模型类可以重新定义自己的变量, 也可以使用 ModelStark 类的变量, 这样变的很灵活. 到此, stark 的主要功能就写完了, 接下来我只需对每个视图写上逻辑和自己定制 templates 模板, 就完成了, 说的很简单, 但其实并不是那么简单.
第四步, 首先写一个查询的视图函数和模板
我们把视图定义成 Modelstark 的一个方法, 直接用模型类对象就可以调用. 我们首先在 stark 文件下新建一个 templates 文件夹, django 在找模板时, 会现在全局找, 然后再一个一个 App 下找, 所以我们不用修改任何设置就行. 静态文件也是一个道理, 如 Bootstrap 文件和 jQuery 文件, 我们直接在 stark 文件下新建一个 static 文件夹, 然后放在里面就行, 它也是先在全局找, 然后再一个一个 App 下找. 我们为什么要把这些文件放在 stark 文件下, 只是为了我们写的这个 stark 模块, 以后用在任何项目里都可以, 只需要把 stark 文件夹拷走就行了.
sites.py
- class ModelStark:
- list_dispaly=['__str__']
- def _checkbox(self,obj=None):
- if obj:
- return mark_safe('<input type="checkbox"name="check"vlaue="%s">'%obj.pk)
- return '选择'
- def _delete(self,obj=None):
- if obj:
- model_name = self.model._meta.model_name
- app_label = self.model._meta.app_label
- return mark_safe('<a href="/stark/%s/%s/%s/delete"> 删除 </a>'%(app_label,model_name,obj.pk))
- return '删除'
- def _edit(self,obj=None):
- if obj:
- model_name = self.model._meta.model_name
- app_label = self.model._meta.app_label
- return mark_safe('<a href="/stark/%s/%s/%s/edit"> 编辑 </a>' % (app_label, model_name, obj.pk))
- return '编辑'
- def get_new_list_display(self):
- new_list_display=self.list_dispaly
- new_list_display.insert(0,self._checkbox)
- new_list_display.append(self._edit)
- new_list_display.append(self._delete)
- return new_list_display
- def list_view(self,request):
- queryset=self.model.objects.all()
- header=[]
- for field in self.get_new_list_display():
- if field=='__str__':
- header.append(self.model._meta.model_name.upper())
- elif callable(field):
- header.append(field())
- else:
- header.append(self.model._meta.get_field(field).verbose_name)
- data=[]
- for obj in queryset:
- tr=[]
- for field in self.list_dispaly:
- if callable(field):
- val=field(obj)
- else:
- val=getattr(obj,field)
- tr.append(val)
- data.append(tr)
- return render(request,'list_view.html',locals())
list_view.HTML
- <!DOCTYPE HTML>
- <HTML lang="en">
- <head>
- <meta charset="UTF-8">
- <title>
- Title
- </title>
- <link rel="stylesheet" href="/static/CSS/bootstrap.css">
- <script src="/static/js/bootstrap.js">
- </script>
- <script src="/static/jquery-3.3.1.js">
- </script>
- </head>
- <body>
- <div class="container">
- <div class="title">
- 所有书籍
- </div>
- <table class="table table-bordered table-hover table-striped">
- <thead>
- <tr>
- {% for foo in header %}
- <td>
- {{ foo }}
- </td>
- {% endfor %}
- </tr>
- </thead>
- <tbody id="tbody">
- {% for book in data %}
- <tr>
- {% for foo in book %}
- <td>
- {{ foo }}
- </td>
- {% endfor %}
- </tr>
- {% endfor %}
- </tbody>
- </table>
- </div>
- </body>
- </HTML>
今天就写到这里, 明天继续.......
来源: https://www.cnblogs.com/12345huangchun/p/10274376.html