为了账号安全,请及时绑定邮箱和手机立即绑定

根据相关ManyToMany另一个Model id的id过滤查询模型的结果

根据相关ManyToMany另一个Model id的id过滤查询模型的结果

达令说 2022-07-12 14:45:00
我有 2 个模型class Tag(models.Model):    id = models.AutoField(primary_key=True)    name = models.CharField(max_length=255)    def __str__(self):        return self.nameclass Question(models.Model):    ques_id = models.IntegerField(default=0)    name = models.CharField(max_length=255)    Tag_name = models.ManyToManyField(Tag)    class Meta:        ordering = ['ques_id']    def __str__(self):        return self.namesearlizers.pyclass TagSerializers(serializers.ModelSerializer):    class Meta:        model = Tag        fields = '__all__'class QuestionSerializers(serializers.ModelSerializer):    class Meta:        model = Question        fields = '__all__'这是我的searilzers课。我想要这样的回应{  "id": 1,  "name": "QUES 1",  "tags": [{     "id": 1,     "name": "Abcd"   }]} 给定一些输入标签 ID,例如 Tag_id = 1 或 2 或 3,将查询什么来获取 10 个问题。
查看完整描述

3 回答

?
慕森卡

TA贡献1806条经验 获得超8个赞

你只需要tags在你的QuestionSerializers


class QuestionSerializers(serializers.ModelSerializer):

    tags = TagSerializers(source='Tag_name', many=True)


    class Meta:

        model = Question

        fields = ('id', 'name', 'tags')

它会给你这样的回应


{

  "id": 1,

  "name": "QUES 1",

  "tags": [{

     "id": 1,

     "name": "Abcd" 

  }]

您基于标签获取的查询将是这样的


Question.objects.filter(Tag_name__in=[1, 2, 4])


查看完整回答
反对 回复 2022-07-12
?
千万里不及你

TA贡献1784条经验 获得超9个赞

您需要将tags字段作为另一个序列化程序数据添加到您的QuestionSerializer.


您的QuestionSerializer代码应如下所示:


class QuestionSerializers(serializers.ModelSerializer):

    Tag_name = TagSerializer(many=True)


    class Meta:

        model = Question

        fields = '__all__'

如果您想要确切tags的名称作为响应,您可以SerializerMethodField这样指定:


class QuestionSerializer(serializers.ModelSerializer):

    tags = serializers.SerializerMethodField()


    get_tags(self, instance):

        return TagSerializer(instance.Tag_name, many=True).data


    class Meta:

        model = Question

        fields = ('ques_id', 'name', 'tags')


查看完整回答
反对 回复 2022-07-12
?
杨魅力

TA贡献1811条经验 获得超6个赞

首先:我建议你重构你的Question模型,因为它有一个ques_id,我认为它被认为是重复的(因为 Django 已经默认创建了一个 id 字段)


然后你需要把你ManyToManyField的名字改成tags, makemigrations, 然后migrate


class Question(models.Model):

    name = models.CharField(max_length=255)

    tags = models.ManyToManyField(Tag)


    class Meta:

        ordering = ['id']


    def __str__(self):

        return self.name

# run make migrations

python manage.py makemigrations <<<YOUR QUESTIONS APP NAME>>>

# It will prompt you to check if you change the many to many relationship say yes

Did you rename question.Tag_name to question.tags (a ManyToManyField)? [y/N] y

# Then Run migrate

python manage.py migrate

第二:更新您QuestionSerializers以使标签字段序列化关系


class QuestionSerializers(serializers.ModelSerializer):

    tags = TagSerializers(many=True)


    class Meta:

        model = Question

        fields = '__all__'

这样你就可以让你的代码更干净。你很高兴。


答案更新(过滤和分页)

现在,如果您想根据提供的标签 ID 过滤问题。


您需要PageNumberPagination用于您的视图,并用于过滤使用DjangoFilterBackend.


我建议您将它们设为 DRF 设置的默认值。


确保您已django-filter安装。


# In your settings.py

REST_FRAMEWORK = {

    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',

    'DEFAULT_FILTER_BACKENDS': (

        'django_filters.rest_framework.DjangoFilterBackend',

    ),

    'PAGE_SIZE': 10

}


现在创建您的自定义过滤器


# Inside filters.py

import re


import django_filters


from questions.models import Question



class QuestionsFilterSet(django_filters.FilterSet):

    tags = django_filters.CharFilter(field_name='tags__id', method='tags_ids_in')


    def tags_ids_in(self, qs, name, value):

        ids_list = list(map(lambda id: int(id), filter(lambda x: x.isdigit(), re.split(r'\s*,\s*', value))))

        return qs.filter(**{f"{name}__in": ids_list}).distinct()


    class Meta:

        model = Question

        fields = ('tags',)

现在ListAPIView用来列出你的问题


class QuestionsListAPIView(ListAPIView):

    queryset = Question.objects.all()

    serializer_class = QuestionSerializers

    filter_class = QuestionsFilterSet

现在如果你打


http://<PATH_TO_VIEW>?tags=1,2,3

您将收到标签 ID 为 1、2 或 3 的所有问题。所有这些问题将一次分页 10 个结果。


查看完整回答
反对 回复 2022-07-12
  • 3 回答
  • 0 关注
  • 129 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信