Django 模型视图集过滤

Django Modelviewset Filtering

我有两个模型类别 & Post。在 Post 模型中有类别的外键。基于类别,我想过滤数据以明智地显示 post 类别。这是我的代码。

models.py

class Category(models.Model):
    name = models.CharField(max_length=200)
    slug = models.SlugField()
    parent = models.ForeignKey('self',blank=True, null=True ,related_name='news', on_delete=models.CASCADE)

    class Meta:
        unique_together = ('slug', 'parent',)    
        verbose_name_plural = "Category"     

    def __str__(self):                           
        full_path = [self.name]                  
        k = self.parent
        while k is not None:
            full_path.append(k.name)
            k = k.parent
        return ' -> '.join(full_path[::-1])

class Post(models.Model):
    NEWS_TYPE = (('Images','Images'),('Multi-Images','Multi-Images'),('Image-Text','Image-Text'),
                 ('Audio-Video','Audio-Video'),('Audio-Video-Text','Audio-Video-Text'),('Audio','Audio'),
                 ('Audio-Text','Audio-Text'))
    POST_STATUS = (('Pending','Pending'),('Verified','Verified'),('Un-Verified','Un-Verified'),
              ('Published','Published'),('Mint','Mint'))
    category = models.ForeignKey(Category, related_name='posts', on_delete=models.CASCADE)
    post_type = models.CharField(max_length=100, verbose_name='Post Type', choices=NEWS_TYPE)
    title = models.TextField(verbose_name='News Title')
    content = models.TextField(verbose_name='News Content')
    hash_tags = models.CharField(max_length=255, verbose_name='Hash Tags')
    source = models.CharField(max_length=255, verbose_name='News Source')
    author = models.ForeignKey(User, related_name='Post', on_delete=models.CASCADE)
    views = models.ManyToManyField(User,related_name='Views', blank=True)
    likes = models.ManyToManyField(User, related_name='Likes', blank=True)
    dislikes = models.ManyToManyField(User, related_name='Dislikes', blank=True)
    status = models.CharField(max_length=20, verbose_name='Status', choices=POST_STATUS, default='Pending')
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return (self.post_type)+ '-' +self.title

serializers.py

class CategorySerializer(serializers.ModelSerializer):
    class Meta:
        model = Category
        fields = '__all__'

class PostSerializer(serializers.ModelSerializer):
    category = CategorySerializer(many=True, read_only=True)
    class Meta:
        model = Post
        fields = ('category','post_type','title','content','hash_tags','source','author','views',
                  'likes','dislikes','status')

views.py

class CategoryAPI(viewsets.ModelViewSet):
    queryset = Category.objects.all()
    serializer_class = CategorySerializer

class PostAPI(viewsets.ModelViewSet):
    serializer_class = PostSerializer

    def get_queryset(self):
        news_post = Post.objects.all()
        return news_post

    def retrieve(self, request, *args, **kwargs):
        params = kwargs
        print(params['pk'])
        category = Category.objects.filter(name=params['pk'])
        serializer = CategorySerializer(category, many=True)
        return Response(serializer.data)

urls.py

from django.urls import path, include
from rest_framework import routers
from rest_framework.routers import DefaultRouter
from news.views import PostAPI, CategoryAPI
from . import views

router = DefaultRouter()
router.register('posts', views.PostAPI, basename='posts'),
router.register('category', views.CategoryAPI, basename='category'),


urlpatterns = router.urls

我尝试用这些方法解决,但它告诉 'PostSerializer' object has no attribute 'get_category'。有什么我做错了吗?请您的支持会有所帮助。谢谢

我认为你的方法应该反过来,这意味着你应该将 Posts 的列表添加到你的 Category:

serializers.py

class PostSerializer(serializers.ModelSerializer):
    class Meta:
        model = Post
        fields = ('category','post_type','title','content','hash_tags','source','author','views',
                  'likes','dislikes','status')

class CategorySerializer(serializers.ModelSerializer):
    posts = PostSerializer(many=True, read_only=True)

    class Meta:
        model = Category
        fields = ['name', 'slug', 'parent', 'posts']

注意:我将Post模型中你的类别字段的相关名称更改为'posts'

这应该会在检索类别时向您显示所有 Posts。无需覆盖您视图中的任何方法:

class CategoryAPI(viewsets.ModelViewSet):
    queryset = Category.objects.all()
    serializer_class = CategorySerializer

class PostAPI(viewsets.ModelViewSet):
    queryset = Post.obejcts.all()
    serializer_class = PostSerializer

如果不想通过id而是通过类别名称来识别类别,例如:

http://127.0.0.1:8000/news/category/sports/

向您的类别视图添加自定义查找字段,例如

class CategoryAPI(viewsets.ModelViewSet):
    queryset = Category.objects.all()
    serializer_class = CategorySerializer
    lookup_field = 'name'

但要确保 lookup_field 是唯一的