Отфильтруйте объект с отношением «многие ко многим», проверив, содержит ли он хотя бы один из элементов в списке - PullRequest
0 голосов
/ 08 апреля 2019

Мы создаем приложение, которое будет использоваться для продажи подержанных товаров.Внутри этого приложения у нас будет возможность фильтровать товары по ряду критериев: географическое положение пользователя и максимальное расстояние, минимальная цена, максимальная цена, минимальная оценка и список тегов.

Моя главная проблема - отфильтровать отношения «многие ко многим», которые имеет продукт с тегом.Мы хотим получить все продукты, которые содержат хотя бы один из выбранных пользователем тегов.

Вот код функции фильтра:

def FilterProduct(request, format=None):
    if request.method != 'POST':
        return Response(status=status.HTTP_400_BAD_REQUEST)
    token = request.POST.get('token', 'nothing')
    if token == 'nothing':
        return Response(status=status.HTTP_400_BAD_REQUEST)
    else:
        try:
            tags = request.POST.get('tags', '')
            tags_pk = []
            for tag_search in tags:
                tag = Tag.objects.filter(nombre=tag_search)
                if tag != None:
                    tags_pk.append(tag.pk)

            user_latitude = request.POST.get('latitud', '')
            user_longitude = request.POST.get('longitud', '')
            max_distance = request.POST.get('distancia_maxima', '')
            min_price = request.POST.get('precio_minimo', '')
            max_price = request.POST.get('precio_maximo', '')
            min_score = request.POST.get('calificacion_minima', '')
            if tags == '' or user_latitude == '' or user_longitude == '' or max_distance == '' or min_price == '' or max_price == '' or min_score == '':
                return Response(status=status.HTTP_400_BAD_REQUEST)
            products = Productos.objects.filter(precio__lte=max_price, precio__gte=min_price, vendido_por__media_valoraciones__gte=min_score, tiene_tags__in=tags_pk)

Почему-тоэто не возвращает все продукты, которые хотя бы содержат один элемент из списка первичных ключей.

Вот модели.py:

class Producto(models.Model):
    vendido_por = models.ForeignKey(
        to=Usuario,
        null=False,
        on_delete=models.CASCADE,
        verbose_name='Usuario que ha puesto a la venta el producto',
        related_name='producto_del_usuario')
    latitud = models.DecimalField(
        verbose_name='Latitud del producto',
        max_digits=9,
        decimal_places=6)
    longitud = models.DecimalField(
        verbose_name='Longitud del producto',
        max_digits=9,
        decimal_places=6)
    nombre = models.CharField(
        max_length=50,
        verbose_name='Nombre del producto')
    precio = models.CharField(
        max_length=10,
        verbose_name='Precio del producto')
    estado_producto = models.CharField(
        max_length=50,
        choices=[(tag.name, tag.value) for tag in EleccionEstadoProducto],
        verbose_name='Estado en el que se encuentra el producto: Nuevo, Semi-nuevo, etc')
    estado_venta = models.CharField(
        max_length=50,
        choices=[(tag.name, tag.value) for tag in EleccionEstadoVenta],
        verbose_name='Estado en el que se encuentra la venta')
    num_acciones = models.IntegerField(
        default=0,
        verbose_name='Marca si uno o los dos usuarios han confirmado el estado de venta')
    tipo_envio = models.CharField(
        max_length=50,
        verbose_name='Si el usuario que ha colgado el producto esta dispuestos a enviar a domicilio o no')
    descripcion = models.CharField(
        max_length=1000,
        verbose_name='Descripcion asociada al producto')
    tiene_tags = models.ManyToManyField(
        Tag,
        blank=True,
        editable=True,
        related_name='tiene_tags')
    le_gusta_a = models.ManyToManyField(
        Usuario,
        blank=True,
        editable=True,
        related_name='le_gusta_a')
    num_likes = models.IntegerField(
        default=0,
        verbose_name='Likes acumulados por el producto')

class Tag(models.Model):
    nombre = models.CharField(
        max_length=50,
        verbose_name='Nombre del tag')
    es_predeterminado = models.BooleanField(
        default=False,
        verbose_name='Marca si un tag ha sido creado por los administradores de la aplicacion')

Существует ли реальный способ отфильтровать всепродукты, которые содержат хотя бы один из тегов в списке, отправленных в запросе?

Заранее спасибо!

1 Ответ

2 голосов
/ 08 апреля 2019

Я думаю, что вы можете упростить работу фильтра тегов, например,

tags = request.POST.get('tags', '')
tag_queryset = Tag.objects.filter(nombre__in=tags)

. Затем вы можете добавить набор запросов непосредственно в фильтр товаров, например,

products = Productos.objects.filter(precio__lte=max_price, precio__gte=min_price, vendido_por__media_valoraciones__gte=min_score, tiene_tags__in=tag_queryset)

Надеюсь, что это поможет.

...