博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
手写一个admin 组件------STARK
阅读量:4607 次
发布时间:2019-06-09

本文共 23074 字,大约阅读时间需要 76 分钟。

开一个新的项目,,建立一个stark 包, 在里面创建一个service包,在service 包里创建一个stark.py 文件,

配置好环境, makemigreations, migreate.

settings.py 配置:

STATIC_URL = '/static/' STATICFILES_DIRS = [     os.path.join(BASE_DIR,'static'), ]
INSTALLED_APPS = [     'django.contrib.admin',     'django.contrib.auth',     'django.contrib.contenttypes',     'django.contrib.sessions',     'django.contrib.messages',     'django.contrib.staticfiles',     'app01.apps.App01Config',     'stark.apps.StarkConfig', ] from django.contrib import  admin 配置好后: app01下的modles.py
from django.db import models# Create your models here.from django.db import models# Create your models here.class Author(models.Model):    nid = models.AutoField(primary_key=True)    name=models.CharField( max_length=32)    age=models.IntegerField()    # 与AuthorDetail建立一对一的关系    authorDetail=models.OneToOneField(to="AuthorDetail",on_delete=models.CASCADE)    def __str__(self):        return self.nameclass AuthorDetail(models.Model):    nid = models.AutoField(primary_key=True)    birthday=models.DateField()    telephone=models.BigIntegerField()    addr=models.CharField( max_length=64)    def __str__(self):        return str(self.telephone)class Publish(models.Model):    nid = models.AutoField(primary_key=True)    name=models.CharField( max_length=32)    city=models.CharField( max_length=32)    email=models.EmailField()    def __str__(self):        return self.nameclass Book(models.Model):    nid = models.AutoField(primary_key=True,verbose_name="ID")    title = models.CharField( max_length=32,verbose_name="名称")    publishDate=models.DateField()    price=models.DecimalField(max_digits=5,decimal_places=2,verbose_name="价格")    # 与Publish建立一对多的关系,外键字段建立在多的一方    publish=models.ForeignKey(to="Publish",to_field="nid",on_delete=models.CASCADE,verbose_name="出版社")    # 与Author表建立多对多的关系,ManyToManyField可以建在两个模型中的任意一个,自动创建第三张表    authors=models.ManyToManyField(to='Author',)    def __str__(self):        return self.title
modles.py

app01创建一个的stark.py

# 完成注册功能from app01 import modelsfrom stark.service.stark import site,ModelStarkfrom django.utils.safestring import mark_safefrom django import formsclass BookModelForm(forms.ModelForm):    class Meta:        model=models.Book        fields="__all__"        error_messages={            "title":{
"required":" 该字段不能为空"} }class BookConfig(ModelStark): def authors_display(self,obj=None,is_header=False): if is_header: return "作者" author_list=obj.authors.all() name_list=[author.name for author in author_list] return ','.join(name_list) list_display = ["title","price","publish",authors_display,] list_display_links=["title","price"] model_form_class=BookModelForm search_fields = ["title","price",] def patch_delete(self,request,queryset): queryset.delete() patch_delete.desc="批量删除" def patch_init(self,request,queryset): queryset.update(price=0) patch_init.desc="批量初始化" actions=[patch_delete,patch_init] list_filter=["publish","authors"]site.register(models.Book,BookConfig)site.register(models.Publish)site.register(models.Author)site.register(models.AuthorDetail)
stark.py

day81项目文件夹下的url.py文件

from django.conf.urls import urlfrom django.contrib import adminfrom app01 import viewsfrom stark.service.stark import siteurlpatterns = [    url(r'^admin/', admin.site.urls),
url.py

stark包下的service包里的stark.py

from django.conf.urls import urlfrom django.shortcuts import HttpResponse,redirect,renderfrom django.utils.safestring import mark_safefrom django.urls import reversefrom stark.utils.page import Paginationfrom django.db.models import Qclass Showlist(object):    def __init__(self,conf_obj,queryset,request):        self.conf_obj=conf_obj        self.queryset=queryset        self.request=request        # 分页        current_page=self.request.GET.get("page")        pagination=Pagination(current_page,self.queryset.count(),self.request.GET,per_page_num=2)        self.pagination=pagination        self.page_queryset=self.queryset[self.pagination.start:self.pagination.end]    def get_header(self):        # 处理表头        # header_list=["名称","价格","出版社"]        header_list = []        for field_or_func in self.conf_obj.get_new_list_display():  # ["title","price","publish",delete_col]            if isinstance(field_or_func, str):                if field_or_func == "__str__":                    val = self.conf_obj.model._meta.model_name.upper()                else:                    field_obj = self.conf_obj.model._meta.get_field(field_or_func)                    val = field_obj.verbose_name            else:                val = field_or_func(self.conf_obj, is_header=True)            header_list.append(val)        return header_list    def get_body(self):        #  处理表单数据        data_list = []        for obj in self.page_queryset:  # [obj1,obj2,obj3]            temp = []            for field_or_func in self.conf_obj.get_new_list_display():  # list_display = ["title","price","publish",delete_col]                if isinstance(field_or_func, str):                    val = getattr(obj, field_or_func)                    if field_or_func in self.conf_obj.list_display_links:                        val = mark_safe("%s" % (self.conf_obj.get_reverse_url("change", obj), val))                else:                    val = field_or_func(self.conf_obj, obj)                temp.append(val)            data_list.append(temp)        print(data_list)        return data_list    def get_actions(self):        temp=[]        for func in self.conf_obj.actions:# [patch_delete,]            temp.append({                "name":func.__name__,                "desc":func.desc            })        return temp  #  [{
"name":"patch_delete","desc":"批量删除"},] def get_filter_links(self): print("self.conf_obj.list_filter",self.conf_obj.list_filter) # ['publish', 'authors'] links_dict={} for filter_field in self.conf_obj.list_filter: # ['publish', 'authors'] filter_field_obj=self.conf_obj.model._meta.get_field(filter_field) print(filter_field_obj) print(type(filter_field_obj)) from django.db.models.fields.related import ForeignKey print("rel",filter_field_obj.rel.to) queryset=filter_field_obj.rel.to.objects.all() print("queryset",queryset) temp=[] import copy params=copy.deepcopy(self.request.GET) # 渲染标签 current_filter_field_id=self.request.GET.get(filter_field) # all 的链接标签 params2 = copy.deepcopy(self.request.GET) if filter_field in params2: params2.pop(filter_field) all_link="All"%params2.urlencode() else: all_link = "All" temp.append(all_link) for obj in queryset: params[filter_field]=obj.pk _url=params.urlencode() if current_filter_field_id==str(obj.pk): s = "%s" % (_url, str(obj)) else: s="%s"%(_url,str(obj)) temp.append(s) links_dict[filter_field]=temp return links_dictclass ModelStark(): # 默认配置类对象 def __init__(self,model): self.model=model self.model_name = self.model._meta.model_name self.app_label = self.model._meta.app_label self.app_model_name=(self.app_label,self.model_name) self.key_word="" list_display=["__str__"] list_display_links=[] model_form_class=[] actions=[] search_fields=[] list_filter=[] # 反向解析出增删改查的url # # 删除url # def get_delete_url(self,obj): # url_name = "%s_%s_delete" % self.app_model_name # _url = reverse(url_name, args=(obj.pk,)) # # return _url # # # 编辑url # def get_change_url(self, obj): # url_name = "%s_%s_change" % self.app_model_name # _url = reverse(url_name, args=(obj.pk,)) # # return _url # # # # 查看url # def get_list_url(self): # url_name = "%s_%s_list" % self.app_model_name # _url = reverse(url_name) # # return _url # # # 添加url # def get_add_url(self, obj): # url_name = "%s_%s_add" % self.app_model_name # _url = reverse(url_name, args=(obj.pk,)) # # return _url def get_reverse_url(self, type,obj=None): url_name = "%s_%s_%s" % (self.app_label,self.model_name,type) if obj: _url = reverse(url_name, args=(obj.pk,)) else: _url = reverse(url_name) return _url # 选择,删除,编辑按钮 def delete_col(self,obj=None,is_header=False): if is_header: return "删除" return mark_safe("删除"%self.get_reverse_url("delete",obj)) def edit_col(self,obj=None,is_header=False): if is_header: return "编辑" return mark_safe("编辑"%(self.get_reverse_url("change",obj))) def check_col(self,obj=None,is_header=False): if is_header: return "选择" return mark_safe(""%obj.pk) def get_new_list_display(self): new_list_display=[] new_list_display.extend(self.list_display) if not self.list_display_links: new_list_display.append(ModelStark.edit_col) new_list_display.append(ModelStark.delete_col) new_list_display.insert(0,ModelStark.check_col) return new_list_display def search_filter(self,request,queryset): # search 操作 key_word = request.GET.get("q") print(self.search_fields) # ["title","price"] self.key_word = "" if key_word: self.key_word=key_word search_condition = Q() search_condition.connector = "or" for field in self.search_fields: search_condition.children.append((field + "__icontains", key_word)) queryset = queryset.filter(search_condition) return queryset def filter_list(self,request,queryset): # filter 操作 filter_condition = Q() for key, val in request.GET.items(): # publish=2&authors=1 filter_condition.children.append((key, val)) if filter_condition: queryset=queryset.filter(filter_condition) return queryset def list_view(self,request): # action操作 if request.method=="POST": action=request.POST.get("action") pk_list=request.POST.getlist("selected_action") queryset=self.model.objects.filter(pk__in=pk_list) func=getattr(self,action) func(request,queryset) # 用户访问的模型表: self.model # print("self.model:", self.model) queryset = self.model.objects.all() # print("self.list_display", self.list_display) # ["nid","title","price","publish"] # search 操作 queryset=self.search_filter(request,queryset) queryset=self.filter_list(request,queryset) showlist=Showlist(self,queryset,request) # 获取添加url add_url=self.get_reverse_url("add") return render(request, "stark/list_view.html", locals()) def get_model_form_class(self): if self.model_form_class: return self.model_form_class else: from django import forms class ModelFormDemo(forms.ModelForm): class Meta: model = self.model fields = "__all__" return ModelFormDemo def add_view(self, request): """ if GET请求: GET请求: form = BookModelForm() form:渲染 if POST请求: form = BookModelForm(request.POST) form.is_valid() form.save() # 添加数据 create :param request: :return: """ ModelFormDemo=self.get_model_form_class() from django.forms.boundfield import BoundField from django.forms.models import ModelChoiceField if request.method=="GET": form=ModelFormDemo() for bfield in form : # print(type(bfield.field)) if isinstance(bfield.field,ModelChoiceField): bfield.is_pop=True filed_rel_model=self.model._meta.get_field(bfield.name).rel.to model_name=filed_rel_model._meta.model_name app_label=filed_rel_model._meta.app_label _url=reverse("%s_%s_add"%(app_label,model_name)) bfield.url=_url+"?pop_back_id="+bfield.auto_id return render(request,"stark/add_view.html",locals()) else: form=ModelFormDemo(request.POST) if form.is_valid(): obj=form.save() pop_back_id=request.GET.get("pop_back_id") if pop_back_id: pk=obj.pk text=str(obj) return render(request,"stark/pop.html",locals()) return redirect(self.get_reverse_url("list")) else: return render(request, "stark/add_view.html", locals()) def change_view(self, request,id): """ edit_book = Book.objects.get(pk=id) GET: form = BookModelForm(instance=edit_book) form:渲染 POST: form = BookModelForm(request.POST, instance=edit_book) form.is_valid form.save() # 更新数据 update :param request: :param id: :return: """ ModelFormDemo=self.get_model_form_class() edit_obj=self.model.objects.get(pk=id) if request.method=="GET": form=ModelFormDemo(instance=edit_obj) return render(request, "stark/change_view.html",locals()) else: form=ModelFormDemo(data=request.POST,instance=edit_obj) if form.is_valid(): form.save() return redirect(self.get_reverse_url("list")) else: return render(request, "stark/change_view.html", locals()) def delete_view(self, request,id): if request.method=="POST": self.model.objects.get(pk=id).delete() return redirect(self.get_reverse_url("list")) list_url=self.get_reverse_url("list") return render(request,"stark/delete_view.html",locals()) def get_urls(self): temp=[ url("^$",self.list_view,name="%s_%s_list"%(self.app_model_name)), url("^add/$",self.add_view,name="%s_%s_add"%(self.app_model_name)), url("^(\d+)/change/$",self.change_view,name="%s_%s_change"%(self.app_model_name)), url("^(\d+)/delete/$",self.delete_view,name="%s_%s_delete"%(self.app_model_name)), ] return temp @property def urls(self): return self.get_urls(),None,Noneclass StarkSite(object): def __init__(self, name='admin'): self._registry = {} def register(self, model, admin_class=None, **options): if not admin_class: admin_class = ModelStark # 配置类 self._registry[model] = admin_class(model) # {Book:BookConfig(Book),Publish:ModelAdmin(Publish)} def get_urls(self): temp = [ ] for model_class, config_obj in self._registry.items(): print("===>", model_class, config_obj) model_name = model_class._meta.model_name app_label = model_class._meta.app_label print("===>", app_label, model_name,) temp.append(url(r'^%s/%s/' % (app_label, model_name),config_obj.urls)) ''' 创建url: url("app01/book/$",self.list_view,name="app01_book_list"), url("app01/book/add$",self.add_view,name="app01_book_add"), url("app01/book/(\d+)/change/$",self.change_view), url("app01/book/(\d+)/delete/$",self.delete_view), url("app01/publish/$",self.list_view,name="app01_publish_list"), url("app01/publish/add$",self.add_view,name="app01_publish_add"), url("app01/publish/(\d+)/change/$",self.change_view), url("app01/publish/(\d+)/delete/$",self.delete_view), ''' return temp @property def urls(self): return self.get_urls(),None,Nonesite=StarkSite()
stark.py

utils包里的page.py(分页)

"""分页组件使用示例:    obj = Pagination(request.GET.get('page',1),len(USER_LIST),request.path_info)    page_user_list = USER_LIST[obj.start:obj.end]    page_html = obj.page_html()    return render(request,'index.html',{
'users':page_user_list,'page_html':page_html})"""class Pagination(object): def __init__(self,current_page,all_count,params,per_page_num=10,pager_count=11): """ 封装分页相关数据 :param current_page: 当前页 :param all_count: 数据库中的数据总条数 :param per_page_num: 每页显示的数据条数 :param base_url: 分页中显示的URL前缀 :param pager_count: 最多显示的页码个数 all_count;100 per_page_num:8 current_page start (current_page-1)*per_page_num end (current_page*per_page_num) 1 0 8 2 8 16 3 16 24 情况1:self.current_page-self.pager_count_half<1 2 3 5 pager_start=1 pager_end=self.pager_count+1 情况2: 8 9 10 11 12 13 14 15 16 17 18 15 20 25 pager_start = self.current_page-self.pager_count_half pager_end = self.current_page+self.pager_count_half+1 情况3:self.current_page+self.pager_count_half>self.all_pager 48 47 79 pager_start = self.all_pager-self.pager_count pager_end =self.all_pager+1 """ try: current_page = int(current_page) except Exception as e: current_page = 1 if current_page <1: current_page = 1 self.current_page = current_page self.all_count = all_count self.per_page_num = per_page_num # 总页码 all_pager, tmp = divmod(all_count, per_page_num) if tmp: all_pager += 1 self.all_pager = all_pager self.pager_count = pager_count self.pager_count_half = int((pager_count - 1) / 2) # 5 # import copy self.params=copy.deepcopy(params) @property def start(self): return (self.current_page - 1) * self.per_page_num @property def end(self): return self.current_page * self.per_page_num def page_html(self): # 如果总页码 < 11个: if self.all_pager <= self.pager_count: pager_start = 1 pager_end = self.all_pager + 1 # 总页码 > 11 else: # 当前页如果<=页面上最多显示11/2个页码 if self.current_page <= self.pager_count_half: pager_start = 1 pager_end = self.pager_count + 1 # 当前页大于5 else: # 页码翻到最后 if (self.current_page + self.pager_count_half) > self.all_pager: pager_start = self.all_pager - self.pager_count + 1 pager_end = self.all_pager + 1 else: pager_start = self.current_page - self.pager_count_half pager_end = self.current_page + self.pager_count_half + 1 ######################################################################### page_html_list = [] first_page = '
  • 首页
  • ' % (1,) page_html_list.append(first_page) if self.current_page <= 1: prev_page = '
  • 上一页
  • ' else: prev_page = '
  • 上一页
  • ' % (self.current_page - 1,) page_html_list.append(prev_page) # self.params {
    "page":7,"xxx":123} for i in range(pager_start, pager_end): self.params["page"]=i if i == self.current_page: temp = '
  • %s
  • ' % (i, i,) else: temp = '
  • %s
  • ' % (self.params.urlencode(), i,) page_html_list.append(temp) if self.current_page >= self.all_pager: next_page = '
  • 下一页
  • ' else: next_page = '
  • 下一页
  • ' % (self.current_page + 1,) page_html_list.append(next_page) last_page = '
  • 尾页
  • ' % (self.all_pager,) page_html_list.append(last_page) return ''.join(page_html_list)
    page.py

    stark包里的apps.py

    from django.apps import AppConfigfrom django.utils.module_loading import autodiscover_modulesclass StarkConfig(AppConfig):    name = 'stark'    def ready(self):        autodiscover_modules('stark')
    apps.py

    前端页面:

        
    Title
    {
    % include "stark/class_form.html" %}
    add_view
        
    Title
    {
    % include "stark/class_form.html" %}
    change_view
    {
    % csrf_token %} {
    % for field in form %}
    {
    { field }}
    { { field.errors.0 }} {
    % if field.is_pop %}
    + {
    % endif %}
    {
    % endfor %}
    class_form
        
    Title
    {
    % csrf_token %}
    取消
    delete_view
        
    Title

    数据展示

    添加数据 {
    % if showlist.conf_obj.search_fields %}
    {
    % endif %}
    {
    % csrf_token %}
    { % for item in showlist.get_header %}
    { % endfor %}
    { % for data in showlist.get_body %}
    { % for foo in data %}
    { % endfor %}
    { % endfor %}
    { { item }}
    { { foo }}
    FILTER
    {
    % for key,val in showlist.get_filter_links.items %}
    By { { key|upper }}
    { % for link in val %}

    { { link|safe }}

    { % endfor %}
    {
    % endfor %}
    list_view
        
    Title

    POP

    pop_view

     

     

     

    转载于:https://www.cnblogs.com/lx3822/p/9378471.html

    你可能感兴趣的文章
    luogu P3809 【模板】后缀排序
    查看>>
    JVM 调优工具
    查看>>
    SCTF 2014 pwn题目分析
    查看>>
    集合以及特殊集合
    查看>>
    USACO 2.2 Runaround Numbers
    查看>>
    Matlab画图-非常具体,非常全面
    查看>>
    365. Water and Jug Problem
    查看>>
    SQL数据库数据检索top和distinct
    查看>>
    平衡搜索树--红黑树 RBTree
    查看>>
    sqlite驱动下载
    查看>>
    让IE6/IE7/IE8浏览器支持CSS3属性
    查看>>
    队列实现霍夫曼树
    查看>>
    【Java】图片高质量缩放类
    查看>>
    详解定位与定位应用
    查看>>
    【前端开发】 5分钟创建 Mock Server
    查看>>
    java 从键盘录入的三种方法
    查看>>
    使用jQuery和YQL,以Ajax方式加载外部内容
    查看>>
    pyspider 示例
    查看>>
    电路板工艺中的NPTH和PTH
    查看>>
    JNI实现JAVA和C++互相调用
    查看>>