Exemple #1
0
class UserGroup(Model):
    name = Field(str,
                 max_length=128,
                 verbose_name=_('Name'),
                 index=True,
                 nullable=True)
    parent = SelfReference(verbose_name=_('Parent Group'),
                           collection_name='children',
                           nullable=True,
                           default=0)
    users = ManyToMany('user',
                       verbose_name=_('Users'),
                       collection_name='groups')
    deleted = Field(bool, verbose_name=_('Deleted'))
    created_time = Field(datetime.datetime,
                         verbose_name=_('Created Datetime'),
                         auto_now_add=True)
    number_of_children = Field(int, verbose_name=_('Number of Children'))
    number_of_people = Field(int, verbose_name=_('Number of People'))
    order = Field(int, verbose_name=_('Order'), default=9999)
    type = Field(CHAR,
                 max_length=1,
                 verbose_name=_('Group Type'),
                 choices=get_var('AUTH/USER_GROUP_TYPE'))
    auth_type = Field(int,
                      default=get_var('AUTH/AUTH_TYPE_DEFAULT'),
                      verbose_name=_('Auth type'))

    def __unicode__(self):
        return self.name

    @classmethod
    def OnInit(cls):
        Index('usergroup_idx', cls.c.parent, cls.c.name)
Exemple #2
0
class Tutorials_Chapters(Model):
    __verbose_name__ = '章节'
    
    tutorial = Reference('tutorials', verbose_name='所属教程', collection_name='turotial_chapters')
    parent = SelfReference(verbose_name='上级章节', collection_name='children_chapters')
    title = Field(str, max_length=255, verbose_name='标题', required=True)
    order = Field(int, verbose_name='顺序号')
    content = Field(TEXT, verbose_name='内容', default='', nullable=False, required=True)
    format = Field(CHAR, max_length=1, verbose_name='格式', choices=get_var('TUTORIALS/format'), default='2')
    render = Field(CHAR, max_length=1, verbose_name='渲染器', choices=get_var('TUTORIALS/render'), default='1')
    html = Field(TEXT, verbose_name='显示内容', default='', nullable=False)
    modified_user = Reference('user', verbose_name='修改人')
    modified_date = Field(datetime, verbose_name='修改时间')
    hits = Field(int, verbose_name='点击次数')
    votes = Field(int, verbose_name='支持票数')
    deleted = Field(bool, verbose_name='删除标志')
    chars_count = Field(int, verbose_name='字节数', default=0, server_default='0')
    comments_count = Field(int, verbose_name='评论条数', default=0, server_default='0')
    #enable_para_comment = Field(bool, verbose_name='是否打开段落评论', default=True)
    theme = Field(CHAR, max_length=1, verbose_name='代码块样式', choices=get_var('TUTORIALS/theme'), default='1')
    linenum = Field(bool, verbose_name='行号显示')
    scrollable = Field(bool, verbose_name='代码滚动')
    
    def __unicode__(self):
        return self.title
    
    class AddForm:
        fields = ['title', 'content', 'format', 'render', 'theme', 'scrollable']
    
    class EditForm:
        fields = ['title', 'content', 'format', 'render', 'theme', 'scrollable']

    @classmethod
    def OnInit(cls):
        Index('tutchp_indx', cls.c.tutorial, cls.c.parent, cls.c.order)
Exemple #3
0
class Model_Config_His(Model):
    model_name = Field(str,
                       verbose_name=_('Model Name'),
                       index=True,
                       required=True)
    display_name = Field(str, verbose_name=_('Display Name'))
    description = Field(str, verbose_name=_('Description'), max_length=255)
    table_name = Field(str, verbose_name=_('Tablename'))
    uuid = Field(CHAR, max_length=32)
    basemodel = Field(str,
                      verbose_name=_('Base Model Class'),
                      hint=_('Underlying model class path'))
    has_extension = Field(bool, verbose_name=_('Has Extension Model'))
    extension_model = Field(str,
                            verbose_name=_('Extension Model Class'),
                            hint=_('Underlying model class path'))
    fields = Field(TEXT)
    indexes = Field(TEXT)
    extension_fields = Field(TEXT)
    extension_indexes = Field(TEXT)
    version = Field(int)
    status = Field(CHAR,
                   max_length=1,
                   verbose_name=_('Publish Status'),
                   choices=get_var('MODEL_SETTING/'),
                   default='0')
    create_time = Field(datetime.datetime,
                        verbose_name=_('Create Time'),
                        auto_now_add=True)
    published_time = Field(datetime.datetime, verbose_name=_('Published Time'))

    @classmethod
    def OnInit(cls):
        Index('model_cfg_his_idx', cls.c.model_name, cls.c.uuid)
Exemple #4
0
class Workflow_Trans(Model):
    """
    工作流活动流向表
    """
    workflow = Reference('workflow',
                         verbose_name='所属工作流',
                         collection_name="trans",
                         index=True)
    from_task = Reference('workflow_task',
                          verbose_name='流出活动',
                          collection_name="child_tasks")
    to_task = Reference('workflow_task',
                        verbose_name='流入活动',
                        collection_name="parent_tasks")
    from_name = Field(CHAR, verbose_name='前点名称', max_length=255)
    to_name = Field(CHAR, verbose_name='终点名称', max_length=255)
    created_date = Field(datetime.datetime,
                         verbose_name='创建时间',
                         auto_now_add=True)
    created_user = Reference('user', verbose_name='创建人')
    message = Field(CHAR, verbose_name='流转意见', max_length=255)
    type = Field(int,
                 verbose_name='流向类型',
                 choices=get_var('PARA/WF_TRANS_TYPE'),
                 default=2)
Exemple #5
0
class Class_StudyRecord(Model):
    issue = Field(int, verbose_name='期数', default=1)
    class_obj = Reference('class', verbose_name='课程', required=True)
    student = Reference('user', verbose_name='学生', required=True)
    score = Field(int, verbose_name='成绩')
    create_date = Field(datetime.datetime,
                        verbose_name='报名时间',
                        auto_now_add=True)
    evaluate_level = Field(TEXT,
                           verbose_name='评价级别',
                           choices=get_var('CLASSES/evaluate_level'))
    evaluation = Field(TEXT, verbose_name='评语')
    deleted = Field(bool, verbose_name='删除标志')

    @classmethod
    def OnInit(cls):
        Index('cls_std_idx',
              cls.c.class_obj,
              cls.c.issue,
              cls.c.student,
              unique=True)

    class QueryStudents:
        fields = [
            'student',
            'image',
            'name',
        ]
Exemple #6
0
class Workflow_Task(Model):
    """
    工作流活动实例表
    """
    workflow = Reference('workflow',
                         verbose_name='所属工作流',
                         collection_name="tasks",
                         index=True)
    spec_name = Field(CHAR, verbose_name='活动定义名称', max_length=255)
    desc = Field(CHAR, verbose_name='活动显示名称', max_length=255)
    alias_name = Field(CHAR, verbose_name='活动名称', max_length=255)
    state = Field(int,
                  verbose_name='活动状态',
                  default=1,
                  choices=get_var('PARA/WF_TASK_STATUS'))
    created_date = Field(datetime.datetime,
                         verbose_name='创建时间',
                         auto_now_add=True)
    created_user = Reference('user', verbose_name='创建人')
    modified_date = Field(datetime.datetime, verbose_name='修改时间')
    modified_user = Reference('user', verbose_name='修改人')
    data = Field(PICKLE, verbose_name='工作流活动绑定数据')
    uuid = Field(CHAR, verbose_name='UUID', max_length=255)
    async_status = Field(int, default=0)
    async_deliver_date = Field(datetime.datetime,
                               auto_now=True,
                               auto_now_add=True)
    async_deliver_try_count = Field(int, default=0)
Exemple #7
0
class Workflow(Model):
    """
    工作流实例表
    """
    spec_name = Field(CHAR,
                      verbose_name='工作流定义标识',
                      max_length=255,
                      required=True)
    desc = Field(CHAR, verbose_name='工作流显示名称', max_length=255)
    state = Field(int,
                  verbose_name='工作流状态',
                  default=1,
                  choices=get_var('PARA/WF_STATUS'),
                  index=True)
    created_date = Field(datetime.datetime,
                         verbose_name='创建时间',
                         auto_now_add=True)
    created_user = Reference('user',
                             verbose_name='创建人',
                             default=get_modified_user,
                             auto_add=True)
    modified_date = Field(datetime.datetime,
                          verbose_name='修改时间',
                          auto_now=True,
                          auto_now_add=True)
    modified_user = Reference('user',
                              verbose_name='修改人',
                              default=get_modified_user,
                              auto=True,
                              auto_add=True)
    data = Field(PICKLE, verbose_name='工作流绑定数据')
    ref_unique_id = Field(CHAR, verbose_name='关联数据标识', max_length=255)
Exemple #8
0
class Audit(Model):
    table_id = Reference('tables', verbose_name=_('OperationTable'), required=True)
    title = Field(str, max_length=255, verbose_name=_('Title'))
    obj_id = Field(int, verbose_name="ID", required=True)
    changed_value = Field(BLOB, verbose_name=_('ModifiedContent'))
    old_value = Field(BLOB, verbose_name=_('OriginalContent'))
    modify_flag = Field(CHAR, max_length=1, verbose_name=_('ModifiedFlag'), choices=get_var('PARA/AUDIT_MODIFY_FLAG'))
    modified_date = Field(datetime.datetime, verbose_name=_('ModifiedDate'))
    modified_user = Reference('user', verbose_name=_('ModifiedUser'), collection_name='modifier_audits')
Exemple #9
0
class Class_Issue(Model):
    """
    按期数来区分
    """
    issue = Field(int, verbose_name='期数', default=1)
    class_obj = Reference('class', verbose_name='课程', required=True)
    teachers = ManyToMany('user', verbose_name='教师', required=True)
    begin_date = Field(datetime.datetime, verbose_name='开始时间', required=True)
    finish_date = Field(datetime.datetime, verbose_name='结束时间', required=True)
    need_num = Field(int, verbose_name='招生人数', required=True)
    students_num = Field(int, verbose_name='学生数')
    position = Field(str, verbose_name='上课地点', required=True)
    map = Field(str, verbose_name='地图')
    type = Field(CHAR, max_length=1, verbose_name='课程性质', choices=get_var('CLASSES/class_type'), required=True)
    fee = Field(str, verbose_name='收费说明')
    
    @classmethod
    def OnInit(cls):
        Index('cls_issue_idx', cls.c.class_obj, cls.c.issue, unique=True)
    
    class AddForm:
        fields = ['begin_date', 'finish_date', 'teachers', 'need_num',
            'position', 'map', 'type', 'fee']
            
    class EditForm:
        fields = ['begin_date', 'finish_date', 'teachers', 'need_num',
            'position', 'map', 'type', 'fee']

    class Table:
        fields = [
            {'name':'issue', 'width':45},
            {'name':'teachers'},
            {'name':'begin_date', 'width':100},
            {'name':'finish_date', 'width':100},
            {'name':'need_num', 'width':75},
            {'name':'position'},
            {'name':'type', 'width':75},
            {'name':'fee', 'width':90},
        ]
        
    class ListTable:
        fields = [
            {'name':'issue'},
            {'name':'teachers'},
            {'name':'begin_date'},
            {'name':'finish_date'},
            {'name':'need_num'},
            {'name':'students_num'},
            {'name':'position'},
            {'name':'type'},
            {'name':'fee'},
            {'name':'enroll'},
            {'name':'enrolled'},
        ]
Exemple #10
0
class Message(Model):
    __verbose_name__ = u'消息'

    type = Field(CHAR,
                 verbose_name='消息类别',
                 max_length=1,
                 choices=get_var('MESSAGES/MESSAGE_TYPE'))
    message = Field(TEXT, verbose_name='内容')
    user = Reference('user',
                     verbose_name='用户',
                     collection_name='user_messages')
    read_flag = Field(bool, verbose_name='阅读标志')
    create_date = Field(datetime.datetime,
                        verbose_name='创建时间',
                        auto_now=True,
                        auto_now_add=True)
    sender = Reference('user', verbose_name='创建人')
    send_flag = Field(CHAR, max_length=1, verbose_name='发送标志',
                      default='r')  #'s' 发送, 'r' 接收

    def __unicode__(self):
        return self.message

    class Table:
        fields = [
            'message',
            'type',
            'user',
            'read_flag',
            'create_date',
            'sender',
            'id',
            'send_flag',
            'user_image',
        ]

    @classmethod
    def OnInit(cls):
        Index('msg_idx', cls.c.user, cls.c.read_flag)
Exemple #11
0
class User(Model):
    username = Field(str,
                     verbose_name=_('Username'),
                     max_length=30,
                     unique=True,
                     index=True,
                     nullable=False)
    nickname = Field(str, verbose_name=_('Nick Name'), max_length=30)
    email = Field(str, verbose_name=_('Email'), max_length=40)
    password = Field(str, verbose_name=_('Password'), max_length=128)
    is_superuser = Field(bool, verbose_name=_('Is Superuser'))
    last_login = Field(datetime.datetime, verbose_name=_('Last Login'))
    date_join = Field(datetime.datetime,
                      verbose_name=_('Joined Date'),
                      auto_now_add=True)
    image = Field(FILE, verbose_name=_('Portrait'), max_length=256)
    active = Field(bool, verbose_name=_('Active Status'))
    locked = Field(bool, verbose_name=_('Lock Status'))
    weibo = Field(str, verbose_name='微博')
    blog = Field(str, verbose_name='博客')
    qq = Field(str, verbose_name='QQ号', max_length=20)
    description = Field(TEXT, verbose_name='自我介绍')
    sex = Field(CHAR, verbose_name='性别', choices=get_var('PARA/SEX'))

    def set_password(self, raw_password):
        self.password = encrypt_password(raw_password)
        self.save()

    def check_password(self, raw_password):
        """
        Returns a boolean of whether the raw_password was correct. Handles
        encryption formats behind the scenes.
        """
        return check_password(raw_password, self.password)

    def get_image_url(self):
        from uliweb.contrib.upload import get_url
        from uliweb.contrib.staticfiles import url_for_static

        if self.image:
            return get_href(self.image)
        else:
            return functions.url_for_static('images/user%dx%d.jpg' % (50, 50))

    def get_default_image_url(self, size=50):
        from uliweb.contrib.staticfiles import url_for_static
        return functions.url_for_static('images/user%dx%d.jpg' % (size, size))

    def __unicode__(self):
        return self.nickname or self.username

    class Meta:
        display_field = 'username'

    class AddForm:
        fields = ('username', 'nickname', 'email', 'weibo', 'blog', 'qq',
                  'description', 'is_superuser')

    class EditForm:
        fields = ('username', 'nickname', 'email', 'weibo', 'blog', 'qq',
                  'description')

    class DetailView:
        fields = ('username', 'nickname', 'email', 'weibo', 'blog', 'qq',
                  'description', 'is_superuser', 'date_join', 'last_login')

    class Table:
        fields = [
            {
                'name': 'username'
            },
            {
                'name': 'nickname'
            },
            {
                'name': 'email',
                'width': 150
            },
            {
                'name': 'weibo'
            },
            {
                'name': 'blog'
            },
            {
                'name': 'qq'
            },
            {
                'name': 'is_superuser'
            },
            {
                'name': 'date_join',
                'width': 200
            },
            {
                'name': 'last_login',
                'width': 200
            },
        ]
Exemple #12
0
class Async_Tasks(Model):
    task_id = Field(str,
                    max_length=32,
                    verbose_name=_('Task ID'),
                    index=True,
                    unique=True)
    title = Field(str, max_length=200, verbose_name=_('Title'))
    parent_task = Reference(reference_fieldname='task_id',
                            verbose_name=_('Parent Task'),
                            index=True,
                            collection_name='tasks')
    category = Field(str, max_length=40, verbose_name=_('Category'))
    message_source = Field(CHAR,
                           max_length=1,
                           verbose_name=_('Message Source'),
                           choices=get_var('ASYNC_TASKS/MESSAGE_SOURCE'),
                           default='l')
    message_type = Field(CHAR,
                         max_length=1,
                         verbose_name=_('Message Type'),
                         choices=get_var('ASYNC_TASKS/MESSAGE_TYPE'))
    #如果command_name为空,表示无命令需要执行
    command_name = Field(str, max_length=256, verbose_name=_('Command Name'))
    command_info = Field(JSON, verbose_name=_('Command Info'))
    depend_tasks = Field(JSON, verbose_name=_('Depend Tasks'), default=[])
    status = Field(CHAR,
                   max_length=1,
                   verbose_name=_('Status'),
                   choices=get_var('ASYNC_TASKS/ASYNC_STATUS'),
                   default='0',
                   index=True)

    #记录当前状态,主要用在parent_task中
    current_status = Field(CHAR,
                           max_length=1,
                           verbose_name=_('Current Status'),
                           choices=get_var('ASYNC_TASKS/ASYNC_STATUS'),
                           default='0')

    #子结点个数
    children_count = Field(int, verbose_name=_('Children Count'))

    created_time = Field(datetime.datetime,
                         verbose_name=_('Created Time'),
                         auto_now_add=True)
    execution_info = Field(TEXT, verbose_name=_('Execution Info'))
    message = Field(str, max_length=2000, verbose_name=_('Message'))
    startup_time = Field(datetime.datetime, verbose_name=_('Startup Time'))
    started_time = Field(datetime.datetime, verbose_name=_('Started Time'))
    finished_time = Field(datetime.datetime, verbose_name=_('Finished Time'))
    max_retry_times = Field(int, verbose_name=_('Max Retry Times'))
    retry_time_interval = Field(int, verbose_name=_('Retry Time Interval'))
    retry_times = Field(int, verbose_name=_('Retry Times'))
    timeout = Field(int, verbose_name=_('Timeout'))
    user_id = Field(str,
                    max_length=40,
                    default='SYS',
                    verbose_name=_('User ID'))
    src_ip = Field(str, max_length=15, verbose_name=_('Source IP'))

    correlation = Field(str,
                        max_length=80,
                        verbose_name=_('Correlation'),
                        index=True)
    correlation_link = Field(str,
                             max_length=2000,
                             verbose_name=_('Correlation Link'))

    version = Field(int)

    @classmethod
    def OnInit(cls):
        Index('async_tasks_idx', cls.c.created_time, cls.c.status)

    @classmethod
    def get_task(cls, task_id):
        return cls.get(cls.c.task_id == task_id)

    def get_handler(self, **kwargs):
        from . import Handler
        from uliweb.utils.common import import_attr
        cls = import_attr(self.command_info.get('base', Handler))
        return cls(self, **kwargs)

    def check_depend_tasks(self):
        """
        Check if depend pre tasks have done all, if exists unfinished task, then return False
        """

        if self._parent_task_:
            if self.parent_task.current_status != SUCCESS:
                return self.parent_task
        for t in self.depend_tasks:
            task = self.get_task(t)
            if task.status != SUCCESS:
                return task

    def reset(self, force=False, log=None):
        """
        :param force: True will reset without condition, False will only reset for
         Failed, Error, Cancel status
        """
        from . import SUCCESS, STARTED, QUEUED

        now = date.now()

        task = self
        if force or (not force and task.status != SUCCESS and
                     (task.status != STARTED
                      or task.status == STARTED and task.started_time +
                      datetime.timedelta(milliseconds=task.timeout) > now)):
            task.status = QUEUED
            task.retry_times = 0
            task.startup_time = None
            task.execution_info = ''
            task.message = 'The task is reset'
            handler = self.get_handler(log=log)
            handler.save()

            #处理子结点
            for t in self.tasks:
                t.reset(force=force, log=log)

            return True
        else:
            return False

    def cancel(self, message='', process_child=False, log=None):
        """
        只处理状态为QUEUE, ERROR的记录,其它的不处理
        """
        from . import CANCEL, QUEUED, ERROR

        if self.status in (QUEUED, ERROR):
            self.status = CANCEL
            self.finished_time = date.now()
            self.message = message
            handler = self.get_handler(log=log)
            handler.save()

        if process_child:
            #处理子结点
            for t in self.tasks:
                t.cancel(message, process_child, log)

    @classmethod
    def clear_data(cls, days, count=5000):
        from datetime import timedelta

        His = get_model('async_tasks_his')

        now = date.now()

        i = 0
        for row in cls.filter(
                cls.c.status.in_(['C', '1', 'F']), cls.c.created_time <
            (now - timedelta(days=days))):
            his = His(**row.to_dict())
            his.save(insert=True)
            row.delete()

            i += 1
            if i == count:
                yield i
                i = 0
        yield i

    class Table:
        fields = [
            {
                'name': 'task_id',
                'width': 150
            },
            {
                'name': 'title',
                'width': 200
            },
            {
                'name': 'command_name',
                'width': 150
            },
            {
                'name': 'category',
                'width': 100
            },
            {
                'name': 'message_source',
                'width': 60
            },
            {
                'name': 'message_type',
                'width': 60
            },
            # {'name':'command_info', 'width':200},
            {
                'name': 'status',
                'width': 120
            },
            {
                'name': 'current_status',
                'width': 120,
                'hidden': True
            },
            {
                'name': 'retry_times',
                'width': 30
            },
            # {'name':'depend_tasks', 'width':150},
            {
                'name': 'created_time',
                'width': 120
            },
            {
                'name': 'startup_time',
                'width': 120
            },
            {
                'name': 'started_time',
                'width': 120
            },
            {
                'name': 'finished_time',
                'width': 120
            },
            {
                'name': 'user_id',
                'width': 100
            },
            {
                'name': 'src_ip',
                'width': 100
            },
            {
                'name': 'parent',
                'width': 120
            },
            {
                'name': 'children_count',
                'width': 120,
                'hidden': True
            },
            {
                'name': 'correlation',
                'width': 120
            },
        ]
Exemple #13
0
class User(Model):
    username = Field(str,
                     verbose_name=_('Username'),
                     max_length=30,
                     unique=True,
                     index=True,
                     nullable=False)
    nickname = Field(str, verbose_name=_('Nick Name'), max_length=30)
    email = Field(str, verbose_name=_('Email'), max_length=40)
    password = Field(str, verbose_name=_('Password'), max_length=128)
    is_superuser = Field(bool, verbose_name=_('Is Superuser'))
    last_login = Field(datetime.datetime,
                       verbose_name=_('Last Login'),
                       nullable=True)
    date_join = Field(datetime.datetime,
                      verbose_name=_('Joined Date'),
                      auto_now_add=True)
    image = Field(FILE, verbose_name=_('Portrait'), max_length=256)
    active = Field(bool, verbose_name=_('Active Status'))
    locked = Field(bool, verbose_name=_('Lock Status'))
    deleted = Field(bool, verbose_name=_('Deleted'))
    auth_type = Field(int,
                      default=get_var('AUTH/AUTH_TYPE_DEFAULT'),
                      verbose_name=_('Auth type'))

    def set_password(self, raw_password):
        self.password = encrypt_password(raw_password)
        # self.save()

    def check_password(self, raw_password):
        """
        Returns a boolean of whether the raw_password was correct. Handles
        encryption formats behind the scenes.
        """
        return check_password(raw_password, self.password)

    def get_image_url(self):
        if self.image:
            return functions.get_href(self.image)
        else:
            return functions.url_for_static('images/user%dx%d.jpg' % (50, 50))

    def get_default_image_url(self, size=50):
        return functions.url_for_static('images/user%dx%d.jpg' % (size, size))

    def __unicode__(self):
        return (self.nickname
                or self.username) + (_('(Deleted)') if self.deleted else '')

    class Meta:
        display_field = 'username'

    class AddForm:
        fields = ['username', 'nickname', 'email', 'is_superuser']

    class EditForm:
        fields = ['email']

    class AdminEditForm:
        fields = ['email', 'is_superuser']

    class DetailView:
        fields = [
            'username', 'nickname', 'email', 'is_superuser', 'date_join',
            'last_login'
        ]

    class Table:
        fields = [
            {
                'name': 'username'
            },
            {
                'name': 'nickname'
            },
            {
                'name': 'email'
            },
            {
                'name': 'is_superuser'
            },
            {
                'name': 'date_join'
            },
            {
                'name': 'last_login'
            },
            {
                'name': 'deleted'
            },
        ]
Exemple #14
0
class Resource(Model):
    __verbose_name__ = u'资源表'

    #    category = Reference('resource_category', verbose_name=u'分类')
    name = Field(str,
                 max_length=80,
                 verbose_name=u'英文名称',
                 index=True,
                 unique=True,
                 required=True)
    title = Field(str, max_length=200, verbose_name=u'标题', required=True)
    value = Field(str, max_length=512, verbose_name=u'值')
    description = Field(str, max_length=200, verbose_name=u'说明')
    parent = Reference(verbose_name=u'父结点', server_default='0')
    has_children = Field(bool, verbose_name=u'是否有子结点')
    icon = Field(str, max_length=20, verbose_name=u'图标')
    order = Field(int, verbose_name=u'序号')
    target = Field(str, max_length=10)
    type = Field(CHAR,
                 max_length=5,
                 choices=get_var('RESOURCE/TYPE'),
                 verbose_name=u'类型')
    status = Field(CHAR,
                   max_length=5,
                   choices=get_var('RESOURCE/STATUS'),
                   verbose_name=u'状态',
                   server_default='00001')
    deploy_type = Field(CHAR,
                        max_length=1,
                        choices=get_var('PARA/DEPLOY_TYPE'),
                        verbose_name=u'部署类型')
    permissions = ManyToMany('permission', verbose_name=u'权限')
    modified_user = Reference('user', verbose_name=u'修改人')
    modified_time = Field(DATETIME,
                          verbose_name=u'修改时间',
                          auto_now=True,
                          auto_now_add=True)

    def __unicode__(self):
        return self.name

    @classmethod
    def get_menu(cls, parent):
        from uliweb import functions, settings
        from uliweb.utils.common import Serial

        def _f(_p):
            menus = []
            for row in cls.filter(cls.c.parent == _p, cls.c.type == 'M0000',
                                  cls.c.deploy_type == 'F',
                                  cls.c.status == '00001').order_by(
                                      cls.c.order):
                item = row.to_dict()
                item['link'] = row.value
                item['permissions'] = [x.name for x in row.permissions]
                menus.append(item)
                if row.has_children:
                    item['subs'] = _f(item.id)
                else:
                    item['subs'] = []
            return menus

        menus = []
        use_redis = settings.get_var('RESOURCE/USE_REDIS')
        key = 'MENU:{}'.format(parent)
        if use_redis:
            redis = functions.get_redis()
            v = redis.get(key)
            if v:
                menus = Serial.load(v)
        if not menus:
            p = cls.get(cls.c.name == parent)
            menus = _f(p.id)
            if menus and use_redis:
                redis.set(key, Serial.dump(menus))
        return menus

    @classmethod
    def iter_menu(cls, parent, user):
        from uliweb import functions

        def _f(_m):
            menus = []
            for row in _m:
                if row.get('permissions'):
                    if functions.has_permission(user, row['permissions']):
                        menus.append(row)
                else:
                    menus.append(row)
                if row.get('subs'):
                    row['subs'] = _f(row['subs'])
            return menus

        return _f(cls.get_menu(parent))

    def clear_menu(self):
        from uliweb import functions

        #只处理菜单根结点
        if self.type == 'M0000':
            p = self
            while p.parent:
                p = p.parent
            key = 'MENU:{}'.format(p.name)
            redis = functions.get_redis()
            redis.delete(key)

    class Table:
        fields = [
            {
                'name': 'name',
                'width': 120
            },
            {
                'name': 'title',
                'width': 300
            },
            {
                'name': 'value',
                'width': 200
            },
            {
                'name': 'description'
            },
            {
                'name': 'target',
                'width': 120
            },
            {
                'name': 'status',
                'width': 60,
                'align': 'center'
            },
            {
                'name': 'deploy_type',
                'width': 80,
                'align': 'center'
            },
            {
                'name': 'icon',
                'hidden': True
            },
            {
                'name': 'order',
                'hidden': True
            },
            {
                'name': 'parent',
                'hidden': True
            },
            {
                'name': 'id',
                'hidden': True
            },
            {
                'name': 'has_children',
                'hidden': True
            },
        ]

    class AddForm:
        fields = [
            'parent', 'name', 'title', 'value', 'description', 'target',
            'status', 'icon', 'permissions'
        ]
        layout = {'fields': {'status': {'inline': True}}}

    class EditForm:
        fields = [
            'parent', 'name', 'title', 'value', 'description', 'target',
            'status', 'icon', 'permissions', 'modified_time'
        ]

        layout = {
            'fields': {
                'status': {
                    'inline': True
                }
            },
        }

    class DetailView:
        fields = [
            'parent', 'name', 'title', 'value', 'description', 'target',
            'status', 'icon', 'permissions'
        ]
        layout = [
            '-- 基本信息 --', 'parent', ['name', 'title', 'value'], 'description',
            'target', 'status', '-- 权限信息 --', 'permissions'
        ]