renran-专题模块

专题部分

在models.py中,创建文章投稿记录的模型,代码:

class ArticlePostLog(BaseModel):
    """文章的投稿记录"""
    POST_STATUS = (
        (0,"未审核"),
        (1,"审核通过"),
        (2,"审核未通过"),
    )
    user = models.ForeignKey(User, on_delete=models.DO_NOTHING, verbose_name="投稿人")
    special = models.ForeignKey(Special, on_delete=models.CASCADE, verbose_name="专题")
    article = models.ForeignKey(Article, on_delete=models.CASCADE, verbose_name="文章")
    status = models.IntegerField(choices=POST_STATUS, default=0, verbose_name="审核状态")
    manager = models.IntegerField(default=None, null=True,blank=True, verbose_name="审核人")
    post_time = models.DateTimeField(default=None, null=True,blank=True, verbose_name="审核时间")

    class Meta:
        db_table = "rr_article_post"
        verbose_name = "文章的投稿记录"
        verbose_name_plural = verbose_name

数据迁移

python manage.py makemigrations
python manage.py migrate

创建专题的测试数据, 把专题相关模型注册到adminx.py文件, 添加测试数据

# 专题测试数据
INSERT INTO renran.rr_special (id, orders, is_show, is_deleted, created_time, updated_time, name, image, notice, article_count, follow_count, collect_count, user_id) VALUES (1, 0, 1, 0, '2020-01-15 08:27:39.044094', '2020-01-15 08:27:39.044126', '相亲', 'group1/M00/00/00/wKjDgF4ezPuAO9nlAAB7habsNjs0280196', '相亲相爱', 0, 0, 0, 1);
INSERT INTO renran.rr_special (id, orders, is_show, is_deleted, created_time, updated_time, name, image, notice, article_count, follow_count, collect_count, user_id) VALUES (2, 1, 1, 0, '2020-01-15 08:29:15.513292', '2020-01-15 08:29:15.513346', '相爱', 'group1/M00/00/00/wKjDgF4ezVuADywFAAB7habsNjs8789529', '相亲相爱', 0, 0, 0, 1);
INSERT INTO renran.rr_special (id, orders, is_show, is_deleted, created_time, updated_time, name, image, notice, article_count, follow_count, collect_count, user_id) VALUES (3, 2, 1, 0, '2020-01-15 08:29:15.513292', '2020-01-15 08:29:15.513346', '篮球', 'group1/M00/00/00/wKjDgF4ezVuADywFAAB7habsNjs8789529', '篮球', null, null, null, 1);


# 专题管理员
INSERT INTO renran.rr_special_manager (id, orders, is_show, is_deleted, created_time, updated_time, special_id, user_id) VALUES (1, 0, 1, 0, '2020-01-15 08:35:28.645931', '2020-01-15 08:35:28.645962', 1, 1);
INSERT INTO renran.rr_special_manager (id, orders, is_show, is_deleted, created_time, updated_time, special_id, user_id) VALUES (2, 0, 1, 0, '2020-01-15 08:35:33.216625', '2020-01-15 08:35:33.216656', 2, 1);
INSERT INTO renran.rr_special_manager (id, orders, is_show, is_deleted, created_time, updated_time, special_id, user_id) VALUES (3, 0, 1, 0, '2020-01-15 08:35:37.345065', '2020-01-15 08:35:37.345094', 3, 1);

# 专题投稿记录

服务端提供我管理的专题列表,视图接口代码:

from .models import Special
from .serializers import SpecialModelSerializer
class SpecialListAPIView(ListAPIView):
    queryset = Special.objects.all()
    serializer_class = SpecialModelSerializer
    permission_classes = [IsAuthenticated]

    def list(self, request, *args, **kwargs):
        user = request.user
        ret = self.get_queryset().filter(mymanager__user=user)
        queryset = self.filter_queryset(ret)

        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

客户顿实现发布文章以后的投稿页面








前端指定路由,代码:

import Vue from 'vue'

import PostArticle from "@/components/PostArticle";
Vue.use(Router);

export default new Router({
  mode: "history",
  routes: [
    ,{
      path: "/post",
      name: 'PostArticle',
      component: PostArticle,
    },
  ]
})

序列化器,代码:

from .models import Special
class SpecialModelSerializer(serializers.ModelSerializer):

    class Meta:
        model = Special
        fields = ["id","name","image","article_count","follow_count","collect_count"]

路由,代码:

from django.urls import path,re_path
from . import views
urlpatterns = [
    path("image/", views.ImageAPIView.as_view()),
    path("collection/", views.CollecionAPIView.as_view()),
    re_path("collection/(?P\d+)/", views.CollecionDetailAPIView.as_view()),
    re_path("special/list/", views.SpecialListAPIView.as_view()),
]

from rest_framework.routers import SimpleRouter
router = SimpleRouter()
router.register("", views.ArticleAPIView)
urlpatterns += router.urls

实现专题收录文章的功能

修改发布文章以后的跳转页面代码,并修改路由中原来的Writed的路由地址

Write.vue组件中发布文章以后跳转到投稿页面,代码:

public_article(is_public){
              // 文章发布状态的切换
              let article_id = this.article_list[this.current_article].id;
              this.$axios.put(`${this.$settings.Host}/article/public/${article_id}/`,{
                  is_public: is_public,
              },{
                  headers:{
                      Authorization: "jwt " + this.token,
                  }
              }).then(response=>{
                  this.article_list[this.current_article].is_public=is_public;
                  this.is_show_article_menu = false;
                  if(is_public){
                      // 对页面进行跳转到文章发布投稿页面
                      sessionStorage.current_article_id = this.article_list[this.current_article].id;
                      sessionStorage.current_article_name=this.article_list[this.current_article].name;
                      this.$router.push("/post");
                  }else{
                      this.$message.success("文章设置成功!");
                  }

              }).catch(error=>{
                  this.$message.error("操作失败!请联系客服工作人员!");
              })
          },

router/index.js,代码:

import Vue from 'vue'
import Router from 'vue-router'

import PostArticle from "@/components/PostArticle";
Vue.use(Router);

export default new Router({
  mode: "history",
  routes: [
    /// 。。、、
    ,{
      path: "/post",
      name: 'PostArticle',
      component: PostArticle,
    },
  ]
})

服务端提供收录文章到我管理的专题中的接口

from .models import Special,ArticlePostLog,SpecialArticle
from datetime import datetime
class ArticlePostAPIView(APIView):
    permission_classes = [IsAuthenticated]
    def post(self,request):
        """文章投稿"""
        user = request.user
        article_id = request.data.get("article_id")
        special_id = request.data.get("special_id")

        try:
            article = Article.objects.get(user=user, pk=article_id)
        except Article.DoesNotExist:
            return Response("对不起, 当前文章不存在!", status=status.HTTP_400_BAD_REQUEST)

        # 验证专题是否存在
        try:
            special = Special.objects.get(pk=special_id)
        except Special.DoesNotExist:
            return Response("对不起, 当前专题不存在!", status=status.HTTP_400_BAD_REQUEST)

        # 判断当前文章是否向专题投稿
        article_post_log_list = ArticlePostLog.objects.filter(special=special, article=article).order_by("-id")
        # 判断是否有投稿历史
        if len(article_post_log_list) > 0:
            # 查看最后一次投稿记录的审核状态
            if article_post_log_list[0].status != 2:
                return Response("对不起, 文章已经向当前专题投稿了!", status=status.HTTP_400_BAD_REQUEST)

        # 判断当前投稿人是否属于专题的管理员
        try:
            """专题管理员"""
            special_manage = SpecialManager.objects.get(user=user, special=special)
            ArticlePostLog.objects.create(
                user=user,
                special=special,
                article=article,
                status=1,
                manager=user.id,
                post_time=datetime.now(),
                orders=0,
            )

            SpecialArticle.objects.create(
                special=special,
                article=article,
                orders=0,
            )

        except SpecialManager.DoesNotExist:
            """并非管理员"""
            ArticlePostLog.objects.create(
                user=user,
                special=special,
                article=article,
                status=0,
                manager=user.id,
                post_time="",
                orders=0,
            )

        except:
            return Response("投稿失败!")

        return Response("投稿成功!")

urls.py路由:

    path("post/", views.ArticlePostAPIView.as_view()),

前端发送ajax,请求投稿,代码:





在专题列表中展示当前文章的收录状态

视图代码:

from .models import SpecialManager
class SpecialListAPIView(APIView):
    """我管理的专题列表"""
    permission_classes = [IsAuthenticated]
    def get(self,request):
        user = request.user
        article_id = request.query_params.get("article_id")
        manage_list = SpecialManager.objects.filter(user=user)
        data = []
        for item in manage_list:
            try:
                # 查询当前专题下所有的文章列表是否存在当前文章
                item.special.post_article_list.get(article_id=article_id)
                status = True
            except SpecialArticle.DoesNotExist:
                status = False
            data.append({
                "id": item.special.id,
                "name": item.special.name,
                "image": item.special.image.url if item.special.image else "",
                "is_post": status, # 专题对于当前文章的收录状态
            })
        return Response(data)

前端组件中在原有代码中增加is_post的判断显示





创建专题的测试数据, 把专题相关模型注册到adminx.py文件, 添加测试数据

# 专题测试数据
INSERT INTO renran.rr_special (id, orders, is_show, is_delete, created_time, updated_time, name, image, notice, article_count, follow_count, user_id) VALUES 
(1, 0, 1, 0, '2020-01-15 08:27:39.044094', '2020-01-15 08:27:39.044126', '相亲', 'group1/M00/00/00/wKj8k16Xsx2ASsq_AAAhSb9-85M7053496', '相亲相爱', 0, 0, 1),
(2, 1, 1, 0, '2020-01-15 08:29:15.513292', '2020-01-15 08:29:15.513346', '相爱', 'group1/M00/00/00/wKj8k16Xsx2ASsq_AAAhSb9-85M7053496', '相亲相爱', 0, 0, 1),
(3, 2, 1, 0, '2020-01-15 08:29:15.513292', '2020-01-15 08:29:15.513346', '篮球', 'group1/M00/00/00/wKj8k16Xsx2ASsq_AAAhSb9-85M7053496', '篮球', 0, 0, 1);


# 专题管理员
INSERT INTO renran.rr_special_manager (id, orders, is_show, is_delete, created_time, updated_time, special_id, user_id) VALUES 
(1, 0, 1, 0, '2020-01-15 08:35:28.645931', '2020-01-15 08:35:28.645962', 1, 1),
(2, 0, 1, 0, '2020-01-15 08:35:33.216625', '2020-01-15 08:35:33.216656', 2, 1),
(3, 0, 1, 0, '2020-01-15 08:35:37.345065', '2020-01-15 08:35:37.345094', 3, 1);

因为需要查找到当前登录所管理的专题列表,所以调整模型,增加关联字段:

class SpecialManager(BaseModel):
    """专题管理员"""
    user = models.ForeignKey(User,related_name="special_list", on_delete=models.DO_NOTHING, verbose_name="管理员")
    special = models.ForeignKey(Special,related_name="manager_list", on_delete=models.CASCADE, verbose_name="专题")

    class Meta:
        db_table = "rr_special_manager"
        verbose_name = "专题的管理员"
        verbose_name_plural = verbose_name

视图接口代码:

from .models import Special,SpecialArticle
from .serializers import SpecialModelSerializer
class SpecialListAPIView(ListAPIView):
    serializer_class = SpecialModelSerializer
    permission_classes = [IsAuthenticated]

    def list(self, request, *args, **kwargs):
        user = request.user
        queryset= Special.objects.filter(manager_list__user=user,manager_list__is_delete=False, manager_list__is_show=True).order_by("orders","-id")
        # 接受当前发布的文章ID,和每一个专题进行关系的判断,是否收录了当前文章
        article_id = request.query_params.get("article_id")
        for special in queryset:
            try:
                ret = SpecialArticle.objects.get(article_id=article_id,special=special)
                special.status = ret.status
            except SpecialArticle.DoesNotExist:
                special.status=-1 # 没有投稿/收录记录

        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

序列化器,代码:

from .models import Special
class SpecialModelSerializer(serializers.ModelSerializer):
    """专题的序列化器"""
    status = serializers.IntegerField(label="收录状态")
    class Meta:
        model = Special
        fields = ["id","name","image","article_count","follow_count","status"]

路由,代码:

path("special/", views.SpecialListAPIView.as_view()),

客户在点击发布文章以后的投稿页面,需要显示发布界面。创建组件PostArticle.vue,页面代码如下:







前端指定路由,代码:

import Vue from 'vue'

import PostArticle from "@/components/PostArticle";
Vue.use(Router);

export default new Router({
  mode: "history",
  routes: [
    ,{
      path: "/post",
      name: 'PostArticle',
      component: PostArticle,
    },
  ]
})

在写文章页面组件中在用户发布文章以后,进行页面跳转。


客户端在页面加载成功以后,像服务端请求获取当前用户管理的专题列表。

实现文章向专题进行投稿的功能

服务端提供收录文章到我管理的专题中的接口

from .models import Special,SpecialArticle
class PostArticleAPIView(APIView):
    """文章投稿的api接口"""
    permission_classes = [IsAuthenticated]

    def post(self, request):
        """文章投稿"""
        user = request.user
        article_id = request.data.get("article_id")
        special_id = request.data.get("special_id")

        # 验证文章是否存在
        try:
            article = Article.objects.get(user=user, pk=article_id)
        except Article.DoesNotExist:
            return Response({"message":"对不起, 当前文章不存在!"}, status=status.HTTP_400_BAD_REQUEST)

        # 验证专题是否存在
        try:
            special = Special.objects.get(pk=special_id)
        except Special.DoesNotExist:
            return Response({"message":"对不起, 当前专题不存在!"}, status=status.HTTP_400_BAD_REQUEST)

        # 判断当前文章是否向专题投稿
        try:
            special_article = SpecialArticle.objects.get(special=special, article=article)
            if special_article.status == 0 or special_article.status == 1:
                return Response({"message":"对不起, 当前文章已经投稿了,或在审核中!"}, status=status.HTTP_400_BAD_REQUEST)
            elif special_article.status == 2:
                return Response({"message":"对不起, 当前文章已经被收录,不能重复投稿!"}, status=status.HTTP_400_BAD_REQUEST)
            elif special_article.status == 3:
                """之前审核没通过,继续投稿"""
                special_article.status=1
                special_article.save()
                return Response({"message":"文章重新投稿成功!","status":1}, status=status.HTTP_200_OK)

        except SpecialArticle.DoesNotExist:
            special_article = SpecialArticle.objects.create(
                special=special,
                article=article,
                status=1,
            )

            if special.user == user:
                """如果当前投稿用户是当前专题的管理员,则默认跳过审核阶段"""
                special_article.status = 2
                special_article.user = user
                return Response({"message": "投稿成功!","status":2}, status=status.HTTP_200_OK)

            return Response({"message":"投稿成功!","status":1}, status=status.HTTP_200_OK)

urls.py路由:

    path("post/", views.PostArticleAPIView.as_view()),

前端发送ajax,请求投稿,代码:



文章详情页

在PostArticle.vue中打通跳转到文章详情页的链接:

{{article_name}}
发布成功,点击查看文章

在router/index.js中创建路由,代码:

import Vue from 'vue'
import Router from 'vue-router'
import Article from "@/components/Article";
Vue.use(Router);

export default new Router({
  mode: "history",
  routes: [
    ,{
       name:"Article",
       path:"/article/:id",
       component: Article,
     },
  ]
})

创建Article.vue组件:







在当前页面中查询当前文章的基本内容

服务端视图中提供API接口

from rest_framework.generics import RetrieveAPIView
from .serializers import ArticleInfoModelSerializer
class ArticleInfoAPIView(RetrieveAPIView):
    """文章详情信息"""
    serializer_class = ArticleInfoModelSerializer
    queryset = Article.objects.filter(is_public=True)

序列化器代码:

from users.models import User
class AuthorModelSerializer(serializers.ModelSerializer):
    """文章作者"""
    class Meta:
        model = User
        fields = ["id","nickname","avatar"] # 自己编写需要显示的字段即可

from .models import ArticleCollection
class CollectionInfoModelSerializer(serializers.ModelSerializer):
    """文集信息"""
    class Meta:
        model = ArticleCollection
        fields = ["id","name"] # 自己编写需要显示的字段即可

class ArticleInfoModelSerializer(serializers.ModelSerializer):
    user = AuthorModelSerializer()
    collection = CollectionInfoModelSerializer()
    class Meta:
        model = Article
        fields = [
            "name", "render","content", "user",
            "collection", "updated_time",
            "read_count", "like_count",
            "collect_count", "comment_count",
            "reward_count",
        ]

路由代码:

    re_path("^(?P\d+)/$", views.ArticleInfoAPIView.as_view()),

客户端代码:




你可能感兴趣的:(web)