CRM——插件流程回顾
1. Django项目启动 自动加载文件 制作启动文件 1. 注册strak 在apps.py 类里面增加如下 def ready(self):
from django.utils.module_loading import autodiscover_modules
autodiscover_modules("stark") 2. 在已经注册的app中创建stark.py文件 加载 2. 在stark中模仿AdminSite ModelAdmin类写代码 注册自己的类 class StarkConfig(object): def __init__(self,model_class,site):
self.model_class = model_class
self.site = site class StarkSite(object): def __init__(self):
self._registey = {} def register(self,model_class,stark_config_class=None):
if not stark_config_class:
stark_config_class = StarkConfig self._registey[model_class] = stark_config_class(model_class,self) site = StarkSite() 3. 将注册的类自动生成url - urls.py
from stark.service import v1 urlpatterns = [
url(r'^stark/', v1.site.urls),
] - 为每个类生成4个url v1.py class StarkConfig(object): def __init__(self,model_class,site):
self.model_class = model_class
self.site = site def get_urls(self):
app_model_name = (self.model_class._meta.app_label,self.model_class._meta.model_name,)
url_patterns = [
url(r'^$',self.changelist_view,name="%s_%s_changlist" %app_model_name),
url(r'^add/$',self.add_view,name="%s_%s_add" %app_model_name),
url(r'^(\d+)/delete/$',self.delete_view,name="%s_%s_delete" %app_model_name),
url(r'^(\d+)/change/$',self.change_view,name="%s_%s_chang" %app_model_name),
]
return url_patterns @property
def urls(self):
return self.get_urls() def changelist_view(self,request,*args,**kwargs):
return HttpResponse('列表') def add_view(self,request,*args,**kwargs):
return HttpResponse('添加') def delete_view(self,request,nid,*args,**kwargs):
return HttpResponse('删除') def change_view(self,request,nid,*args,**kwargs):
return HttpResponse('修改') class StarkSite(object): def __init__(self):
self._registey = {} def register(self,model_class,stark_config_class=None):
if not stark_config_class:
stark_config_class = StarkConfig self._registey[model_class] = stark_config_class(model_class,self) def get_urls(self):
url_pattern = [] for model_class,stark_config_obj in self._registry.items(): app_name = model_class._meta.app_label
model_name = model_class._meta.model_name curd_url = url(r'^%s/%s/' %(app_name,model_name,) , (stark_config_obj.urls,None,None))
url_pattern.append(curd_url) return url_pattern @property
def urls(self):
return (self.get_urls(),None,'stark') site = StarkSite() 4. 列表页面展示 - v1.py
def changelist_view(self,request,*args,**kwargs):
# 处理表头 head_list = []
for field_name in self.list_display:
if isinstance(field_name,str):
# 根据类和字段名称,获取字段对象的verbose_name
verbose_name = self.model_class._meta.get_field(field_name).verbose_name
else:
verbose_name = field_name(self,is_header=True)
head_list.append(verbose_name) # 处理表中的数据
# [ UserInfoObj,UserInfoObj,UserInfoObj,UserInfoObj,]
# [ UserInfo(id=1,name='alex',age=18),UserInfo(id=2,name='alex2',age=181),]
data_list = self.model_class.objects.all()
new_data_list = []
for row in data_list:
# row是 UserInfo(id=2,name='alex2',age=181)
# row.id,row.name,row.age
temp = []
for field_name in self.list_display:
if isinstance(field_name,str):
val = getattr(row,field_name) # # 2 alex2
else:
val = field_name(self,row)
temp.append(val)
new_data_list.append(temp) return render(request,'stark/changelist.html',{'data_list':new_data_list,'head_list':head_list}) - shark.py
class UserInfoConfig(v1.StarkConfig): def checkbox(self,obj=None,is_header=False):
if is_header:
return '选择'
return mark_safe('<input type="checkbox" name="pk" value="%s" />' %(obj.id,))
def edit(self,obj=None,is_header=False):
if is_header:
return '编辑'
return mark_safe('<a href="/edit/%s">编辑</a>' %(obj.id,)) list_display = [checkbox,'id','name',edit] 4. 显示增加按钮 - 先判断是否显示,再通过反向解析生成增加链接
- 后端
# 是否显示增加按钮
show_add_btn = True
def get_show_btn(self):
return self.show_add_btn return render(request, 'stark/changelist.html', {'data_list': new_data_list, 'head_list': head_list,"add_url":self.get_add_url(),"show_add_btn":self.get_show_btn()}) - 前端
{% if show_add_btn %}
<a class="btn btn-primary" href="{{ add_url }}">增加</a>
{% endif %} 5. 增加内容页面 1. 通过ModelForm创建公共类 显示和提交 - 后端 def add_view(self, request, *args, **kwargs): class AddTable(ModelForm):
class Meta:
model = self.model_class
fields = "__all__" if request.method == "GET":
form = AddTable()
return render(request,"stark/add_view.html",{"form":form})
else:
form = AddTable(request.POST)
if form.is_valid():
form.save()
return redirect(self.get_list_url())
else:
return render(request, "stark/add_view.html", {"form": form}) - 前端
<form method="post" novalidate>
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="提交">
</form> 2. 升级 在子类自定义ModelForm类 子类之后可以自定义类 - v1.py
model_form_class = None
def get_model_form_class(self):
if self.model_form_class:
return self.model_form_class
else:
#方式一:
# class AddTable(ModelForm):
# class Meta:
# model = self.model_class
# fields = "__all__"
# return AddTable
#方式二:
meta = type("Meta",(object,),{"model":self.model_class,"fields":"__all__"})
AddTable = type("AddTable",(ModelForm,),{"Meta":meta})
return AddTable def add_view(self, request, *args, **kwargs):
model_form_class = self.get_model_form_class()
if request.method == "GET":
form = model_form_class()
return render(request,"stark/add_view.html",{"form":form})
else:
form = model_form_class(request.POST)
if form.is_valid():
form.save()
return redirect(self.get_list_url())
else:
return render(request, "stark/add_view.html", {"form": form})
- stark.py class UserInfoModelForm(ModelForm):
class Meta:
model = models.UserInfo
fields = ["name","password"]
error_messages = {
"name":{
'required':'用户名不能为空'
}
}
class UserInfoConfig(v1.StarkConfig):
model_form_class = UserInfoModelForm 6. 修改 和 删除
def change_view(self, request, nid, *args, **kwargs): obj = self.model_class.objects.filter(pk=nid).first()
if not obj:
return redirect(self.get_list_url())
model_form_class = self.get_model_form_class()
if request.method == "GET":
form = model_form_class(instance=obj)
return render(request,"stark/change_view.html",{"form":form})
else:
form = model_form_class(instance=obj,data=request.POST)
if form.is_valid:
form.save()
return redirect(self.get_list_url())
return render(request,"stark/change_view.html",{"form":form}) def delete_view(self, request, nid, *args, **kwargs):
self.model_class.objects.filter(pk=nid).delete()
return redirect(self.get_list_url())
CRM——插件流程回顾的更多相关文章
- 【Java EE 学习 54】【OA项目第一天】【SSH事务管理不能回滚问题解决】【struts2流程回顾】
一.SSH整合之后事务问题和总结 1.引入问题:DAO层测试 假设将User对象设置为懒加载模式,在dao层使用load方法. 注意,注释不要放开. 使用如下的代码块进行测试: 会报错:no sess ...
- 【Vue】---编写Vue插件流程---【巷子】
一.在Vue中编写插件流程 1.创建组件 components/message.vue <template> <div class="message" v-if= ...
- CRM 插件导出
CRM插件注册一般有三种方式, 1 database 2 disk 3 GAC 如果注册到disk 应该在会在 C:\Program Files\Microsoft Dynamics CRM\Se ...
- CRM 插件奇怪的报错
CRM插件,数据库方式注册.报错 找不到方法:“Void Microsoft.Xrm.Sdk.Entity..ctor(System.String, System.Guid)”. 这个错误让人摸不着头 ...
- Dynamic CRM插件中记录日志-Nlog记录到文本
Dynamic CRM插件中记录日志的方式有多种 通常情况下分为ITracingService记录.单独日志表插入记录.文本记录三种. 之前整理过ITracingService记录的方式,但这种记录有 ...
- Dynamics CRM 插件注册时报Assembly must be registered in isolation的解决方法
在插件注册的时候经常会遇到"Assembly must be registered in isolation"的问题导致无法注册,之前经常会被同事或者朋友问到这个问题,遇到这个问题 ...
- Dynamics CRM 插件Plugin中获取和更新时间字段值的准确转换
前面两篇介绍了后台代码通过组织服务获取更新时间字段.窗体javascript通过Odata获取更新时间字段,最后篇来实验下在插件中的获取和更新时间字段是否需要时制的转化,为何说是最后篇呢,因为在CRM ...
- Dynamic CRM工作流流程实战
前言在研究了MSCRM中插件的使用之后,不可避免需要研究工作流,工作流在各种营销系统中都举足轻重. 关于工作流功能:使用工作流可在后台实现业务流程自动化.类别:分为后台工作流(异步)和实时工作流(同步 ...
- Dynamic CRM插件调试与单元测试
背景 使用Dynamic CRM平台开发完业务插件后,不可避免的就是进行插件调试,测试插件是否正常运行,网上关于Dynamic CRM的资料比较少,但对于调试的博客还是挺多的,足可见插件调试对于Dyn ...
随机推荐
- Paxos发展、算法原理
Paxos 发展史 Leslie Lamport所提出的Paxos算法是现代分布式系统中的一项重要的基础性技术,得到广泛的应用. Paxos的整个发展过程大概可以分为三个阶段: 第一阶段:萌芽期,大致 ...
- 木马suppoie 处理的几个思路 木马文件的权限所有者 属主数组 定时任务 目录权限
木马suppoie 处理的几个思路 木马文件的权限所有者 属主数组 定时任务 目录权限
- php 扩展模块添加
1. 新增安装扩展模块的位置 [root@node_22 ~]# ls /usr/local/php7/lib/php/extensions/no-debug-non-zts-20151012/ op ...
- 12 jsp page 指令
jsp 指令影响由 jsp 页面生成的 servlet 整体结构. jsp page 用来设置整个页面属性, 例如 import 就是引用这些类, 还可以设置 session 等等. <%@ p ...
- json中的日期格式转换(扩展new date()显示格式)
在java spring mvc 开发过程中,通过json 格式,向前端传递数据,日期格式发生了转变, 在前台数据展示时,要进行一定格式的转换才能正常显示: 我在开发中使用了easy ui 和my ...
- WHERE字句
structured query language(非过程性的结构查询语言) 主要内容: 数据库怎么限制里面的数据: 数据库怎么排列里面的数据. WHERE子句: --WHERE字句起到的是对数据库查 ...
- window 实用操作(结束已打开无法删除进程 内存占用)
1.win7删除文件,文件夹或文件已在另一程序中打开:https://jingyan.baidu.com/article/e75057f2a41e88ebc91a8985.html 删除文件时,提示“ ...
- Android 调用堆栈跟踪
Android开发中,我们也会经常遇到段错误,也就是SIGSEGV(11),这个时候libc的backtrace会打印出对应的堆栈信 息,而你看到的仅仅是一对数字,好像无从查起. 如下面这一从串断错误 ...
- Windows 8.1 浏览器中 SkyDrive 的改名与隐藏
在 Windows 8.1 中已经整合了 SkyDrive ,在中文版中 SkyDrive 的名字总是感觉不协调,可是在属性里面可以调整位置却不能修改名称,怎么办呢? 打开注册表,找到 HKEY_CL ...
- 认识tornado(五)
Tornado 自带了模板系统,模板语法与 Django 差异不大.这里简单地介绍如何使用 Tornado 的模板系统. 首先是编写 URL 规则与 Handler: 01 class NowaMag ...