python 包含多个相关对象匹配的Django查询集

yqkkidmi  于 2022-10-30  发布在  Python
关注(0)|答案(1)|浏览(188)

我的模型:

class Pattern(models.Model):
    name = CICharField("Pattern Name", max_length=200, unique=True)
    symptoms = models.ManyToManyField(Symptom, through='PatternSymptom', related_name='patterns')
    tongue_colour = models.ManyToManyField(Color, verbose_name="Tongue Body Colour", blank=True, related_name='patterns')
    tongue_shape = models.ManyToManyField(Shape, verbose_name="Tongue Body Shape", blank=True, related_name='patterns')

class Shape(models.Model):
    name = CICharField(max_length=300, unique=True)

class Color(models.Model):
    name = CICharField(max_length=300, unique=True)

class Symptom(models.Model):
    name = CICharField(max_length=300, unique=True)

在前端,用户可以选择多个症状、颜色和形状来查找将传递给Pattern模型的模式。views.py

def get_queryset(self):
        params = self.request.query_params
        query_symptoms = self.request.GET.getlist('symptoms_selected')
        tongue_colour = self.request.GET.get('tongue_colour')
        tongue_shape = self.request.GET.get('tongue_shape')

        if query_symptoms:
            queryset = Pattern.objects.filter(
                symptoms__id__in=query_symptoms
            ).annotate(
                symptom_matched=Count('symptoms')
            )
        else:
            queryset = Pattern.objects.all().filter(is_searchable=True)

        if tongue_colour is not None and tongue_colour.isnumeric():
            queryset = queryset.filter(tongue_colour__id__in=tongue_colour).annotate(tongue_color_matches=Count('tongue_colour'));

        if tongue_shape is not None and tongue_shape.isnumeric():
            queryset = queryset.filter(tongue_shape__id__exact=tongue_shape).annotate(tongue_shape_matches=Count('tongue_shape'));

        return queryset

用这段代码我可以得到,queryset与匹配症状AND tongue_colour AND tongue_shape.但是,我想显示queryset与OR/所有组合与什么匹配.
我使用Django REST API来传递结果数据。

class PatternSerializer(serializers.ModelSerializer):

    symptoms_matched = serializers.SerializerMethodField()

    class Meta:
        model = Pattern
        fields = ('id', 'name', 'symptoms_matched')

    def get_symptoms_matched(self, obj):
        return getattr(obj, 'symptoms_matched', None)

例如:模式数据:
模式A:出现症状:A、B、C、D鞋舌颜色:TC 1、TC 2、TC 5鞋舌形状:TS1、TS3、TS5
模式B:出现症状:A、D、P、Q鞋舌颜色:TC 2、TC 3、TC 6鞋舌形状:TS 1、TS 2和TS 6
模式C:出现症状:A、Q、X、Y鞋舌颜色:TC 1、TC 4、TC 7鞋舌形状:TS 1、TS 4和TS 7

**例如,如果用户选择:**2个症状:A、Y。鞋舌颜色:TC 1鞋舌形状:TS 7标准

它返回Null。因为没有完全匹配。我不想使用Null,而是想通过显示匹配的症状、颜色、形状等来显示用户与任何组合的匹配。我希望queryset将返回所有组合:

以上示例的所需结果如下所示:

3个模式匹配。

[
    {
        "name": "Pattern A",
        "symptoms_matched": 1,
        "tongue_color_matched": 1,
        "tongue_shape_matched": 0,
    },
    {
        "name": "Pattern B",
        "symptoms_matched": 1,
        "tongue_color_matched": 0,
        "tongue_shape_matched": 0,
    },
    {
        "name": "Pattern C",
        "symptoms_matched": 1,
        "tongue_color_matched": 0,
        "tongue_shape_matched": 1,
    },
]

就像症状匹配一样,我也想通过舌色匹配和舌形匹配的考试。谁能告诉我如何才能做到这一点?

dhxwm5r4

dhxwm5r41#

您可以使用Q对象来执行带有OR的查询。

from django.db.models import Q 

queryset = Pattern.objects.filter(
    Q(symptoms__id__in=symptom) |
    Q(tongue_shape__id__exact=tongue_shape) |
    Q(tongue_colour__id__in=tongue_colour))

相关问题