Exemple #1
0
    def delete_chapter(self, id):
        """
        删除章节
        删除时,如果有子结点,则子结点的父结点应变成当前结点的父结点
        """
        obj = self.model_chapters.get_or_notfound(int(id))
        tutorial = obj.tutorial
        count = obj.comments_count
        parent = obj._parent_

        #修改所有子结点的父结点
        obj.children_chapters.update(parent=parent)

        #删除章节顺序cache
        cache = functions.get_cache()
        cache.delete(self._get_tutorial_chapters_cache_key(obj._tutorial_))

        #删除当前章节
        obj.deleted = True
        obj.modified_user = request.user.id
        obj.modified_date = date.now()
        obj.save()

        #删除所属教程的评论数目
        tutorial.comments_count = max(0, tutorial.comments_count - count)
        tutorial.save()

        #跳转回教程展示页面
        return redirect(url_for(TutorialView.read, id=tutorial.id))
Exemple #2
0
 def _wiki_view(self, pagename):
     from uliweb import request, response
     
     response.template = 'WikiView/wiki_view.html'
     
     if not pagename:
         if 'pages' in request.GET:
             response.template = 'WikiView/wiki_pages.html'
             objects = self.model.filter(self.model.c.enabled==True).filter(self.model.c.deleted==False).fields('name').order_by(self.model.c.name)
             
             return {'objects':objects}
         
         return redirect(url_for(self.__class__.wiki, pagename='Index'))
     
     wiki = self.model.get((self.model.c.name == pagename) & (self.model.c.enabled==True))
     
     if not wiki:
         #check read permission
         self._check_permission('read')
         
         if pagename == 'Index':
             content = settings.WIKI.IndexContent
             wiki = self.model(name='Index', content=content, enabled=True, creator=request.user, modified_user=request.user)
             wiki.save()
             wiki.new_revision()
     
     if wiki:
         #check read permission
         self._check_permission('read', wiki, page=wiki)
         
         #处理阅读次数
         key = '__wikivisited__:%s:%d' % (request.remote_addr, wiki.id)
         cache = functions.get_cache()
         v = cache.get(key, None)
         if not v:
             self.model.filter(self.model.c.id==int(wiki.id)).update(hits=self.model.c.hits+1)
             cache.set(key, 1, settings.get_var('WIKI/WIKI_VISITED_TIMEOUT'))
         
         rev = int(request.GET.get('rev', 0))
         rev_time = None
         if rev:
             cached_pagename = wiki.name + '&ver=%d' % rev
             r = self.changeset.get((self.changeset.c.wiki==wiki.id) & (self.changeset.c.revision==rev))
             rev_time = r.modified_time and r.modified_time.strftime('%Y-%m-%d %H:%M:%S')
             content, kwargs = self._get_cached_page_html(cached_pagename, r.old_content)
         else:
             cached_pagename = wiki.name
             content, kwargs = self._get_cached_page_html(cached_pagename, wiki.content)
         last_rev = wiki.changeset.order_by(self.changeset.c.id.desc()).one().revision
         return {'wiki':wiki, 'content':content, 'revision':rev, 
             'rev_time':rev_time, 'last_rev':last_rev,
             'page_args':kwargs,
             'create_new':self._check_permission('write', raise_exception=False),
             'permissions':self._find_tree_permissions(['read', 'write', 'delete'], wiki, request.user)
             }
     else:
         #check read permission
         self._check_permission('write')
         
         return redirect(url_for(self.__class__.wiki, pagename=pagename, action='edit'))
Exemple #3
0
 def delete_chapter(self, id):
     """
     删除章节
     删除时,如果有子结点,则子结点的父结点应变成当前结点的父结点
     """
     obj = self.model_chapters.get_or_notfound(int(id))
     tutorial = obj.tutorial
     count = obj.comments_count
     parent = obj._parent_
     
     #修改所有子结点的父结点
     obj.children_chapters.update(parent=parent)
     
     #删除章节顺序cache
     cache = functions.get_cache()
     cache.delete(self._get_tutorial_chapters_cache_key(obj._tutorial_))
     
     #删除当前章节
     obj.deleted = True
     obj.modified_user = request.user.id
     obj.modified_date = date.now()
     obj.save()
     
     #删除所属教程的评论数目
     tutorial.comments_count = max(0, tutorial.comments_count-count)
     tutorial.save()
     
     #跳转回教程展示页面
     return redirect(url_for(TutorialView.read, id=tutorial.id))
Exemple #4
0
    def change_titles_order(self, id):
        """
        修改教程的顺序
        id为教程id
        """
        from json import loads

        d = {}
        for x in loads(request.POST['data']):
            d[int(x['id'])] = {
                'parent': x['parent'] or None,
                'order': x['order']
            }
        for row in self.model_chapters.filter(
                self.model_chapters.c.tutorial == int(id)):
            if row.id in d:
                row.parent = d[row.id]['parent']
                row.order = d[row.id]['order']
                row.save()

        #删除章节顺序cache
        cache = functions.get_cache()
        cache.delete(self._get_tutorial_chapters_cache_key(int(id)))

        return json({'success': True})
Exemple #5
0
 def pre_save(data):
     data["creator"] = request.user.id
     cache = functions.get_cache()
     try:
         id = cache.get("interfaceid")
         data["interfaceid"] = id
     except:
         pass
Exemple #6
0
 def post_save(obj, data):
     obj.tutorial.modified_date = date.now()
     obj.tutorial.modified_user = request.user.id
     obj.tutorial.save();
     
     #删除章节顺序cache
     cache = functions.get_cache()
     cache.delete(self._get_tutorial_chapters_cache_key(int(t_id)))
Exemple #7
0
        def post_save(obj, data):
            obj.tutorial.modified_date = date.now()
            obj.tutorial.modified_user = request.user.id
            obj.tutorial.save()

            #删除章节顺序cache
            cache = functions.get_cache()
            cache.delete(self._get_tutorial_chapters_cache_key(int(t_id)))
Exemple #8
0
def check_download():
    cache = functions.get_cache()
    token = request.GET.get('token')
    url = cache.get(token, None)
    if url:
        cache.delete(token)
        return json({'success':True, 'url':url})
    return json({})
Exemple #9
0
 def _get_hits(self, obj, field_name='hits'):
     key = '__tutorialvisited__:%s:%s:%d' % (obj.tablename, request.remote_addr, obj.id)
     cache = functions.get_cache()
     v = cache.get(key, None)
     if not v:
         setattr(obj, field_name, getattr(obj, field_name)+1)
         obj.save()
         cache.set(key, 1, settings.get_var('PARA/TUTORIAL_USER_VISITED_TIMEOUT'))
Exemple #10
0
 def post_save(obj, data):
     obj.tutorial.modified_date = date.now()
     obj.tutorial.modified_user = request.user.id
     obj.tutorial.save();
     
     #删除章节顺序cache
     if old_title != obj.title:
         cache = functions.get_cache()
         cache.delete(self._get_tutorial_chapters_cache_key(obj._tutorial_))
Exemple #11
0
        def post_save(obj, data):
            obj.tutorial.modified_date = date.now()
            obj.tutorial.modified_user = request.user.id
            obj.tutorial.save()

            #删除章节顺序cache
            if old_title != obj.title:
                cache = functions.get_cache()
                cache.delete(
                    self._get_tutorial_chapters_cache_key(obj._tutorial_))
Exemple #12
0
 def _get_hits(self, obj, field_name='hits'):
     key = '__tutorialvisited__:%s:%s:%d' % (obj.tablename,
                                             request.remote_addr, obj.id)
     cache = functions.get_cache()
     v = cache.get(key, None)
     if not v:
         setattr(obj, field_name, getattr(obj, field_name) + 1)
         obj.save()
         cache.set(key, 1,
                   settings.get_var('PARA/TUTORIAL_USER_VISITED_TIMEOUT'))
Exemple #13
0
def check_sep_download():
    import json as json_lib

    cache = functions.get_cache()
    token = request.GET.get('token')
    m = cache.get(token, None)
    if m:
        cache.delete(token)
        return json({'success':True, 'message':'请到ITDM中查看并下载'})
    return json({})
Exemple #14
0
 def view_chapter(self, id):
     """
     查看教程
     """
     
     obj = self.model_chapters.get_or_notfound(int(id))
     if obj.deleted:
         flash('此章节已经被删除!')
         return redirect(url_for(TutorialView.read, id=obj._tutorial_))
     
     #处理点击次数
     self._get_hits(obj)
     
     if not obj.html:
         obj.html = self._get_chapter_html(obj.content, obj.format, obj.render, obj.scrollable)
         obj.save()
     
     if obj.render == '2': #reveal
         response.template = 'TutorialView/render_reveal.html'
         
     #处理上一章和下一章功能,思路是利用缓存,如果存在,则从缓存中取出,如果不存在
     #则创建,保存格式为一个list,这样查找时进行遍历,只保存id和名称
     
     cache = functions.get_cache()
     key = self._get_tutorial_chapters_cache_key(obj._tutorial_)
     value = cache.get(key, None)
     if not value:
         chapters = []
         objects = list(self._get_tutorial_chapters(obj._tutorial_))
         def f(parent=None, n=''):
             for num, row in self._get_chapters(parent, objects=objects):
                 chapters.append({'id':row.id, 'title':n + num + ' ' + row.title})
                 f(row.id, n+num+'.')
         
         f()
         
         value = chapters
         cache.set(key, value, settings.get_var('TUTORIALS/TUTORIAL_CHAPTERS_NAV_TIMEOUT'))
         
     prev = None
     next = None
     for i in range(len(value)):
         if value[i]['id'] == obj.id:
             if i>0:
                 prev = value[i-1]
             if i != len(value)-1:
                 next = value[i+1]
             break
         
     return {'object':obj, 'html':obj.html, 'theme':obj.get_display_value('theme'), 
         'prev':prev, 'next':next}
Exemple #15
0
def delete_user_session():
    from uliweb import settings, request

    user_fieldname = settings.get_var('AUTH/GET_AUTH_USER_FIELDNAME', 'id')
    share_session = settings.get_var('AUTH/AUTH_SHARE_USER_SESSION', False)
    user = request.user
    if user and share_session:
        if isinstance(user, dict):
            user_id = user[user_fieldname]
        else:
            user_id = getattr(user, user_fieldname)
        cache = functions.get_cache()
        key = get_user_session_key(user_id)
        log.debug('Auth: delete user session, userid={}, session_id={}'.format(
            key, request.session.key))
        cache.delete(key)
Exemple #16
0
def delete_user_session():
    from uliweb import settings, request

    user_fieldname = settings.get_var('AUTH/GET_AUTH_USER_FIELDNAME', 'id')
    share_session = settings.get_var('AUTH/AUTH_SHARE_USER_SESSION', False)
    user = request.user
    if user and share_session:
        if isinstance(user, dict):
            user_id = user[user_fieldname]
        else:
            user_id = getattr(user, user_fieldname)
        cache = functions.get_cache()
        key = get_user_session_key(user_id)
        log.debug('Auth: delete user session, userid={}, session_id={}'.format(
            key, request.session.key))
        cache.delete(key)
Exemple #17
0
    def list(self):
        cache = functions.get_cache()
        id = request.params.get("id")

        query = self._get_query_view(url_for(self.__class__.list))
        c = query.run()

        if id:
            cache.delete("interfaceid")
            cache.set("interfaceid", id)
            condition = self.model.c.interfaceid == id
        elif c.get("interface") or c.get("testcasename"):
            condition1 = self.model.c.interface == c["interfaceid"]
            condition2 = self.model.c.testcasename.like("%" + c["testcasename"] + "%")
            condition = condition1 & condition2
        else:
            condition = None

        fields_convert_map = {}

        view = functions.ListView(
            self.model,
            #            pageno=page, #get page info from request
            #            rows_per_page=rows, #get rows info from request
            pagination=True,
            condition=condition,
            fields_convert_map=fields_convert_map,
        )

        if "download" in request.values:
            return view.download("download.xls", action="download", timeout=0)

        if "data" in request.values:
            return json(view.json())

        result = view.run()
        result["view"] = view

        result["pagination"] = functions.create_pagination(
            functions.request_url(), view.total, view.pageno + 1, view.rows_per_page
        )
        result["query_form"] = query.form

        return result
Exemple #18
0
def set_user_session(user):
    """
    Set user session
    :param user: user object chould be model instance or dict
    :return:
    """
    from uliweb import settings, request

    user_fieldname = settings.get_var('AUTH/GET_AUTH_USER_FIELDNAME', 'id')
    share_session = settings.get_var('AUTH/AUTH_SHARE_USER_SESSION', False)
    if isinstance(user, dict):
        user_id = user[user_fieldname]
    else:
        user_id = getattr(user, user_fieldname)

    if share_session:
        cache = functions.get_cache()
        key = get_user_session_key(user_id)
        session_id = cache.get(key, None)
        log.debug(
            'Auth: user session user_id={}, session_id={}, key={}'.format(
                user_id, session_id, key))
        if not session_id:
            request.session.save()
            log.debug('Auth: set user session mapping userid={}, '
                      'session_id={}, expiry time={}'.format(
                          user_id, request.session.key,
                          request.session.expiry_time))
            cache.set(key,
                      request.session.key,
                      expire=request.session.expiry_time)
        elif session_id != request.session.key:
            log.debug('Auth: load oldkey={}, key={}'.format(
                request.session.key, session_id))
            request.session.delete()
            request.session.load(session_id)
    if isinstance(user, dict):
        request.session[_get_auth_key()] = user
    else:
        request.session[_get_auth_key()] = user_id
    request.user = user
Exemple #19
0
 def change_titles_order(self, id):
     """
     修改教程的顺序
     id为教程id
     """
     from json import loads
     
     d = {}
     for x in loads(request.POST['data']):
         d[int(x['id'])] = {'parent':x['parent'] or None, 'order':x['order']}
     for row in self.model_chapters.filter(self.model_chapters.c.tutorial==int(id)):
         if row.id in d:
             row.parent = d[row.id]['parent']
             row.order = d[row.id]['order']
             row.save()
     
     #删除章节顺序cache
     cache = functions.get_cache()
     cache.delete(self._get_tutorial_chapters_cache_key(int(id)))
     
     return json({'success':True})
Exemple #20
0
def messages_number():
    from uliweb import request
    
    message = get_model('message')

    if not request.user:
        return json({'success':False, 'data':''})
        
    cache = functions.get_cache()
    key = _get_key(request.user.id)
    x = cache.get(key, None)
    if not x:
        condition = None
        condition = (message.c.user == request.user.id) & condition
        condition = (message.c.read_flag == False) & condition
        condition = (message.c.send_flag == 'r') & condition
            
        x = message.filter(condition).count()
        
        cache.set(key, x)
    
    return json({'success':True, 'data':x})
Exemple #21
0
def messages_number():
    from uliweb import request

    message = get_model('message')

    if not request.user:
        return json({'success': False, 'data': ''})

    cache = functions.get_cache()
    key = _get_key(request.user.id)
    x = cache.get(key, None)
    if not x:
        condition = None
        condition = (message.c.user == request.user.id) & condition
        condition = (message.c.read_flag == False) & condition
        condition = (message.c.send_flag == 'r') & condition

        x = message.filter(condition).count()

        cache.set(key, x)

    return json({'success': True, 'data': x})
Exemple #22
0
def customer_msg():
    if utils.verification(request):
        data = request.data
        msg = parse_msg(data)
        if user_subscribe_event(msg):
            return help_info(msg)
        elif is_text_msg(msg):  # 如果是文字消息就先返回帮助信息
            content = msg['Content']
            if content == u'今日电影':
                cache = functions.get_cache()

                def tmovie():
                    return utils.moviespider()

                cache.get('tmovie', default='error', creator=tmovie)
                my_movie_list = cache['tmovie']
                recontent = utils.parse_movie_list(my_movie_list)
                return response_text_msg(msg, recontent)


            return help_info(msg)

    return 'message processing fail'
Exemple #23
0
def set_user_session(user):
    """
    Set user session
    :param user: user object chould be model instance or dict
    :return:
    """
    from uliweb import settings, request

    user_fieldname = settings.get_var('AUTH/GET_AUTH_USER_FIELDNAME', 'id')
    share_session = settings.get_var('AUTH/AUTH_SHARE_USER_SESSION', False)
    if isinstance(user, dict):
        user_id = user[user_fieldname]
    else:
        user_id = getattr(user, user_fieldname)

    if share_session:
        cache = functions.get_cache()
        key = get_user_session_key(user_id)
        session_id = cache.get(key, None)
        log.debug('Auth: user session user_id={}, session_id={}, key={}'.format(user_id, session_id, key))
        if not session_id:
            request.session.save()
            log.debug('Auth: set user session mapping userid={}, '
                      'session_id={}, expiry time={}'.format(user_id,
                                                             request.session.key,
                                                             request.session.expiry_time))
            cache.set(key, request.session.key, expire=request.session.expiry_time)
        elif session_id != request.session.key:
            log.debug('Auth: load oldkey={}, key={}'.format(request.session.key, session_id))
            request.session.delete()
            request.session.load(session_id)
    if isinstance(user, dict):
        request.session[_get_auth_key()] = user
    else:
        request.session[_get_auth_key()] = user_id
    request.user = user
Exemple #24
0
def _del_key(user_id):
    cache = functions.get_cache()
    cache.delete(_get_key(user_id))
Exemple #25
0
def _del_key(user_id):
    cache = functions.get_cache()
    cache.delete(_get_key(user_id))
Exemple #26
0
    def view_chapter(self, id):
        """
        查看教程
        """

        obj = self.model_chapters.get_or_notfound(int(id))
        if obj.deleted:
            flash('此章节已经被删除!')
            return redirect(url_for(TutorialView.read, id=obj._tutorial_))

        #处理点击次数
        self._get_hits(obj)

        if not obj.html:
            obj.html = self._get_chapter_html(obj.content, obj.format,
                                              obj.render, obj.scrollable)
            obj.save()

        if obj.render == '2':  #reveal
            response.template = 'TutorialView/render_reveal.html'

        #处理上一章和下一章功能,思路是利用缓存,如果存在,则从缓存中取出,如果不存在
        #则创建,保存格式为一个list,这样查找时进行遍历,只保存id和名称

        cache = functions.get_cache()
        key = self._get_tutorial_chapters_cache_key(obj._tutorial_)
        value = cache.get(key, None)
        if not value:
            chapters = []
            objects = list(self._get_tutorial_chapters(obj._tutorial_))

            def f(parent=None, n=''):
                for num, row in self._get_chapters(parent, objects=objects):
                    chapters.append({
                        'id': row.id,
                        'title': n + num + ' ' + row.title
                    })
                    f(row.id, n + num + '.')

            f()

            value = chapters
            cache.set(
                key, value,
                settings.get_var('TUTORIALS/TUTORIAL_CHAPTERS_NAV_TIMEOUT'))

        prev = None
        next = None
        for i in range(len(value)):
            if value[i]['id'] == obj.id:
                if i > 0:
                    prev = value[i - 1]
                if i != len(value) - 1:
                    next = value[i + 1]
                break

        return {
            'object': obj,
            'html': obj.html,
            'theme': obj.get_display_value('theme'),
            'prev': prev,
            'next': next
        }
Exemple #27
0
def index():
    cache = functions.get_cache()
    print cache.get('test', default='ss', creator=my_creator)
    print cache['test']
    return '<h1>Hello, Uliweb</h1>'
Exemple #28
0
    def topic_view(self, forum_id, topic_id):
        """
        显示某主题页面
        """
        from uliweb.utils.generic import ListView
        from uliweb import settings
        
        pageno = int(request.values.get('page', 1)) - 1
        rows_per_page=int(request.values.get('rows', settings.get_var('PARA/FORUM_PAGE_NUMS')))
        cur_page = request.values.get('page', 1)
        
        Post = get_model('forumpost')
        Topic = get_model('forumtopic')
        Forum = get_model('forum')
        topic = Topic.get(int(topic_id))
        forum = topic.forum

        condition = Post.c.topic == int(topic_id)
        condition1 = (Post.c.parent == None) & condition
        condition2 = (Post.c.parent != None) & condition
        order_by = [Post.c.floor]
        
        def created_on(value, obj):
            return date.to_local(value).strftime('%Y-%m-%d %H:%M:%S %Z')
        
        def content(value, obj):
            return self._get_post_content(obj)
        
        def username(value, obj):
            try:
                username = unicode(obj.posted_by)
            except NotFound:
                username = obj._posted_by_
            return username
        
        def userimage(value, obj):
            get_user_image = functions.get_user_image
            try:
                url = get_user_image(obj.posted_by)
            except NotFound:
                url = get_user_image()
            return url
        
        def actions(value, obj):
            if not request.user:
                return ''
            
            a = []
            is_manager = forum.managers.has(request.user)
            if obj.floor == 1 and obj.parent == None:
                #第一楼为主贴,可以允许关闭,顶置等操作
                if is_manager:
                    a.append('<a href="#" rel="%d" class="close_thread">%s</a>' % (obj.id, self.status['close'][obj.topic.closed]))
                    a.append('<a href="#" rel="%d" class="hidden">%s</a>' % (obj.id, self.status['hidden'][obj.topic.hidden]))
                    a.append('<a href="#" rel="%d" class="top">%s</a>' % (obj.id, self.status['sticky'][obj.topic.sticky]))
                    a.append('<a href="#" rel="%d" class="essence">%s</a>' % (obj.id, self.status['essence'][obj.topic.essence]))
                    a.append('<a href="#" rel="%d" class="homepage">%s</a>' % (obj.id, self.status['homepage'][obj.topic.homepage]))
                    a.append('<a href="#" rel="%d" class="enable_comment">%s</a>' % (obj.id, self.status['enable_comment'][obj.topic.enable_comment]))
                if is_manager or (obj.posted_by.id == request.user.id and obj.created_on+timedelta(days=settings.get_var('PARA/FORUM_EDIT_DELAY'))>=date.now()):
                    #作者或管理员且在n天之内,则可以编辑
                    url = url_for(ForumView.edit_topic, forum_id=forum_id, topic_id=topic_id)
                    a.append('<a href="%s" rel="%d" class="edit">编辑</a>' % (url, obj.id))
                if is_manager:
                    url = url_for(ForumView.remove_topic, forum_id=forum_id, topic_id=topic_id)
                    a.append('<a href="%s" rel="%d" class="delete_topic">删除主题</a>' % (url, obj.id))
                #处理贴子转移,管理员可以转移
                if is_manager or request.user.is_superuser:
                    url = url_for(ForumView.move_topic, forum_id=forum_id, topic_id=topic_id)
                    a.append('<a href="%s" rel="%d" class="move_topic">移动主题</a>' % (url, obj.id))
            else:
                if is_manager or (obj.posted_by.id == request.user.id and obj.created_on+timedelta(days=settings.get_var('PARA/FORUM_EDIT_DELAY'))>=date.now()):
                    #作者或管理员且在n天之内,则可以编辑
                    url = url_for(ForumView.edit_post, forum_id=forum_id, topic_id=topic_id, post_id=obj.id) + '?page=' + str(cur_page)
                    a.append('<a href="%s" rel="%d" class="edit_post">编辑</a>' % (url, obj.id))
                    
            if is_manager or (obj.posted_by.id == request.user.id):
                if (obj.deleted and (obj.deleted_by.id == request.user.id or is_manager)) or not obj.deleted:
                    a.append('<a href="#" rel="%d" class="delete">%s</a>' % (obj.id, self.status['delete'][obj.deleted]))
            try:
                obj.posted_by
                if obj.posted_by.id == request.user.id:    
                    a.append('<a href="#" rel="%d" class="email">%s</a>' % (obj.id, self.status['email'][obj.reply_email]))
            except NotFound:
                obj.posted_by = None
                obj.save()
            #只有允许评论时能可以回复
            if topic.enable_comment:
                a.append('<a href="/forum/%d/%d/%d/new_reply?page=%d">回复该作者</a>' % (forum_id, topic_id, obj.id, int(cur_page)))
            return ' | '.join(a)
        
        def updated(value, obj):
            if obj.floor == 1 and obj.topic.updated_on and not obj.parent:
                return u'<div class="updated">由 %s 于 %s 更新</div>' % (obj.topic.modified_user.username, timesince(obj.topic.updated_on))
        
        fields = ['topic', 'id', 'username', 'userimage', 'posted_by', 'content',
            'created_on', 'actions', 'floor', 'updated', 'parent',
            ]
        fields_convert_map = {'created_on':created_on, 'content':content,
            'username':username, 'userimage':userimage, 'actions':actions,
            'updated':updated}
        #view1 为生成一级回复,即回复主题
        view1 = ListView(Post, fields=fields, condition=condition1, order_by=order_by,
            rows_per_page=rows_per_page, pageno=pageno,
            fields_convert_map=fields_convert_map)
        #view2 为生成二级乃至多级回复
        view2 = ListView(Post, fields=fields, condition=condition2, order_by=order_by,
            pagination=False,
            fields_convert_map=fields_convert_map)
        key = '__topicvisited__:forumtopic:%s:%s:%s' % (request.remote_addr, forum_id, topic_id)
        cache = functions.get_cache()
        v = cache.get(key, None)
        if not v:
            Topic.filter(Topic.c.id==int(topic_id)).update(num_views=Topic.c.num_views+1)
            cache.set(key, 1, settings.get_var('PARA/FORUM_USER_VISITED_TIMEOUT'))
        
        slug = uuid.uuid1().hex
        
        #处理posts和sub_posts
        query = view1.query()
        posts = []
        sub_posts = {}
        def process_sub(ids):
            _ids = []
            for x in Post.filter(Post.c.parent.in_(ids)).order_by(Post.c.floor):
                obj = view2.object(x)
                d = sub_posts.setdefault(str(x._parent_), [])
                d.append(obj)
                _ids.append(x.id)
            if _ids:
                process_sub(_ids)
                
        ids = []
        for row in query:
            posts.append(view1.object(row))
            ids.append(row.id)
            
        process_sub(ids)
           
        pagination = functions.create_pagination(request.path+'?'+request.query_string, view1.total,
            pageno+1, rows_per_page)
        return {'forum':forum, 'topic':topic, 'slug':slug, 
            'has_email':bool(request.user and request.user.email), 
            'page':pageno+1, 'pagination':pagination,
            'posts':posts, 'sub_posts':sub_posts}