心想事成一个冲 SharePoint 2013 的 Timecard 应用(上)

终极咱们来看望Admin的有关打算方法中,都直接或间接的呢模板传递了preserved_filters参数,这也模板的调用add_preserved_filters方法提供了支撑,那么至此,整个preserved_filters的实现逻辑就是已经非常明晰了。

用实现

第一介绍一下虚拟的集体。

管理员  
Star Scream
   
第一队
Long Haul
一队队长

Bonecrusher
一队队员

Hook
一队队员
第二队
Scrapper
二队队长

Scavenger
二队队员

Mixmaster
二队队员

 

# django/contrib/admin/templatetags/admin_urls.py
@register.simple_tag(takes_context=True)
def add_preserved_filters(context, url, popup=False, to_field=None):
"""
向指定的URL地址添加列表过滤参数。
:param context: 此context为试图向模板传递的context对象,要求包含有opts和preserved_filters参数,Admin的相应试图中都包含有这两个值。
"""
    opts = context.get('opts')
    preserved_filters = context.get('preserved_filters')    # 通过context获取列表过滤参数

    parsed_url = list(urlparse(url))
    parsed_qs = dict(parse_qsl(parsed_url[4]))  # 获取url现有的GET查询参数
    merged_qs = dict()

    if opts and preserved_filters:
        preserved_filters = dict(parse_qsl(preserved_filters))  # 将列表过滤参数转换为字典的形式

        match_url = '/%s' % url.partition(get_script_prefix())[2]   # 此句的作用是移除Django项目的URL前缀。
        try:
            match = resolve(match_url)  # 获取URL反向解析的匹配信息
        except Resolver404:
            pass
        else:
            current_url = '%s:%s' % (match.app_name, match.url_name)
            changelist_url = 'admin:%s_%s_changelist' % (opts.app_label, opts.model_name)
            if changelist_url == current_url and '_changelist_filters' in preserved_filters:
                # 这里是验证当前的url是否就是列表页的url,如果是,则将列表过滤参数还原到url当中
                preserved_filters = dict(parse_qsl(preserved_filters['_changelist_filters']))

        merged_qs.update(preserved_filters)

    if popup:
        from django.contrib.admin.options import IS_POPUP_VAR
        merged_qs[IS_POPUP_VAR] = 1
    if to_field:
        from django.contrib.admin.options import TO_FIELD_VAR
        merged_qs[TO_FIELD_VAR] = to_field

    merged_qs.update(parsed_qs)

    parsed_url[4] = urlencode(merged_qs)
    return urlunparse(parsed_url)

用新 Site,还是新 Web?

自家本着 Site、Web、Web Site 的接头,就是打询问 SharePoint
开始受颠覆的。恨死那帮人了,起名字太自由了。

Web 本来就是多多益善节点连接成的“蜘蛛网”,而 Site
则是其一网中的节点。但是,SharePoint “帮”我们吃倒过来了。

SharePoint 的 Site 是赖的平众多网站(Web)的集纳,但是,Site
的齐却休称“Web Collection”,而号称“Site Collection”;但她 Collect
的却连无是 Site,而是 Web。用郭德纲的说话说:“你想去吧!”

———- 下面开始说正事 ———-

Timecard 作为一个单独的用,当然是得发出和好单身的网站的。这时,我们来
2 只选项:1)建立一个新的网站集(Site Collection)或者
2)找一个存世的网站集建立一个新的子站点(Web)。两种植选择各有利弊,具体分析起来考虑的元素即过剩了。在咱们今天之
Timecard 应用内,我说了算动用子网站(Web)的样式。

 

尽管Django的Admin如此的劲,但也设有不少底不足,好于支付社区为是异常之外向,通过持续的更新迭代,逐步缓解了咱日常支出中所遇到的题目。今天,我们虽来聊聊Django
Admin引入的preserved_filters的实现。

 

咱们懂得Django的Admin是环着Model的数量进行保管的,其首要的田间管理页面我们可以分成两接近:一接近是兼具数据的目列表页面,通过这个页面,我们好进行多少的淘和查找,从而找到我们用展开具体操作的多寡,我们称之为列表页;另一样像样就是具体操作的页面了,通过就好像页面可对现实的数目进行针对的操作,我们且称之为操作页,如Add、Change、Delete等还属于此类。我们通过列表页找到我们所用操作的多寡,进入相应的操作页面,通过操作页面,对数据进行操作,当操作完成后,通常是会超过反回来列表页,以便让我们得延续指向另外的数码开展查找和操作,看图:

需分析

剖析下要小心几独关键:

  1. 组织者有翻动有 Timecard 的权杖,因为若发出报告的。
  2. 每个集体的权柄必须让团队经理自己管理,谁吗帮忙不了外/她。
  3. Time Window 的可见性由管理员控制,也便意味着 Timecard
    的填有初步和结束日期。

 

满足上述之求以后,整个事情的兑现呢就差不绝远了。而且数量要到了
Timecard List 里面,再怎么捞出来、怎么分析就是相对好惩治,因为导出 Timecard
和查看分析的效力权限相对集中,只要埋头实现效益即可。

 

# django/contrib/admin/options.py
class ModelAdmin(BaseModelAdmin):
    …
    def get_preserved_filters(self, request):
        """
        返回当前请求页面所对应的列表页的过滤参数,并将其转换为一个新的GET查询参数,该参数名为_changelist_filters。
        """
        match = request.resolver_match  # 这里获取当前请求所匹配的URL相关的信息
        if self.preserve_filters and match:
            opts = self.model._meta
            current_url = '%s:%s' % (match.app_name, match.url_name)
            changelist_url = 'admin:%s_%s_changelist' % (opts.app_label, opts.model_name)
            if current_url == changelist_url:
                # 如果当前请求的页面就是列表页,则直接参数从GET中获取列表的过滤参数
                preserved_filters = request.GET.urlencode()
            else:
                # 如果当前请求的页面不是列表页,则从GET参数_changelist_filters中获取列表的过滤参数
                preserved_filters = request.GET.get('_changelist_filters')

            if preserved_filters:
                # 将列表过滤参数转换为名为_changelist_filters的单一GET参数
                return urlencode({'_changelist_filters': preserved_filters})
        return ''

新 Time Window 的通知

可以用 SharePoint 的 Alert 功能。

 

# 1、我们假设当前是用户Model的列表页,我们检索了用户名为lili的且职员状态为True的用户,GET参数如下
?q=lili&is_staff__exact=1

# 2、我们将该列表所有GET参数转换为一个GET参数值,即将“q=lili&is_staff__exact=1”参数进行urlencode操作(urlencode的目的是为转义特殊字符),得到结果
q%3Dlili%26is_staff__exact%3D1

# 3、然后我们将该值做为操作页的一个GET参数,假设该参数名为_changelist_filters,那么该参数的GET表示为
_changelist_filters=q%3Dlili%26is_staff__exact%3D1

# 4、假设操作页URL如下
/app_label/model/add/?name=lili

# 5、则将_changelist_filters参数附上以后操作页的完整URL如下:
/app_label/model/add/?name=lili&_changelist_filters=q%3Dlili%26is_staff__exact%3D1

Time Window 与 Timecard List(s) 的关联

是相对简单,直接用 Lookup Column 就可了。

 

自从以上的代码中我们得以视,add_preserved_filters方法其实开了少单趋势的工作,一凡用列表过滤参数保存及非列表页的GET参数中(上文列出的4-5之换过程),二凡以列表过滤参数还原到列表页的GET参数中,因此我们当调用该措施来落实列表过滤参数的保存的复原的时光,就不管需考虑当下之页面到底是排表页还是操作页了,因为方法都拉我们协调搞定了。

业务流程

  1. 集团经理发申请为管理员,让管理员让树集体的专用 Timecard List。
  2. 集体经理于投机的 Timecard List
    中参加团队成员,给她们恰当的权位。(这便是业务流程,其实早就起做技术方案设计了)
  3. 领队定期放出可填写的 Time Window,比如,“2014 W26”就是 2014 年第 26
    周。并且可指定这个窗口的起止日期,这是盖,跨月或者跨年的
    Timecard
    有时使用一个整的日历周打散分配以便各种财务结算。邮件通知发至每个人。
  4. 组织成员至温馨所属团伙的 Timecard List 中填入
    Timecard。如果一个人数属于多单团体,那么他要于差不多只地方填多次。如果他足够聪明,他会晤拿这些不同团体
    Timecard List 的链接组织起、收藏好。
  5. 团体经理上来,刷就交由但是还从来不审查了的
    Timecard,然后对通过或者拒绝。
  6. 月底管理员收 Timecard,导出来月度数据供 … 之用 :)

 

Admin页面关系图.png

角色

  1. 组织者(Admin),控制得填充的日窗口(Time Window)。
  2. 组织(Team),是让求打卡的集体之中可管理的群落。比如,部门是一个组织,项目组为是一个集体,如何设置团队,取决于管理要。
  3. 团组织成员(Team Member),填写 Timecard 的总人口。只能修好的
    Timecard。
  4. 组织经理(Team Manager),负责审核团队成员的 Timecard。

 起名 1

 

由之历程遭到我们好看看所有的操作都是盖列表页也起点和终极的,因此我们得以认为列表页就是单科Model所有管理页面的着力页,维护好该中心页的操作状态,是保险我们操作连贯性的向。但咱都知道Web是随便状态的,因此我们要制定出同样种体制来保障列表页的状态,我们知晓列表页的数量过滤和寻找等操作,是通页面的GET参数来传递的,如果会拿这些GET参数保存下来,当起操作页返回列表页时,将这些参数还原,那么我们就可以还原至操作前的列表页的状态了,那么我们又该如何保存列表页的GET参数为?我们好以列表页的拥有GET参数编码成一个GET参数值,并将该值当作操作页的一个GET参数,当由操作页返回时,再还原该参数就好了,好像不是不行好掌握,看看下面的更换过程就吓明了:

 

每当Django
1.6以前,我们在动用Admin进行多少管理时,很不爽的一些就算是当我们以数额管理列表页面被经过筛选、搜索找到我们所急需之数据集,然后针对数码集中的某个数开展改动、删除等操作后,系统跳转回到数据管理列表页面,此时咱们所筛选、搜索的标准都没有了,页面又回到了具备数据状态,如果我们还得操作才所筛选的数据集,那么还得按刚才底操作步骤逐一筛选、搜索我们所而之数据集,那是一定的分神。为了化解之题材,我们扩张了Django的Admin,通过在页面内传递ChangeList页面的过滤参数,返回ChangeList页面时还原过滤参数,从而缓解了上述问题,实现了操作的连贯性,我们深受它们自从名叫keep_list_parms。

起名 2
起名 3

新兴Django发布了1.6本,我们惊喜的觉察Django
1.6着早就原生实现了以上的需,但为咱们的系对Admin进行了较多的扩张,并且有些特性是恃让keep_list_parms的特性,如果我们只要以系统支持提升到1.6版本,就需对咱原来的贯彻与Django的原生实现进行联,为之,我们专门研究了Django
1.6之源码,结果发现我们的兑现与Django的兑现有惊人的同样,只待经过简单的调修改,就实现了兼容性的调动工作。

 

好了,今天的preserved_filters实现原理及源码解析就交这了,希望能对大家具有助,Bye~

数据及表单

第一发生 Time Window、Timecard、月度导出报告,这样几种。

是分析的一部分是无可知掠过的。我理解架构师、程序员不是丹青(UI
设计师),但是,无视表单设计的人最终都见面赶上麻烦的。哪怕只是一致布置纸的计划,也要是设计。

起名 4

 

Django的Admin是盖Model为使得的数目管理体系,他会晤依据你所定义的Model自动为而老成多少的根基管理介面,从而快速的贯彻多少的CRUD操作,同时该也供了一对一强的扩展性,使你可以根据需要实现个性化的数操作介面,真可谓万分的强劲。

内容类型和 List 模板

考虑到管理员要不厌其烦的吧每个小组成立他们好的 Timecard
List,还是想少办法减轻他/她的行事吧好。

专门依照 Timecard 数据结构的用树立内容类型,然后,附加到每个 List
上面去,无疑会轻松多。

然,我们还得再进一步,在率先单 List 的基础及,再保存其也一个 List
模板,这样,以后又建立其它的 Timecard List
的时光,连绑定内容类型的操作都不了,直接从 List 模板里面挑就好了。

 

Django的合法文档中连从未指向这无异于表征做特别之讲述,
也许是为及时属于系统的特征,而无开发接口和扩展点的因由,对于一般开发人员来说无关紧要,但要急需进行深入的扩展开发,就发或会见波及到拖欠特性,就以我们团结的系统就是应用该特性实现了干数据在同一介面内的联保管,很好之包了管住数据工作的连贯性。因此了解特性的兑现,对于大层次之付出来说,是特别有必要之,今天,就来为大家解析一下Django的原生实现。

需求

Timecard(打卡)应用之求描述如下。

上述代码实现了和齐文列出的1-3的易过程的逻辑,通过调用该办法,我们获得了为_changelist_filters为名称保存之列表过滤参数(即达到文中的_changelist_filters=
q%3Dlili%26is_staff__exact%3D1),我们还需要为此该参数与事实上页面的URL地址进行联合,以便在超过反至对应的页面后将列表过滤参数保存在该页面的GET参数中,因为URL的众操作是当Django的模版被展开的,因此Django将该描绘成了一个自定义标签的计,代码如下:

Timecard 网站

没什么特别的,就是一个惯常的子网站。推荐用 Blank Site 模板。

 

通地上面的易过程,我们落实了将列表的过滤参数保存下去的法力,当返回列表页时,我们就待保留下去的列表过滤参数还原即可,Django给这等同特色的命名吧preserved_filters,翻译过来就保存之过滤器,下面我们来探望代码的落实。

当 SharePoint 2013 上面实现一个 Timecard
应用的想法来自一个实打实的急需,而落实之方案以自我脑海里盘旋已经非常悠久了,终于就几龙准备安排个别时间拿其实现出来。

Time Window 列表

长大脚这样子:

起名 5

此列表的关键在于它的权能设置。

  1. 立刻是一个默认所有人数还足以拜的列表:
    起名 6 
  2. 逾期的岁月窗口,则断开权限继承,所有人将不再可以拜,除了管理员:
    起名 7

 

是因为地方这样的权限设置,大家以填充 Timecard
的时,就只能看见管理员发布之灵光之 Time Window
了。这多亏我们得之效应。

起名 8

 

 

Timecard 列表

Timecard 列表和 Time Window
做了关联,从而实现选择由管理员发布的年华窗口的机能。

Timecard 列表需要吗各级一个社都建立一个之。

起名 9

地方立条记下,说明填写的总人口周六加以了 4 单钟头之次,并且及时长长的记下还当
Pending 状态。

 

实际上运行的早晚,管理员创建好组织的 Timecard 列表,然后拿列表的 Full
Control 给团队经理,然后团队经理进入安排每个成员的权限。

起名 10

 

然后,团队经理需要也每个成员单独建一个文件夹,只允许该成员填写者文件夹下面的
Timecard。

遵照,Bonecrusher 的这文件夹,就要修改其权力,只叫 Bonecrusher
本人可交 Timecard、经理 Long Haul 可以审批。

起名 11

起名 12

对任何队员也一律设置。

 

自,Timecard 列表的 Content Approval
也只要拉开,这样给团队经理可以审核一下。

 

哼了,现在起名之 Timecard 已经可以用起了!

试试看这里:

 

 

啊哈,好像得了邪!这么简单,那叫我们炒掉那个 SharePoint
专家算了,这生活看上去很轻呀!

嘿嘿,真滴吗?:)

起名 13

 

 

 

 

(你们用 IE
访问的时节会意识我的博客界面错乱吗?如果起,请发消息还是评论让自己晓得,谢谢!)

起名 14

“ We started small, then grow up.”—Dont’know who.

采取设计

及时是成套环节中最为有趣儿的组成部分,我们要一步步底日益来。

定位的,这个 Timecard 应用的基本思维依然是因 SharePoint
自身之法力,使该成 SharePoint 应用而休是另的。如果 SharePoint
这个平台不克如其更好,那么,就非值得以 SharePoint 上面实现它。

一如既往开始尝试了 SharePoint 2013 的 App
来促成,但新兴晓过来了,这向未针对路途。App
是一个作者给多个用户独立设置配备的景,而于商家中员工都去装
Timecard App 太为了;而使拿 App
安装于一个恒定位置,让所有人数失去拜谒,那又何须折腾用 App 呐?况且,放正
SharePoint 自己的 CRUD
功能不用实在是和友好过去不。于是,调转船头,设计了今天之这混合方案。

 

导出的喻

由于每个 Team 的 Timecard List 是独自的,所以,无法直接用富有的 Timecard
导出来要做成报告。

此间有 2 只挑选:1)使用 CQWP,将与属于 Timecard
内容类型的数据聚合到一个地方,或者 2)写代码(CSOM、Sandbox Solution
都得以考虑)。

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图