【问题标题】:Django search with AND operator many to many relationshipDjango搜索与AND运算符多对多关系
【发布时间】:2022-02-01 12:46:32
【问题描述】:

这是我的模特

class MenuItem(models.Model):
    name = models.CharField(max_length=500, null=False)
    description = models.CharField(max_length=500, null=True)
    image_url = models.CharField(max_length=1000, null=True)
    menu_category = models.ForeignKey(MenuCategory, on_delete=models.CASCADE)

    def __str__(self):
        return f'{self.name}'


class Venue(models.Model):
    name = models.CharField(max_length=500, null=False)

    def __str__(self):
        return f'{self.name}'


class VenueMenu(models.Model):
    venue = models.ForeignKey(Venue, null=False, on_delete=models.CASCADE)
    menu_item = models.ManyToManyField(MenuItem, null=False)

这是我的看法

@api_view(['GET'])
def search_menu_item(request):
    if request.GET.get('venue') and request.GET.get('search_name'):
        menu_item_filter = Q(menu_item__name__icontains=request.GET.get('search_name'))
        venue_filter = Q(venue__name=request.GET.get('venue').title())
        menu_item_search = VenueMenu.objects.filter(venue_filter & menu_item_filter)
        serializer = VenueMenuSerializer(menu_item_search, many=True)
        return Response(serializer.data)

这是我的序列化器

class MenuItemSerializer(serializers.ModelSerializer):
    menu_category = MenuCategorySerializer(many=True)

    class Meta:
        model = MenuItem
        fields = '__all__'


class VenueSerializer(serializers.ModelSerializer):
    class Meta:
        model = Venue
        fields = '__all__'


class VenueMenuSerializer(serializers.ModelSerializer):
    menu_item = MenuItemSerializer(many=True)
    venue = VenueSerializer(many=False)

我想在特定场所搜索单个菜单项信息,正如您在我的查询中看到的那样正在查询对象,但此查询返回了与该场所关联的所有菜单项,包括我已经搜索但我想要一个我正在搜索的与该场所相关联的菜单项。

【问题讨论】:

  • 删除icontains

标签: python-3.x django django-rest-framework django-views django-queryset


【解决方案1】:

您会得到正确过滤的VenueMenus,但不会自动过滤相关的MenuItems,因为过滤器是针对VenueMenu 而不是MenuItem

要在序列化程序中过滤相关的MenuItems,您必须使用Prefetch 进行过滤预取,如下所示:

from django.db.models import Prefetch


menu_item_search = VenueMenu.objects.filter(
    venue_filter & menu_item_filter
).prefetch_related(
    Prefetch(
        'menu_item',
        queryset=MenuItem.objects.filter(name__icontains=request.GET.get('search_name'))
    )
)

为了进一步改进这一点,您还可以使用select_related 选择相关的Venue,以避免为了在序列化程序中获取场地详细信息而进行单独的查询。总而言之:

menu_item_search = VenueMenu.objects.filter(
    venue_filter & menu_item_filter,
).select_related(
    'venue',
).prefetch_related(
    Prefetch(
        'menu_item',
        queryset=MenuItem.objects.filter(name__icontains=request.GET.get('search_name'))
    )
)

【讨论】:

  • @Brian Destura 工作完美。谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-02
  • 2013-09-30
  • 2015-10-29
  • 2019-05-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多