cvmachine.com - 申博开户网

查找: 您的方位主页 > 电脑频道 > 电脑教程 > 阅览资讯:Flask项目新经资讯项目总结

Flask项目新经资讯项目总结

2019-03-28 04:42:32 来历:www.cvmachine.com 【

新经资讯是一个包含新闻主页,新闻概况,用户中心和后台办理等模块的Flask项目

  1. 项目结构的建立

    • 包含装备信息:mysql,redis,session等
    • 工厂函数产出多种装备的app,数据库目标db,redis_store等
    • 日志的记载
    • 第三方库:云通讯,七牛云
    • 设置的常量,自界说状况码,commons,models等
    • flask_script,flask_migrate等
  2. 依据需求剖析E-R图,构建模型类

    ![](D:\Users\Liu xiangyu\Desktop\新经资讯E-R图.png)

  3. 新闻主页和概况页模块

    3.1 登录/注册/登出/状况坚持(略),以下代码生成图片验证码,在form表单翻开时调用

    # 后端回来图片验证码运用呼应体目标
    resp = make_response(image)
    # 设置内容类型
    resp.headers['Content-Type'] = 'image/jpg'
    return resp
    
    // 生成一个图片验证码的编号,并设置页面中图片验证码img标签的src特点
    function generateImageCode() {
      // 1. 生成一个编号
      // 严厉一点的运用uuid确保编号仅有, 不是很谨慎的状况下,也能够运用时刻戳
      imageCodeId = generateUUID();
      // 2. 拼接验证码地址
      var imageCodeUrl = "/passport/image_code?code_id=" + imageCodeId;
      // 3. 设置页面中图片验证码img标签的src特点
      $(".get_pic_code").attr("src", imageCodeUrl)}
    
    // 一个最根底的ajax恳求,担任给后端发送数据
    var params = {
        "mobile": mobile,
        "smscode": smscode,
        "password": password,}
      $.ajax({
        url:"/passport/register",
        type: "post",
        headers: {
        "X-CSRFToken": getCookie("csrf_token")},
        data: JSON.stringify(params),
        contentType: "application/json",
        success: function (resp) {
          if (resp.errno == "0"){
            // 改写当时界面
            location.reload()
          }else {
            $("#register-password-err").html(resp.errmsg)
            $("#register-password-err").show()
          } } } )
    

    3.2 新闻点击排行

    • 查询新闻表依照点击次数排序,转化成字典列表后回来数据并烘托模板

      news_list = News.query.
      order_by(News.clicks.desc()).limit(constants.CLICK_RANK_MAX_NEWS)
      

      模板展现数据

      <ul class="rank_list">
        {% for news in data.click_news_list %}
          <li><span class="{{ loop.index0 | indexClass }}">{{ loop.index }}</span><a href="#">{{ news.title }}</a></li>
        {% endfor %}
      </ul>
      

    3.3 新闻分类展现(同租房城区列表,略)

    categories = Category.query.all()
    

    3.4 新闻列表完成

    • 获取第几页page,每页数量per_page,分类category_id参数

    • 查验参数后,查询数据并分页,后端有合作的js代码,概况见下文

      filters = []
      # 假如分类id不为1,那么增加分类id的过滤
      if category_id != "1":  
        filters.append(News.category_id == category_id)
      paginate = News.query.filter(*filters).
      order_by(News.create_time.desc()).paginate(page, per_page, False)
      
    • 回来json数据,包含 total_pages,current_page,和新闻数据

    3.5 界说一个装修器判别用户是否登录

    def user_login_data(f):
    #装修器会改动被装修函数的端点称号,选用此手法去除影响
      @functools.wraps(f)
      def wrapper(*args, **kwargs):
        # 获取到当时登录用户的id
        user_id = session.get("user_id")
        # 经过id获取用户信息
        user = None
        if user_id:
          from info.models import User
          user = User.query.get(user_id)
        g.user = user
        return f(*args, **kwargs)
      return wrapper
    

    3.6 概况页新闻展现

    • 获取news_id,查询news目标
    • 和 user_info数据,新闻点击列表数据一起传给概况页模板进行烘托

    3.7 保藏和撤销保藏(前后端不别离的开发方法耦合度高,在这里表现的很明显,新闻概况页这个要烘托的模板中触及的数据就许多,包含:is_collected,user_info,news,click_news_list,is_followed,comments等,要挤在一个视图函数中)

    • 判别用户登录,获取 news_id,action

    • 查验参数,获取新闻目标

    • 依据action挑选:append(news),仍是remove(news),回来的是json数据。

      if action == "collect":
      user.collection_news.append(news)
      else:
      user.collection_news.remove(news)
      

    3.8 新闻谈论

    • 判别用户是否登录,获取参数 news_id,comment_str,parent_id
    • 查验参数,重点是判别新闻是否存在
    • 创立谈论模型类,保存数据提交,并且经过json回来谈论数据(新闻概况页模板烘托时需求传谈论数据,见下文)。

    3.9 谈论列表

    • 获取news_id,取出新闻一切谈论目标

      comments = Comment.query.filter(Comment.news_id == news_id).
      order_by(Comment.create_time.desc()).all()
      
      comment_list=[item.to_dict() for item in comments]
      
    • 放入传给模板文件的data中,模板内判别是否有父谈论

      {% if comment.parent %}
            <div class="reply_text_con fl">
              <div class="user_name2">
                {{ comment.parent.user.nick_name }}</div>
            <div class="reply_text">
               {{ comment.parent.content }}
             </div>
            </div>
      {% endif %}
      

    3.9 点赞

    • 前端获取 comment_id,news_id,action参数,参数查验和用户登录查验

    • 依据comment_id取出谈论目标,依据 action 决议增加 comment_like 目标仍是 remove(comment_like)目标,并对 comment.like_count 进行相应加减。以下是前端对应代码:

      success: function (resp) {
            if (resp.errno == "0") {
              // 更新点赞按钮图标
              if (action == "add") {
                // 代表是点赞
                $this.addClass('has_comment_up')
              }else {
                $this.removeClass('has_comment_up')
              }
            }else if (resp.errno == "4101"){
              $('.login_form_con').show();
            }else {
              alert(resp.errmsg)
            }
          }
      
    • 取出该新闻下一切 谈论目标,继而经过 谈论id 取出 一切点赞目标,继而生成 被用户点赞的谈论的id 组成的列表

      comments = Comment.query.
      filter(Comment.news_id == news_id).
      order_by(Comment.create_time.desc()).all()
      
      comment_ids = [comment.id for comment in comments]
      
      comment_likes = 
      CommentLike.query.filter
      (CommentLike.comment_id.in_(comment_ids),                            CommentLike.user_id == g.user.id).all()
      
      comment_like_ids = 
      [comment_like.comment_id for comment_like in comment_likes]
      
    • 先假定用户没有点赞谈论,再判别该谈论id是否在comment_like_ids,假如在如下操作,和用户保藏是类似的套路,并且都需求传给模板烘托。

      comment_dict["is_like"] = True
      
  4. 个人中心

    4.1 修正用户信息

    • 后端更新并保存数据,更改状况坚持即可

    • 前端成功回调函数,多处name都要改动

      if (resp.errno == "0") {
      // 更新父窗口内容
      $('.user_center_name', parent.document).html(params['nick_name'])
      $('#nick_name', parent.document).html(params['nick_name'])
      $('.input_sub').blur()
      }else { 
      alert(resp.errmsg) }
      

    4.2 用户保藏数据加载

    • 先获取页数参数,设定默许值

      collections = []
      current_page = 1
      total_page = 1
      
    • 进行分页数据查询,给默许数据赋值,处理保藏数据列表后回来数据。前端展现分页界面的代码如下,内部的 currentPage,totalPage 是全局变量。

      paginate = user.collection_news.paginate(p,constants.USER_COLLECTION_MAX_NEWS, False)
      collections = paginate.items
      current_page = paginate.page
      total_page = paginate.pages
      
      $(function() {
            $("#pagination").pagination({
              currentPage: {{ data.current_page }},
              totalPage: {{ data.total_page }},
              callback: function(current) {
                window.location.href = "/user/collection?p=" + current
              }
            });
          });
      

    4.2 用户发布新闻

    • 获取新闻分类的数据,但要pop掉 ‘最新’

      categories = Category.query.all()
      categories_dicts = [categorie.to_dict() for categorie in categories]
      categories_dicts.pop(0)
      
    • 获取前端提交的数据:title,digest,content,index_image,category_id,参数查验

    • 读取图片上传七牛云,初始化新闻目标存储数据,设置 news.status=1

    4.3 用户新闻列表(略)

  5. 其他

    5.1 重视和撤销重视

    • 获取 user_id,action 参数,获取发布新闻的用户目标

    • 依据action采纳履行不同句子,回来json数据

      if action == "follow":
      if target_user.followers.filter(User.id == g.user.id).count() > 0:
      return jsonify(errno=RET.DATAEXIST, errmsg="当时已重视")
      target_user.followers.append(g.user)
      else:
      if target_user.followers.filter(User.id == g.user.id).count() > 0:
      target_user.followers.remove(g.user)
      
      // 重视当时新闻作者
      $(".focus").click(function () {
        var user_id = $(this).attr('data-userid')
        var params = {
          "action": "follow",
          "user_id": user_id
        }
        $.ajax({
          url: "/news/followed_user",
          type: "post",
          contentType: "application/json",
          headers: {
            "X-CSRFToken": getCookie("csrf_token")
          },
          data: JSON.stringify(params),
          success: function (resp) {
            if (resp.errno == "0") {
              // 重视成功
              var count = parseInt($(".follows b").html());
              count++;
              $(".follows b").html(count + "")
              $(".focus").hide()
              $(".focused").show()
            }else if (resp.errno == "4101"){
              // 未登录,弹出登录框
              $('.login_form_con').show();
            }else {
              // 重视失利
              alert(resp.errmsg)
            } } }) })
      

    5.2 其他用户界面

    • 获取其他用户id,查验参数后,取出该用户目标

    • 判别是否重视

      is_followed = False
        if g.user:
          if other.followers.filter(User.id == user.id).count() > 0:
            is_followed = True
      
    • 其他用户新闻列表(略)

  6. 后台

    6.1 办理员登录

    • GET恳求获取模板页面后,前端提交两个参数 username,password

    • 经过username取出用户目标,做暗码验证

      if not user.check_passowrd(password):
          return render_template('admin/login.html', errmsg="暗码过错")
      
    • 一起验证用户是否是办理员

      {% if errmsg %}
      <div class="error_tip" style="display: block">{{ errmsg }}</div>
      {% endif %}
      
    • 运用端点名重定向到后台主页

      return redirect(url_for('admin.admin_index'))
      

    6.2 用户计算

    • 获取到本月第1天0点0分0秒的时刻目标,然后查询最终一次登录比其大的一切数据

      now = time.localtime()
      mon_begin = '%d-%02d-01'%(now.tm_year, now.tm_mon)
      mon_begin_begin = datetime.strptime(mon_begin, '%Y-%m-%d)
      mon_count =User.query.
      filter(User.is_admin == False, User.create_time >= mon_begin_date).count()
      
    • 获取到当日0点0分0秒时刻目标,然后查询最终一次登录比其大的一切数据

      day_begin = '%d-%02d-%02d' % (now.tm_year, now.tm_mon, now.tm_mday)
      day_bedin_date = datetime.strptime(day_begin, '%Y-%m-%d)
      day_count = User.query.
      filter(User.is_admin == False, User.create_time >= day_begin_date).count()
      
    • 图表查询:遍历查询数据每一天的数据(当时天数,减去某些天)

      now_date = datetime.strptime(datetime.now().strftime('%Y-%m-%d'), '%Y-%m-%d')
      active_date = []
      active_count = []
      for i in range(0, 31):
      begin_date = now_date-timedelta(days=i)
      end_date = now_date-timedelta(days=(i-1))
      active_date.append(begin_date.strftime('%Y-%m-%d'))
      count = 0
      count = User.query.filter(User.is_admin == False, User.last_login >= day_begin, User.last_login < day_end).count()
      active_count.append(count)
      active_date.reverse()
      active_count.reverse()
      

    6.3 用户列表(略)

    6.4 新闻审阅列表

    • 新闻列表的关键字查找的完成,后端承受了参数 page,keywords,增加过滤条件

      filters = [News.status != 0]
      if keywords:
      # 增加关键词的检索选项
      filters.append(News.title.contains(keywords))
      
    • 查询出新闻分页目标,回来前端即可

    6.5 新闻审阅概况

    • 依据参数action的值修正新闻目标的status值,假如status=-1,需求增加reason

      // 获取到一切的参数,尤其是reason
      $(this).serializeArray().map(function (x) {
      params[x.name] = x.value; });
      
      if (resp.errno == "0") {
              // 回来上一页,改写数据
              location.href = document.referrer; }
      

    6.6 用户新闻修改

    • 修改概况界面数据,GET恳求回来分类数据,新闻目标数据,要判别当时新闻归于哪个分类

      categories = Category.query.all()
        categories_li = []
        for category in categories:
          c_dict = category.to_dict()
          c_dict["is_selected"] = False
          if category.id == news.category_id:
            c_dict["is_selected"] = True
          categories_li.append(c_dict)
        # 移除最新分类
        categories_li.pop(0)
      
    • 前端修改提交,后端承受参数:news_id,title,digest,content,index_image,category_id,验证后,给news目标增加数据,保存,回来json数据。前端发送数据前需求的处理如下:

      beforeSubmit: function (request) {
              // 在提交之前,对参数进行处理
              for(var i=0; i<request.length; i++) {
                var item = request[i]
                if (item["name"] == "content") {
                  item["value"] = tinyMCE.activeEditor.getContent()
                } } }
      

    6.7 新闻分类办理(略)

  7. 留意点:

  • 当时端需求一次性展现页面作用,所需的数据不会动态改变运用模板烘托数据

  • 当时端需求动态展现页面数据和处理事情,所需数据 依据状况改变时,运用ajax或许其他方法向后端发送异步恳求。

  • 先行假定数据一个安全值,然后推翻,赋予数据实在值,做到安全性的套路。

    is_followed = False
      if g.user:
        if other.followers.filter(User.id == user.id).count() > 0:
          is_followed = True
    
 
 

本文地址:http://www.cvmachine.com/dnjc/99765.html
Tags: 项目 Flask 新经
修改:申博开户网
关于咱们 | 联络咱们 | 友情链接 | 网站地图 | Sitemap | App | 回来顶部