开始今日份整理

1.stark模块基本操作

1.1 stark模块的启动

保证django自动的加载每一个app下的stark.py文件

  • 创建django项目,创建stark项目,start app stark
  • settings注册app
  • stark.app中的apps.py创建def(函数名必须是ready才会自动执行)
from django.utils.module_loading import autodiscover_modules

class StarkConfig(AppConfig):
name = 'stark'
def ready(self):
autodiscover_modules('stark')

1.2 stark模块的注册

所谓注册就是仿照admin模块,对于注册的数据表进行记录,方便后面的url的增删改查

仿照admin在stark下创建一个包services,并创建一个sites.py文件,代码如下

from django.contrib import admin
from django.urls import path
from django.shortcuts import render,HttpResponse class ModelStark(object): list_display =("__str__") def __init__(self,model):
self.model = model def list_view(self, request): return render(request,'stark/list_view.html',locals()) def add_view(self, request):
return HttpResponse("add_view") def change_view(self, request, id):
return HttpResponse("change_view") def delete_view(self, request, id):
return HttpResponse("delete_view") @property
def get_url(self,):
temp = [
path("", self.list_view),
path("add/",self. add_view),
path("(\d+)/change/", self.change_view),
path("(\d+)/delete/", self.delete_view),
]
return (temp, None, None) class StarkSite:
def __init__(self):
self._registry ={} def register(self,model,admin_class=None,**options):
admin_class = admin_class or ModelStark
self._registry[model]=admin_class(model) def get_urls(self):
temp =[] # 拿到已经注册的所有表
for model,config_obj in self._registry.items():
# 表名
model_name = model._meta.model_name
# 项目名
model_label = model._meta.app_label temp.append(
path("%s/%s/"%(model_label,model_name),config_obj.get_url)
)
return temp @property
def urls(self):
return self.get_urls(),None,None site = StarkSite()

在app01中创建stark.py文件,并注册

from stark.services.sites import site,ModelStark
from .models import Book,Publish,Author,Author_detail # 分别注册书籍,出版社以及作者
site.register(Book)
site.register(Publish)
site.register(Author) print(site._registry)

打印注册的列表,结果如下

{<class 'app01.models.Publish'>: <stark.services.sites.ModelStark object at 0x04B66B50>, <class 'app01.models.Book'>: <stark.services.sites.ModelStark object at 0x04B669B0>, <class 'app01.models.Author'>: <stark.services.sites.ModelStark object at 0x04B66970>}

这样就注册成功了

1.3 URL的分发功能以及页面样式理解(非常重要)

为了自定义的URL。所以我们才会有自定义页面,才会有配置类。

(1)在site中StarkSite类中创建一个URLS(self)方法,用@property方式,静态方法

(2)将二级分发功能放在配置类模块中

(3)配置类中self以及self.model的区别(超级重要)

self:是配置类对象

self.model:数据表对象,其实就是数据表的数据

通过上面:即可理解为什么在注册的时候有一个空字典,在每一个表对象进行注册时,对每一个表生成对应的配置类对象,如果一个表对象有自己的自定义样式,则会走自己自定义样式,无则会走默认样式。

这样就基本实现了url的分发功能,有一级也有二级分发。这块内容就是理解就会觉得东西少,不理解则东西好多!,只需要记住

self是配置类,self.model就是数据表对象就可以了。

对于默认类,self为默认配置类,其中self.model为传入的表对象,展示则使用默认类中的样式。

对于自定义类,self为自定义类,其中self.model为传入的表对象,自定义类继承默认类,优先使用自定义定义的类方法。

如下图展示

from django.contrib import admin
from django.urls import path
from django.shortcuts import render,HttpResponse class ModelStark(object): list_display =("__str__") def __init__(self,model):
self.model = model def list_view(self, request): return render(request,'stark/list_view.html',locals()) def add_view(self, request):
return HttpResponse("add_view") def change_view(self, request, id):
return HttpResponse("change_view") def delete_view(self, request, id):
return HttpResponse("delete_view") @property
def get_url(self,):
temp = [
path("", self.list_view),
path("add/",self. add_view),
path("(\d+)/change/", self.change_view),
path("(\d+)/delete/", self.delete_view),
]
return (temp, None, None) class StarkSite:
def __init__(self):
self._registry ={} def register(self,model,admin_class=None,**options):
admin_class = admin_class or ModelStark
self._registry[model]=admin_class(model) def get_urls(self):
temp =[] # 拿到已经注册的所有表
for model,config_obj in self._registry.items():
# 表名
model_name = model._meta.model_name
# 项目名
model_label = model._meta.app_label
temp.append(
path("%s/%s/"%(model_label,model_name),config_obj.get_url)
)
return temp
@property
def urls(self):
return self.get_urls(),None,None site = StarkSite()

stark核心代码

访问顺序

path("stark/app01/book",BookConfig(Book).list_view)
path("stark/app01/book/add",BookConfig(Book).add_view)
path("stark/app01/publish",ModelAdmin(Publish).list_view)
path("stark/app01/publish/add",ModelAdmin(Publish).add_view)

2.stark基础页面

2.1 stark的数据展示

2.1.1 普通数据与一对多数据展示

2.1.1.1 基于自定义类的数据展示

普通数据就是类似于数据库中book表中的title,price,出版日期,作者等基础数据,django天然对一对多支持

#目标数据类型
new_data=[
["python",123],
["java",234]
]

视图层如下

def list_view(self, request):
"""
self:当前配置类
self.model:当前访问的表数据
:param request:
:return:
"""
# 当前要展示的数据表的数据
querset = self.model.objects.all()
print(querset) print(self.list_display) # 用于构建视图中的展示数据
new_data = []
for obj in querset:
temp = []
# 构建列表嵌套中的小列表,使用的是自定义配置列表中要展示的内容
for field_or_info in self.list_display:
vim = getattr(obj,field_or_info)
temp.append(vim) new_data.append(temp)
print('new_data', new_data) return render(request,'stark/list_view.html',locals())

模板层如下

对于Book表,是自定义展示配置类,展示如下图

2.1.1.2 基于默认类的数据展示

视图层以及模板层如上,不过需要注意的是

没有加逗号,django会默认认为是一个字符串,并不会以一个元祖来读取元素,最后导致报错

对于出版社展示如下,只会展示对象名,显示名称是由于模型类中有__str__方法

2.1.2 多对多数据的判断

在app01中添加展示列表中添加作者这个多对多字段

2.1.2.1 错误显示

添加多对多字段

模板展示

最后展示中,作者多对多数据显示为none,

2.1.2.2 多对多数据判断以及自定义错误报错

(1)知识补充:

使用名字访问一个model的实例:模型名._meta.get_field("publish")

展示模型类的的名字:模型名._meta.model_name

展示模型类对应的项目名称:模型名._meta.app_label

展示一个模型类对象的默认名称:模型对象.verbose_name

对于模型类中的参数,如果设置了verbose.name则会显示设置的名字,无则显示参数名称

(2)多对多的判断

对于多对多的判断,首先是导包,对于 list_display来说,普通属性从self.list_display拿到的是字符串,一对多和多对多则是拿到的对象,拿到对象的类型判断是否是多对多,如果是多对多则报错并报错

对于多对多来说,需要提示为多对多,需要使用自定义列,弹出错误,用于提示错误

2.1.3 模型类中choice数据的反射

数据的反射,例如book的出版状态只有已出版以及未出版,但在数据库中记录只有1和2,需要对1和2的内容取出并反射出具体的内容

注:这里主要使用的是”get_属性名_display方法”,这样最后在页面中展示就会变成以及出版或者是未出版,不在是数据库中1和2

2.1.4 模型类属性中的__str__处理方法

field_obj = self.model._meta.get_field(field_or_func) #获取模型对象
这句话,获取的是模型类中的方法,由于模型类中没有__str__方法,所以需要对其进行处理

2.1.5 自定义的展示多对多内容

2.1.5.1 APP内对stark进行自定义列设定

自定义函数,例如show_author,然后把函数名丢到list_display列表中

stites中获取返回值,然后加入到列表中传到前端

注:由于list_display中有字符串也有函数,所以需要用到callable来判断是都为函数名

这里的self 是类函数调用的方式.,因为原来类中需要穿参,现在增加一个参数而已,什么都行.但是最好是self

2.1.5.2 处理多对多内容

在callable 内容中传入obj对象,方便操作数据

在自定制配置类中,通过obj 获取对应的作者信息

2.2 表头数据的展示

2.2.1 默认配置类

非定制列 ,即只有 __str__,只需要返回到数据表名的大写即可

2.2.2 自定制配置类

如果是普通属性,则只需要丢到对应的head_list列表中即可,对于自定义列,传入为函数名的时候则需要对传入做判断

app中注册类书写

2.3 添加选择框,编辑以及删除到所有的展示页面中

2.3.1 在html中展示指定的内容

导入mark_safe包

from django.utils.safestring import mark_safe

可以是后台传入的标签内容不会被转化,直接成为前端代码

2.3.2 反向解析

导入包

from django.urls import reverse

定义类名以及表名

def __init__(self,model):

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

视图层反向解析,设置name

@property
def get_url(self,):
# temp = [
# path("", self.list_view),
# path("add/",self. add_view),
# re_path("(\d+)/change/", self.change_view),
# re_path("(\d+)/delete/", self.delete_view),
# ]
temp = [
path("", self.list_view, name="%s_%s_list" % (self.app_label, self.model_name)),
path("add/", self.add_view, name="%s_%s_add" % (self.app_label, self.model_name)),
re_path("(\d+)/change/", self.change_view, name="%s_%s_change" % (self.app_label, self.model_name)),
re_path("(\d+)/delete/", self.delete_view, name="%s_%s_delete" % (self.app_label, self.model_name)),
]
return (temp, None, None)

反向解析代码

# 反向解析当前访问表的增删改查URL
def get_list_url(self):
# 反向解析当前表的查询的URL
list_url = reverse("%s_%s_list" % (self.app_label, self.model_name))
return list_url def get_add_url(self, obj):
# 反向解析当前表的添加的URL
add_url = reverse("%s_%s_delete" % (self.app_label, self.model_name))
return add_url def get_delete_url(self, obj):
# 反向解析当前表的删除的URL
delete_url = reverse("%s_%s_delete" % (self.app_label, self.model_name), args=(obj.pk,))
return delete_url def get_change_url(self, obj):
# 反向解析当前表的修改的URL
change_url = reverse("%s_%s_change" % (self.app_label, self.model_name), args=(obj.pk,))
return change_url

分析:反向解析名字为app名加表名,利用的是无名分组,注意无名分组为元祖传参,最后是三个默认列代码

# 三个默认列
# 选择框
def show_checkbox(self, obj=None, heade=False):
if heade:
return mark_safe("<input type='checkbox'>")
return mark_safe("<input type='checkbox'>") # 删除框 def show_delbtn(self, obj=None, heade=False):
if heade:
return '删除'
# return mark_safe("<a href='stark/app01/book/%s/delete'>删除</a>" % obj.pk)
return mark_safe("<a href='%s'>删除</a>" % self.get_delete_url(obj))
# 编辑框 def show_editbtn(self, obj=None, heade=False):
if heade:
return '编辑'
# return mark_safe("<a href='stark/app01/book/%s/change'>编辑</a>" % obj.pk)
return mark_safe("<a href='%s'>编辑</a>" % self.get_change_url(obj)) ####同时构建新的list_display,如果需要在默认列表中都展示,需要设定新的list_display # 构建新的list_display def get_new_list_display(self):
temp = []
temp.extend(self.list_display)
temp.append(ModelStark.show_editbtn)
temp.append(ModelStark.show_delbtn)
temp.insert(0, ModelStark.show_checkbox) return temp

属性说明:

  • self 为当前操作的模型配置类
  • obj=None 让默认对象的值为None,即当获取表头的时候不用传值
  • header=False  让默认的header 为False ,使调用数据的时候不用传值,不返回表头,只返回数据

获取表头中,是header =true 这样可以获取表头数据内容

完整site代码如下

from django.contrib import admin
from django.urls import path,re_path
from django.shortcuts import render,HttpResponse
from django.utils.safestring import mark_safe
from django.urls import reverse class ModelStark(object): list_display =("__str__",) def __init__(self,model): self.model = model
self.model_name = self.model._meta.model_name
self.app_label = self.model._meta.app_label # 反向解析当前访问表的增删改查URL
def get_list_url(self):
# 反向解析当前表的查询的URL
list_url = reverse("%s_%s_list" % (self.app_label, self.model_name))
return list_url def get_add_url(self, obj):
# 反向解析当前表的添加的URL
add_url = reverse("%s_%s_delete" % (self.app_label, self.model_name))
return add_url def get_delete_url(self, obj):
# 反向解析当前表的删除的URL
delete_url = reverse("%s_%s_delete" % (self.app_label, self.model_name), args=(obj.pk,))
return delete_url def get_change_url(self, obj):
# 反向解析当前表的修改的URL
change_url = reverse("%s_%s_change" % (self.app_label, self.model_name), args=(obj.pk,))
return change_url # 三个默认列
# 选择框
def show_checkbox(self, obj=None, heade=False):
if heade:
return mark_safe("<input type='checkbox'>")
return mark_safe("<input type='checkbox'>") # 删除框 def show_delbtn(self, obj=None, heade=False):
if heade:
return '删除'
# return mark_safe("<a href='stark/app01/book/%s/delete'>删除</a>" % obj.pk)
return mark_safe("<a href='%s'>删除</a>" % self.get_delete_url(obj))
# 编辑框 def show_editbtn(self, obj=None, heade=False):
if heade:
return '编辑'
# return mark_safe("<a href='stark/app01/book/%s/change'>编辑</a>" % obj.pk)
return mark_safe("<a href='%s'>编辑</a>" % self.get_change_url(obj))
# 构建新的list_display def get_new_list_display(self):
temp = []
temp.extend(self.list_display)
temp.append(ModelStark.show_editbtn)
temp.append(ModelStark.show_delbtn)
temp.insert(0, ModelStark.show_checkbox) return temp # 视图函数
def list_view(self, request):
"""
self:当前配置类
selfmodel:当前访问的表数据
:param request:
:return:
"""
# 当前访问表的数据
querset = self.model.objects.all()
print(querset) print(self.list_display) #用于展示头部文件
header_list=[]
for field_or_info in self.get_new_list_display():
#判断是函数名或者是字符段
if callable(field_or_info):
vim=field_or_info(self,heade=True)
header_list.append(vim)
else:
# 获取指定字段的对象属性,并拿出verbose_name属性
if field_or_info=='__str__':
#如果只有默认装饰类,只有__str__,则拿出他的表名作为头
vim = self.model._meta.model_name.upper()
else:
file_obj =self.model._meta.get_field(field_or_info)
vim = file_obj.verbose_name
header_list.append(vim) #用于构建视图中的展示数据
new_data=[]
for obj in querset:
temp=[]
for field_or_info in self.get_new_list_display():
# 判断是函数还是字符段
if callable(field_or_info):
vim = field_or_info(self,obj)
else:
try:
from django.db.models.fields.related import ManyToManyField
info_obj=self.model._meta.get_field(field_or_info)
# 判断多对多字段
if type(info_obj)==ManyToManyField:
raise Exception("list_distplay 不能是多不多字段")
#判断是否是__str__
# if field_or_info=='__str':
# vim=getattr(obj,field_or_info)()
# 判断是否有choices字段
if info_obj.choices:
vim = getattr(obj,'get_%s_display'%field_or_info)()
else:
vim =getattr(obj,field_or_info)
except Exception as e:
vim = getattr(obj, field_or_info)()
temp.append(vim)
new_data.append(temp)
print('new_data',new_data) # 目标数据
# new_data=[
# ["python",123],
# ["java",234]
# ] return render(request,'stark/list_view.html',locals()) def add_view(self, request):
return HttpResponse("add_view") def change_view(self, request, id):
return HttpResponse("change_view") def delete_view(self, request, id):
return HttpResponse("delete_view") @property
def get_url(self,):
# temp = [
# path("", self.list_view),
# path("add/",self. add_view),
# re_path("(\d+)/change/", self.change_view),
# re_path("(\d+)/delete/", self.delete_view),
# ]
temp = [
path("", self.list_view, name="%s_%s_list" % (self.app_label, self.model_name)),
path("add/", self.add_view, name="%s_%s_add" % (self.app_label, self.model_name)),
re_path("(\d+)/change/", self.change_view, name="%s_%s_change" % (self.app_label, self.model_name)),
re_path("(\d+)/delete/", self.delete_view, name="%s_%s_delete" % (self.app_label, self.model_name)),
]
return (temp, None, None) class StarkSite:
def __init__(self):
self._registry ={} def register(self,model,admin_class=None,**options):
admin_class = admin_class or ModelStark
self._registry[model]=admin_class(model) def get_urls(self):
temp =[] # 拿到已经注册的所有表
for model,config_obj in self._registry.items():
# 表名
model_name = model._meta.model_name
# 项目名
model_label = model._meta.app_label
temp.append(
path("%s/%s/"%(model_label,model_name),config_obj.get_url)
)
return temp
@property
def urls(self):
return self.get_urls(),None,None site = StarkSite()

site代码

完整注册stark代码如下

from stark.services.sites import site,ModelStark
from .models import *
from django.utils.safestring import mark_safe class BookConfig(ModelStark): def show_authors(self,obj=None,heade=False):
if heade:
return "作者信息" return " ".join([author.name for author in obj.author.all()])
# # 选择框
# def show_checkbox(self,obj=None,heade=False):
# if heade:
# return mark_safe("<input type='checkbox'>")
# return mark_safe("<input type='checkbox'>")
#
# # 删除框
# def show_delbtn(self, obj=None, heade=False):
# if heade:
# return '删除'
# return mark_safe("<a href='stark/app01/book/%s/delete'>删除</a>"%obj.pk)
#
# # 编辑框
# def show_editbtn(self, obj=None, heade=False):
# if heade:
# return '编辑'
# return mark_safe("<a href='stark/app01/book/%s/change'>编辑</a>" % obj.pk) list_display=["title","price","staes","publish",show_authors]
# list_display=["title","price","staes","publish"] site.register(Book,BookConfig)
site.register(Publish)
print(site._registry)

stark代码

a

Django-CRM项目学习(二)-模仿admin实现stark的更多相关文章

  1. Spring Boot 项目学习 (二) MySql + MyBatis 注解 + 分页控件 配置

    0 引言 本文主要在Spring Boot 基础项目的基础上,添加 Mysql .MyBatis(注解方式)与 分页控件 的配置,用于协助完成数据库操作. 1 创建数据表 这个过程就暂时省略了. 2 ...

  2. Django - CRM项目(3)

    一.CRM项目的业务逻辑与表结构梳理 1.分析业务逻辑 (1) 引流(sem) (2) 网络咨询师(客服):添加客户信息和查看客户,分配销售 (3) 销售:查看私户 添加跟进记录 失败:加入公户 成功 ...

  3. Django - CRM项目(2)Q查询(模糊查询)

    一.CRM项目(2) 利用Q查询中的q对象完成条件筛选功能. 批量删除.公户转私户功能. 新增一张跟进记录表ConsultRecord,迁移数据库并添加测试数据,实现跟进记录列表页面. 客户列表新增跟 ...

  4. WPF项目学习.二

    WPF用MVVM的解决记录 版权声明:本文为博主初学经验,未经博主允许不得转载. 一.前言 记录在学习与制作WPF过程中遇到的解决方案.  焦点的控制,键盘事件触发,输入框的数字限制,异步处理,隐藏状 ...

  5. django——CRM项目

    1.引言 CRM,客户关系管理系统(Customer Relationship Management).企业用CRM技术来管理与客户之间的关系,以求提升企业成功的管理方式,其目的是协助企业管理销售循环 ...

  6. Django ---- blog项目学习所得

    一.登录功能 1.采用ajax 提交form表单的方式 2.后台生成随机验证码,登录时提交验证码 3.用PLI库生成随机验证码,置于session中,登录时与前台提交的code进行upeer()的验证 ...

  7. php开源项目学习二次开发的计划

      开源项目: cms 国内 dedecms cmstop 国外 joomla, drupal 电商 国内 ecshop 国外 Magento 论坛 discuz 博客 wordpress   学习时 ...

  8. django 基础框架学习 (二)

    Django框架基础-02 Django缓存cookie 1.说明        当我们服务器在响应数据的同时,希望写⼊⼀些缓存数据到客户端        我们可以选择在响应的同时,将要写⼊到客户端的 ...

  9. android 开源项目学习<二>

    roottools:   RootTools gives Rooted developers easy access to common rooted tools...  https://code.g ...

随机推荐

  1. leetcode — binary-tree-inorder-traversal

    import java.util.Arrays; import java.util.Stack; import java.util.TreeMap; /** * * Source : https:// ...

  2. LeetCode专题-Python实现之第27题:Remove Element

    导航页-LeetCode专题-Python实现 相关代码已经上传到github:https://github.com/exploitht/leetcode-python 文中代码为了不动官网提供的初始 ...

  3. Java开发知识之Java类的高级特性,内部类.以及包使用.跟常量关键字

    Java开发知识之Java类的高级特性,内部类.以及包使用.跟常量关键字 一丶Java中包的机制 首先包其实就是个文件夹.作用就是管理类. Java中每次定义一个类的时候.通过Java编译之后.都会生 ...

  4. Spring源码情操陶冶-tx:advice解析器

    承接Spring源码情操陶冶-自定义节点的解析.本节关于事务进行简单的解析 spring配置文件样例 简单的事务配置,对save/delete开头的方法加事务,get/find开头的设置为不加事务只读 ...

  5. Python SQLalchemy的学习与使用

    SQLAlchemy是python中最著名的ORM(Object Relationship Mapping)框架了. 前言:什么是ORM? ORM操作是所有完整软件中后端处理最重要的一部分,主要完成了 ...

  6. Redis数据类型使用场景及有序集合SortedSet底层实现详解

    Redis常用数据类型有字符串String.字典dict.列表List.集合Set.有序集合SortedSet,本文将简单介绍各数据类型及其使用场景,并重点剖析有序集合SortedSet的实现. Li ...

  7. 分享:Java 开发精美艺术二维码

    博客地址:https://ainyi.com/58 Java 开发精美艺术二维码 看到网络上各种各样的二维码层出不穷,好像很炫酷的样子,一时兴起,我也要制作这种炫酷二维码效果 例如: 根据以往例子 根 ...

  8. .Net语言 APP开发平台——Smobiler学习日志:在手机应用开发中如何快速调用电话拨打功能

    样式一 一.目标样式 我们要实现上图中的效果,需要如下的操作: 1.从工具栏上的”Smobiler Components”拖动一个PhoneButton控件到窗体界面上 2.修改PhoneButton ...

  9. 基于C#程序设计语言的三种组合算法

    目录 基于C#程序设计语言的三种组合算法 1. 总体思路 1.1 前言 1.2 算法思路 1.3 算法需要注意的点 2. 三种组合算法 2.1 普通组合算法 2.2 与自身进行组合的组合算法 2.3 ...

  10. HTML代码片段

    按钮类 后退.前进按钮 返回按钮 几种刷新按钮 警告框显示源代码 链接按钮 打开新窗口 打印 新窗口延迟打开 背景色变换 表单类 点击清空文字 关闭输入法 链接 双击打开链接 超链接鼠标形状 页面 不 ...