Browse Source

fix收藏夹多对多关系,add topic.js

topic.js file:回复点赞,主题投票,收藏相关操作
honmaple 9 years ago
parent
commit
d84877083e

+ 1 - 1
maple/__init__.py

@@ -6,7 +6,7 @@
 # Author: jianglin
 # Email: xiyang0807@gmail.com
 # Created: 2016-05-20 12:35:52 (CST)
-# Last Update:星期六 2016-6-25 1:0:54 (CST)
+# Last Update:星期一 2016-6-27 14:49:34 (CST)
 #          By:jianglin
 # Description:
 # **************************************************************************

+ 4 - 2
maple/extensions.py

@@ -6,7 +6,7 @@
 # Author: jianglin
 # Email: xiyang0807@gmail.com
 # Created: 2016-05-20 13:02:50 (CST)
-# Last Update:星期六 2016-6-25 11:13:8 (CST)
+# Last Update:星期一 2016-6-27 14:49:53 (CST)
 #          By:
 # Description:
 # **************************************************************************
@@ -67,7 +67,8 @@ def register_babel(app):
 def register_maple(app):
     Bootstrap(app,
               css=('styles/monokai.css', 'styles/mine.css'),
-              js=('styles/upload.js', 'styles/order.js', 'styles/mine.js'),
+              js=('styles/upload.js', 'styles/order.js', 'styles/mine.js',
+                  'styles/topic.js'),
               use_auth=True)
     Captcha(app)
     Error(app)
@@ -128,3 +129,4 @@ def register_jinja2(app):
     app.jinja_env.filters['get_online_users'] = load_online_users
     app.jinja_env.filters['markdown'] = Filters.safe_markdown
     app.jinja_env.filters['safe_clean'] = safe_clean
+    app.jinja_env.filters['is_collected'] = Filters.is_collected

+ 11 - 1
maple/filters.py

@@ -6,7 +6,7 @@
 # Author: jianglin
 # Email: xiyang0807@gmail.com
 # Created: 2016-06-15 00:39:29 (CST)
-# Last Update:星期一 2016-6-20 21:2:58 (CST)
+# Last Update:星期一 2016-6-27 12:33:39 (CST)
 #          By:
 # Description:
 # **************************************************************************
@@ -90,6 +90,16 @@ class Filters(object):
             replies = int(replies)
         return replies, read
 
+    def is_collected(topicId):
+        from maple.topic.models import CollectTopic
+        from flask_login import current_user
+        for collect in current_user.collects:
+            cid = CollectTopic.query.filter_by(collect_id=collect.id,
+                                               topic_id=topicId).first()
+            if cid is not None:
+                return True
+        return False
+
     class Title(object):
         title = setting['title']
         picture = setting['picture']

+ 35 - 13
maple/mine/views.py

@@ -6,12 +6,12 @@
 # Author: jianglin
 # Email: xiyang0807@gmail.com
 # Created: 2016-05-20 18:04:43 (CST)
-# Last Update:星期三 2016-6-15 19:6:23 (CST)
+# Last Update:星期一 2016-6-27 12:52:4 (CST)
 #          By:
 # Description:
 # **************************************************************************
 from flask import (Blueprint, render_template, request, redirect, url_for,
-                   jsonify)
+                   flash, jsonify)
 from flask.views import MethodView
 from flask_maple.forms import flash_errors
 from flask_login import current_user, login_required
@@ -30,30 +30,35 @@ site = Blueprint('mine', __name__)
 class CollectAPI(MethodView):
     decorators = [collect_permission]
 
-    def template_with_uid(self, topics, collect):
+    def template_with_uid(self, data):
         form = CollectForm()
+        collect = data['collect']
         form.name.data = collect.name
         form.description.data = collect.description
         form.is_privacy.data = 0 if collect.is_privacy else 1
-        data = {'topics': topics, 'collect': collect, 'form': form}
+        data_form = {'form': form}
+        data.update(data_form)
         return render_template('mine/collect.html', **data)
 
-    def template_without_uid(self, collects):
+    def template_without_uid(self, data):
         form = CollectForm()
-        data = {'collects': collects, 'form': form}
+        data_form = {'form': form}
+        data.update(data_form)
         return render_template('mine/collect_list.html', **data)
 
     def get(self, uid):
         page = is_num(request.args.get('page'))
         if uid is None:
-            topics = current_user.collects.paginate(page,
-                                                    app.config['PER_PAGE'],
-                                                    error_out=True)
-            return self.template_without_uid(topics)
+            collects = current_user.collects.paginate(page,
+                                                      app.config['PER_PAGE'],
+                                                      error_out=True)
+            data = {'collects': collects}
+            return self.template_without_uid(data)
         else:
             collect = Collect.query.filter_by(id=uid).first()
             topics = collect.topics.paginate(page, 10, True)
-            return self.template_with_uid(topics, collect)
+            data = {'collect': collect, 'topics': topics}
+            return self.template_with_uid(data)
 
     def post(self):
         form = CollectForm()
@@ -93,11 +98,28 @@ def add_collect():
     topic = Topic.query.filter_by(uid=topicId).first_or_404()
     for id in form:
         collect = Collect.query.filter_by(id=id).first_or_404()
-        collect.topics.append(topic)
-        db.session.commit()
+        if topic in collect.topics:
+            flash('This topic has been collected in %s' % collect.name,
+                  'warning')
+        else:
+            collect.topics.append(topic)
+            db.session.commit()
     return redirect(url_for('topic.topic', uid=topic.uid))
 
 
+@site.route('/delete-from-collect', methods=['DELETE'])
+@login_required
+def delete_collect():
+    data = request.get_json()
+    topicId = data['topicId']
+    collectId = data['collectId']
+    topic = Topic.query.filter_by(uid=topicId).first_or_404()
+    collect = Collect.query.filter_by(id=collectId).first_or_404()
+    collect.topics.remove(topic)
+    db.session.commit()
+    return jsonify(judge=True)
+
+
 class LikeAPI(MethodView):
     decorators = [like_permission]
 

+ 14 - 1
maple/static/assets/home.js

@@ -23,4 +23,17 @@ else
 {$.ajax({type:"POST",url:"/user/follow",data:data,contentType:'application/json;charset=UTF-8',success:function(result){if(result.judge===true)
 {obj.text('取消关注').addClass('active');}else
 {alert('asd');}}});}}
-$(document).ready(function(){$('button.tagfollow').click(function(){var _$this=$(this);var data=JSON.stringify({id:_$this.attr("id"),type:'tag'});Follow(_$this,data);});$('button.topicfollow').click(function(){var _$this=$(this);var data=JSON.stringify({id:_$this.attr("id"),type:'topic'});Follow(_$this,data);});$('button.collectfollow').click(function(){var _$this=$(this);var data=JSON.stringify({id:_$this.attr("id"),type:'collect'});Follow(_$this,data);});});
+$(document).ready(function(){$('button.tagfollow').click(function(){var _$this=$(this);var data=JSON.stringify({id:_$this.attr("id"),type:'tag'});Follow(_$this,data);});$('button.topicfollow').click(function(){var _$this=$(this);var data=JSON.stringify({id:_$this.attr("id"),type:'topic'});Follow(_$this,data);});$('button.collectfollow').click(function(){var _$this=$(this);var data=JSON.stringify({id:_$this.attr("id"),type:'collect'});Follow(_$this,data);});});function DoCollect(collectData){$(document).ready(function(){$('button#edit-collect-form').click(function(){var data=JSON.stringify({name:$('#name').val(),description:$('#description').val(),is_privacy:$("input[name='is_privacy']:checked").val()});$.ajax({type:"PUT",url:collectData.edit_url,data:data,contentType:'application/json;charset=UTF-8',success:function(result){if(result.judge==true)
+{window.location=collectData.edit_url;}}});});$('button#delete-collect-form').click(function(){$.ajax({type:"DELETE",url:collectData.delete_url,data:JSON.stringify(),contentType:'application/json;charset=UTF-8',success:function(result){if(result.judge==true)
+{window.location=collectData.url;}}});});$('#delete-from-collect').click(function(){var _$this=$(this);var topicId=_$this.attr('data-id');var collectId=collectData.collectId;var data=JSON.stringify({collectId:collectId,topicId:topicId});$.ajax({type:"DELETE",url:collectData.delete,data:data,contentType:'application/json;charset=UTF-8',success:function(result){if(result.judge==true)
+{_$this.parent().remove();}}});});});}
+function DoLike(replyData){$(document).ready(function(){$('.like-reply').click(function(){var _$this=$(this);var replyId=_$this.attr('data-id');var data=JSON.stringify({uid:replyId});if(_$this.hasClass('like-active')){$.ajax({type:"DELETE",url:replyData.like,data:data,contentType:'application/json;charset=UTF-8',success:function(result){if(result.judge===true)
+{_$this.attr("title","赞");_$this.removeClass("like-active");_$this.addClass("like-no-active");}else
+{window.location.href=result.url;}}});}else{$.ajax({type:"POST",url:replyData.like,data:data,contentType:'application/json;charset=UTF-8',success:function(result){if(result.judge===true)
+{_$this.attr("title","取消赞");_$this.removeClass("like-no-active");_$this.addClass("like-active");}else
+{window.location.href=result.url;}}});}});$('.reply-author').click(function(){var _$this=$(this);var author=_$this.attr('data-id');$('#content').focus();$('#content').val('@'+author+' ');});});}
+function DoVote(voteData){$(document).ready(function(){$('#topic-up-vote').click(function(){var data=JSON.stringify({});$.ajax({type:"POST",url:voteData.vote_up,data:data,contentType:'application/json;charset=UTF-8',success:function(result){if(result.judge)
+{$('.votes').html(result.html);}else
+{window.location.href=result.url;}}});});$('#topic-down-vote').click(function(){var data=JSON.stringify({});$.ajax({type:"POST",url:voteData.vote_down,data:data,contentType:'application/json;charset=UTF-8',success:function(result){if(result.judge)
+{$('.votes').html(result.html);}else
+{window.location.href=result.url;}}});});});}

+ 58 - 0
maple/static/styles/mine.js

@@ -53,3 +53,61 @@ $(document).ready(function(){
     Follow(_$this,data);
   });
 });
+function DoCollect(collectData) {
+  $(document).ready(function(){
+    $('button#edit-collect-form').click(function() {
+      var data = JSON.stringify({
+        name:$('#name').val(),
+        description:$('#description').val(),
+        is_privacy:$("input[name='is_privacy']:checked").val()
+      });
+      $.ajax ({
+        type : "PUT",
+        url : collectData.edit_url,
+        data:data,
+        contentType: 'application/json;charset=UTF-8',
+        success: function(result) {
+          if (result.judge == true)
+          {
+            window.location =collectData.edit_url ;
+          }
+        }
+      });
+    });
+    $('button#delete-collect-form').click(function() {
+      $.ajax ({
+        type : "DELETE",
+        url : collectData.delete_url,
+        data:JSON.stringify(),
+        contentType: 'application/json;charset=UTF-8',
+        success: function(result) {
+          if (result.judge == true)
+          {
+            window.location = collectData.url;
+          }
+        }
+      });
+    });
+    $('#delete-from-collect').click(function() {
+      var _$this = $(this);
+      var topicId = _$this.attr('data-id');
+      var collectId = collectData.collectId;
+      var data = JSON.stringify({
+        collectId:collectId,
+        topicId:topicId
+      });
+      $.ajax ({
+        type : "DELETE",
+        url : collectData.delete,
+        data:data,
+        contentType: 'application/json;charset=UTF-8',
+        success: function(result) {
+          if (result.judge == true)
+          {
+            _$this.parent().remove();
+          }
+        }
+      });
+    });
+  });
+}

+ 91 - 0
maple/static/styles/topic.js

@@ -0,0 +1,91 @@
+function DoLike(replyData) {
+  $(document).ready(function(){
+    $('.like-reply').click(function() {
+      var _$this = $(this);
+      var replyId = _$this.attr('data-id');
+      var data = JSON.stringify({
+        uid:replyId
+      });
+      if(_$this.hasClass('like-active')){
+        $.ajax ({
+          type : "DELETE",
+          url : replyData.like,
+          data:data,
+          contentType: 'application/json;charset=UTF-8',
+          success: function(result) {
+            if (result.judge === true)
+            {
+              _$this.attr("title","赞");
+              _$this.removeClass("like-active");
+              _$this.addClass("like-no-active");
+            } else
+            {
+              window.location.href = result.url;
+            }
+          }});
+      }else {
+        $.ajax ({
+          type : "POST",
+          url : replyData.like,
+          data:data,
+          contentType: 'application/json;charset=UTF-8',
+          success: function(result) {
+            if (result.judge === true)
+            {
+              _$this.attr("title","取消赞");
+              _$this.removeClass("like-no-active");
+              _$this.addClass("like-active");
+            } else
+            {
+              window.location.href = result.url;
+            }
+          }});
+      }});
+    $('.reply-author').click(function() {
+      var _$this = $(this);
+      var author = _$this.attr('data-id');
+      $('#content').focus();
+      $('#content').val('@' + author + ' ');
+    });
+  });
+}
+function DoVote(voteData) {
+  $(document).ready(function(){
+    $('#topic-up-vote').click(function() {
+      var data = JSON.stringify({
+      });
+      $.ajax ({
+        type : "POST",
+        url : voteData.vote_up,
+        data:data,
+        contentType: 'application/json;charset=UTF-8',
+        success: function(result) {
+          if (result.judge)
+          {
+            $('.votes').html(result.html);
+          } else
+          {
+            window.location.href = result.url;
+          }
+        }});
+    });
+    $('#topic-down-vote').click(function() {
+      var data = JSON.stringify({
+      });
+      $.ajax ({
+        type : "POST",
+        url : voteData.vote_down,
+        data:data,
+        contentType: 'application/json;charset=UTF-8',
+        success: function(result) {
+          if (result.judge)
+          {
+            $('.votes').html(result.html);
+          } else
+          {
+            window.location.href = result.url;
+          }
+        }});
+    });
+  });
+}

+ 11 - 53
maple/templates/mine/collect.html

@@ -2,56 +2,14 @@
 {% block script %}
 {{ super()}}
 <script type=text/javascript>
- $(document).ready(function(){
-     $('button#editform').click(function() {
-         var data = JSON.stringify({
-             name:$('#name').val(),
-             description:$('#description').val(),
-             is_privacy:$("input[name='is_privacy']:checked").val()
-         });
-         $.ajax ({
-             type : "PUT",
-             url : "{{ url_for('mine.collect',uid = collect.id)}}",
-             data:data,
-             contentType: 'application/json;charset=UTF-8',
-             success: function(result) {
-                 if (result.judge == true)
-                 {
-                     window.location = '{{ url_for('mine.collect',uid = collect.id)}}';
-                 }
-                 else
-                 {
-                     alert(result.error);
-                     alert(data)
-                 }
-             }
-         });
-     });
-     $('button#deleteform').click(function() {
-         /* var data = JSON.stringify({
-            name:$('#name').val(),
-            description:$('#description').val(),
-            is_privacy:$("input[name='is_privacy']:checked").val()
-            }); */
-         $.ajax ({
-             type : "DELETE",
-             url : "{{ url_for('mine.collect',uid = collect.id)}}",
-             data:JSON.stringify(),
-             contentType: 'application/json;charset=UTF-8',
-             success: function(result) {
-                 if (result.judge == true)
-                 {
-                     window.location = '{{ url_for('mine.collect')}}';
-                 }
-                 else
-                 {
-                     alert(result.error);
-                     alert(data)
-                 }
-             }
-         });
-     });
- });
+ var collectData = {
+     'url':'{{ url_for('mine.collect')}}',
+     'edit_url':'{{ url_for('mine.collect',uid = collect.id)}}',
+     'delete_url':"{{ url_for('mine.collect',uid = collect.id)}}",
+     'collectId':"{{ collect.id}}",
+     'delete':"{{ url_for('mine.delete_collect')}}"
+ }
+ DoCollect(collectData);
 </script>
 {% endblock %}
 {% block content %}
@@ -68,7 +26,7 @@
             {% for topic in topics.items %}
             <div class="panel-body" style="border-bottom:1px solid #eee">
                 <a href="{{ url_for('topic.topic',uid=topic.uid)}}">{{ topic.title}}</a>
-                <span class="pull-right btn btn-sm btn-danger">删除</span>
+                <span id="delete-from-collect" class="pull-right btn btn-sm btn-danger" data-id="{{ topic.uid }}">删除</span>
             </div>
             {% endfor %}
             {% else %}
@@ -110,7 +68,7 @@
                 </div>
                 <div class="modal-footer">
                     <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
-                    <button type="button" id="editform" class="btn btn-primary">提交</button>
+                    <button type="button" id="edit-collect-form" class="btn btn-primary">提交</button>
                 </div>
             </form>
         </div>
@@ -129,7 +87,7 @@
             </div>
             <div class="modal-footer" style="padding-top:5px;padding-bottom:5px;">
                 <button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
-                <button type="button" id="deleteform" class="btn btn-danger">删除</button>
+                <button type="button" id="delete-collect-form" class="btn btn-danger">删除</button>
             </div>
         </div>
     </div>

+ 21 - 49
maple/templates/topic/content.html

@@ -1,9 +1,6 @@
 {% extends 'base/base.html' %}
-{% block content %}
-{% set board = topic.board %}
-{{ breadcrumb(hrefs={board.parent_board:url_for('board.board',parent_b=board.parent_board),
-board.board:url_for('board.board',parent_b=board.parent_board,child_b=board.board)},active=topic.title)}}
-{% set last_reply = topic.replies.first() %}
+{% block style %}
+{{ super() }}
 <style>
  .vote {
      font-size: 10px;
@@ -19,48 +16,23 @@ board.board:url_for('board.board',parent_b=board.parent_board,child_b=board.boar
      text-decoration: none;
  }
 </style>
+{% endblock %}
+{% block script -%}
+{{ super() }}
 <script type="text/javascript">
- function upVoteTopic(topicId) {
-     if (g.csrftoken) {
-         var data = JSON.stringify({
-         });
-         $.ajax ({
-             type : "POST",
-             url : "{{ url_for('topic.vote_up',topicId=topic.uid)}}",
-             data:data,
-             contentType: 'application/json;charset=UTF-8',
-             success: function(result) {
-                 if (result.judge)
-                 {
-                     $('.votes').html(result.html);
-                 } else
-                 {
-                     window.location.href = result.url;
-                 }
-             }});
-     }
- }
- function downVoteTopic(topicId) {
-     if (g.csrftoken) {
-         var data = JSON.stringify({
-         });
-         $.ajax ({
-             type : "POST",
-             url : "{{ url_for('topic.vote_down',topicId=topic.uid)}}",
-             data:data,
-             contentType: 'application/json;charset=UTF-8',
-             success: function(result) {
-                 if (result.judge)
-                 {
-                     $('.votes').html(result.html);
-                 } else
-                 {
-                     window.location.href = result.url;
-                 }
-             }});
-     }
- }
+ var voteData = {
+     'vote_up': "{{ url_for('topic.vote_up',topicId=topic.uid)}}",
+     'vote_down': "{{ url_for('topic.vote_down',topicId=topic.uid)}}"
+ };
+ DoVote(voteData);
 </script>
+{%- endblock script %}
+
+{% block content %}
+{% set board = topic.board %}
+{{ breadcrumb(hrefs={board.parent_board:url_for('board.board',parent_b=board.parent_board),
+board.board:url_for('board.board',parent_b=board.parent_board,child_b=board.board)},active=topic.title)}}
+{% set last_reply = topic.replies.first() %}
 {% from 'base/paginate.html' import footer as p_footer %}
 <div class="row">
     <div class="col-md-9">
@@ -71,20 +43,20 @@ board.board:url_for('board.board',parent_b=board.parent_board,child_b=board.boar
                     <small style="color:#999">
                         <div class="votes">
                             {% if topic.vote and topic.vote > 0 -%}
-                            <a class="vote" href="javascript:void(0)" onclick="upVoteTopic({{ topic.uid }});" style="text-decoration:none;">
+                            <a id="topic-up-vote" class="vote" href="javascript:void(0)" style="text-decoration:none;">
                                 <i class="icon-chevron-up">{{ topic.vote}}</i>
                             </a>
                             {% else %}
-                            <a class="vote" href="javascript:void(0)" onclick="upVoteTopic({{ topic.uid }});" style="text-decoration:none;">
+                            <a id="topic-up-vote" class="vote" href="javascript:void(0)" style="text-decoration:none;">
                                 <i class="icon-chevron-up"></i>
                             </a>
                             {%- endif %}
                             {% if topic.vote and topic.vote < 0 %}
-                            <a class="vote" href="javascript:void(0)" onclick="downVoteTopic({{ topic.uid }});" style="text-decoration:none;">
+                            <a id="topic-down-vote" class="vote" href="javascript:void(0)" style="text-decoration:none;">
                                 <i class="icon-chevron-down">{{ topic.vote}}</i>
                             </a>
                             {% else %}
-                            <a class="vote" href="javascript:void(0)" onclick="downVoteTopic({{ topic.uid }});" style="text-decoration:none;">
+                            <a id="topic-down-vote" class="vote" href="javascript:void(0)" style="text-decoration:none;">
                                 <i class="icon-chevron-down"></i>
                             </a>
                             {%- endif %}

+ 5 - 1
maple/templates/topic/panel.html

@@ -5,6 +5,9 @@
     {% else %}
     <button type="button" class="btn btn-info btn-block topicfollow" id="{{ topic.id }}">关注问题</button>
     {% endif %}
+    {% if topic.id | is_collected %}
+    <span class="btn btn-default btn-block">已收藏</span>
+    {% else %}
     <span class="btn btn-default btn-block" data-toggle="modal" data-target="#sidecollect">收藏问题</span>
     <div class="modal fade" id="sidecollect" tabindex="-1" role="dialog" aria-labelledby="sidecollectLabel">
         <div class="modal-dialog" role="document">
@@ -34,7 +37,8 @@
                 </form>
             </div>
         </div>
-                        </div>
+        </div>
+    {% endif %}
 </ul>
 {% endif %}
 {% include 'base/panel.html' %}

+ 5 - 50
maple/templates/topic/replies.html

@@ -7,55 +7,10 @@
  }
 </style>
 <script type="text/javascript">
- $(document).ready(function(){
-     $('.like-reply').click(function() {
-         var _$this = $(this);
-         var replyId = _$this.attr('data-id');
-         var data = JSON.stringify({
-             uid:replyId
-         });
-         if(_$this.hasClass('like-active')){
-             $.ajax ({
-                 type : "DELETE",
-                 url : "{{ url_for('mine.like') }}",
-                 data:data,
-                 contentType: 'application/json;charset=UTF-8',
-                 success: function(result) {
-                     if (result.judge === true)
-                     {
-                         _$this.attr("title","赞");
-                         _$this.removeClass("like-active");
-                         _$this.addClass("like-no-active");
-                     } else
-                     {
-                         window.location.href = result.url;
-                     }
-                 }});
-         }else {
-             $.ajax ({
-                 type : "POST",
-                 url : "{{ url_for('mine.like') }}",
-                 data:data,
-                 contentType: 'application/json;charset=UTF-8',
-                 success: function(result) {
-                     if (result.judge === true)
-                     {
-                         _$this.attr("title","取消赞");
-                         _$this.removeClass("like-no-active");
-                         _$this.addClass("like-active");
-                     } else
-                     {
-                         window.location.href = result.url;
-                     }
-                 }});
-         }});
-     $('.reply-author').click(function() {
-         var _$this = $(this);
-         var author = _$this.attr('data-id');
-         $('#content').focus();
-         $('#content').val('@' + author + ' ');
-     })
- });
+ var replyData = {
+     'like':"{{ url_for('mine.like') }}",
+ }
+ DoLike(replyData);
 </script>
 <div class="panel panel-default" id="replies-content">
     <div class="panel-heading">
@@ -115,7 +70,7 @@
         <form action="{{ url_for('topic.reply',uid=topic.id)}}" method="POST">
             {{ form.hidden_tag() }}
             {{ form.content(class='form-control')}}
-            <button class="btn btn-sm btn-primary" type="submit">提交问题</button>
+            <button class="btn btn-sm btn-primary" type="submit">提交回复</button>
         </form>
     </div>
     {% else %}

+ 18 - 8
maple/topic/controls.py

@@ -6,7 +6,7 @@
 # Author: jianglin
 # Email: xiyang0807@gmail.com
 # Created: 2016-06-15 10:22:42 (CST)
-# Last Update:星期六 2016-6-25 13:4:49 (CST)
+# Last Update:星期一 2016-6-27 14:36:20 (CST)
 #          By:
 # Description:
 # **************************************************************************
@@ -52,25 +52,35 @@ class TopicModel(object):
         RedisData.set_topics()
         return topic
 
-    def vote(uid, count):
+    def vote(count):
         if count > 0:
             html = '''
-                    <a class="vote" href="javascript:void(0)" onclick="upVoteTopic(%s);" style="text-decoration:none;">
+                    <a id="topic-up-vote" class="vote" href="javascript:void(0)" style="text-decoration:none;">
                         <i class="icon-chevron-up">%d</i>
                     </a>
-                    <a class="vote" href="javascript:void(0)" onclick="downVoteTopic(%s);" style="text-decoration:none;">
+                    <a id="topic-down-vote" class="vote" href="javascript:void(0)" style="text-decoration:none;">
                         <i class="icon-chevron-down"></i>
                     </a>
-            ''' % (uid, count, uid)
+            ''' % (count)
+        elif count == 0:
+            html = '''
+                    <a id="topic-up-vote" class="vote" href="javascript:void(0)" style="text-decoration:none;">
+                        <i class="icon-chevron-up"></i>
+                    </a>
+                    <a  id="topic-down-vote" class="vote" href="javascript:void(0)" style="text-decoration:none;">
+                        <i class="icon-chevron-down"></i>
+                    </a>
+            '''
+
         else:
             html = '''
-                    <a class="vote" href="javascript:void(0)" onclick="upVoteTopic(%s);" style="text-decoration:none;">
+                    <a id="topic-up-vote" class="vote" href="javascript:void(0)" style="text-decoration:none;">
                         <i class="icon-chevron-up"></i>
                     </a>
-                    <a class="vote" href="javascript:void(0)" onclick="downVoteTopic(%s);" style="text-decoration:none;">
+                    <a  id="topic-down-vote" class="vote" href="javascript:void(0)" style="text-decoration:none;">
                         <i class="icon-chevron-down">%d</i>
                     </a>
-            ''' % (uid, uid, count)
+            ''' % (count)
         return html
 
 

+ 13 - 8
maple/topic/models.py

@@ -6,7 +6,7 @@
 # Author: jianglin
 # Email: xiyang0807@gmail.com
 # Created: 2016-05-20 13:32:12 (CST)
-# Last Update:星期六 2016-6-25 16:40:1 (CST)
+# Last Update:星期一 2016-6-27 12:13:37 (CST)
 #          By:
 # Description:
 # **************************************************************************
@@ -67,13 +67,6 @@ class Topic(db.Model):
     # is_top = db.Column(db.Integer, default = 0)
     is_markdown = db.Column(db.Boolean, default=False)
     is_draft = db.Column(db.Boolean, default=False)
-    collect_id = db.Column(db.Integer,
-                           db.ForeignKey('collects.id',
-                                         ondelete="CASCADE"))
-    collect = db.relationship('Collect',
-                              backref=db.backref('topics',
-                                                 cascade='all,delete-orphan',
-                                                 lazy='dynamic'))
 
     __mapper_args__ = {"order_by": publish.desc()}
 
@@ -110,6 +103,13 @@ class Reply(db.Model):
     __mapper_args__ = {"order_by": publish.desc()}
 
 
+class CollectTopic(db.Model):
+    __tablename__ = 'collect_topic'
+    id = db.Column(db.Integer, primary_key=True)
+    topic_id = db.Column(db.Integer, db.ForeignKey('topics.id'))
+    collect_id = db.Column(db.Integer, db.ForeignKey('collects.id'))
+
+
 class Collect(db.Model):
     __tablename__ = 'collects'
     id = db.Column(db.Integer, primary_key=True)
@@ -124,6 +124,11 @@ class Collect(db.Model):
                                                 cascade='all,delete-orphan',
                                                 lazy='dynamic'))
 
+    topics = db.relationship('Topic',
+                             secondary='collect_topic',
+                             lazy='dynamic',
+                             backref="collects")
+
     def __repr__(self):
         return "<Collect %r>" % self.name
 

+ 9 - 9
maple/topic/views.py

@@ -6,7 +6,7 @@
 # Author: jianglin
 # Email: xiyang0807@gmail.com
 # Created: 2016-05-20 13:47:04 (CST)
-# Last Update:星期六 2016-6-25 17:55:55 (CST)
+# Last Update:星期一 2016-6-27 14:30:59 (CST)
 #          By:
 # Description:
 # **************************************************************************
@@ -75,7 +75,7 @@ def vote_up(topicId):
     else:
         topic.vote += 1
     db.session.commit()
-    html = TopicModel.vote(topicId, topic.vote)
+    html = TopicModel.vote(topic.vote)
     return jsonify(judge=True, html=html)
 
 
@@ -89,19 +89,17 @@ def vote_down(topicId):
     else:
         topic.vote -= 1
     db.session.commit()
-    html = TopicModel.vote(topicId, topic.vote)
+    html = TopicModel.vote(topic.vote)
     return jsonify(judge=True, html=html)
 
 
 class TopicAPI(MethodView):
     decorators = [topic_permission]
 
-    def template_with_uid(self, form, topic, replies):
-        data = {'topic': topic, 'replies': replies, 'form': form}
+    def template_with_uid(self, data):
         return render_template('topic/content.html', **data)
 
-    def template_without_uid(self, topics, top_topics):
-        data = {'topics': topics, 'top_topics': top_topics}
+    def template_without_uid(self, data):
         return render_template('topic/topic.html', **data)
 
     def get(self, uid):
@@ -111,14 +109,16 @@ class TopicAPI(MethodView):
                 page, app.config['PER_PAGE'],
                 error_out=True)
             top_topics = Topic.query.filter_by(is_top=True).limit(5).all()
-            return self.template_without_uid(topics, top_topics)
+            data = {'topics': topics, 'top_topics': top_topics}
+            return self.template_without_uid(data)
         else:
             form = ReplyForm()
             topic = Topic.query.filter_by(uid=str(uid)).first_or_404()
             replies = topic.replies.paginate(page, app.config['PER_PAGE'],
                                              True)
             RedisData.set_read_count(topic.id)
-            return self.template_with_uid(form, topic, replies)
+            data = {'form': form, 'topic': topic, 'replies': replies}
+            return self.template_with_uid(data)
 
     def post(self):
         form = TopicForm()