Как получить foreighkey из foreighkey без цикла в django?

Это проект Django, я пытаюсь создать список желаний (many-to-many не поможет, потому что мне нужно DateTime получения желаемого элемента в списке желаний).

class Client(models.Model):
    name = models.CharField(max_length=100)
    user = models.ForeignKey(User, on_delete=models.CASCADE)


class Product(models.Model):
    name = models.CharField(max_length=100)
    price = models.DecimalField()

class WishItem(models.Model):
    product = models.ForeignKey(Product, on_delete=models.CASCADE)
    client = models.ForeignKey(Client, related_name="wishlist", on_delete=models.CASCADE)
    added_at = models.DateTimeField(auto_now_add=True)

Что я могу сделать, так это только следующее:

wishlist = Client.objects.wishlist.select_related('product').all()
wish_products = [item.product for item in wishlist]

Но мне нужно что-то вроде этого, без цикла, но с одним SQL запросом и одной строкой

wishlist = Client.objects.wishlist.product.all()

Когда я пытаюсь запустить этот код, я получаю ошибку AttributeError: 'RelatedManager' object has no attribute 'product'

Отношения "многие ко многим" решат проблему, вы можете добавить дополнительные поля в класс WishItem, попробуйте сделать это :

class Product(models.Model):
    name = models.CharField(max_length=100)
    price = models.DecimalField()

 class Client(models.Model):
    name = models.CharField(max_length=100)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    WishProducts = models.ManyToManyField(Product,through='WishItem')


class WishItem(models.Model):
    product = models.ForeignKey(Product, on_delete=models.CASCADE)
    client = models.ForeignKey(Client, on_delete=models.CASCADE)
    added_at = models.DateTimeField(auto_now_add=True)

You can .filter(…) [Django-doc] and then .order_by(…) [Django-doc] with:

Product.objects.filter(wishitem__client__user=my_user).order_by('wishitem__added_at')

Вы можете сделать его более удобным для запроса, соединив ManyToManyField с вашим WishItem:

class Client(models.Model):
    # …
    wishlist = models.ManyToManyField(
        'Product',
        through='WishItem'
    )


class Product(models.Model):
    # …
    pass

class WishItem(models.Model):
    product = models.ForeignKey(Product, on_delete=models.CASCADE)
    client = models.ForeignKey(Client, related_name='wishitems', on_delete=models.CASCADE)
    added_at = models.DateTimeField(auto_now_add=True)

тогда вы можете запросить:

Product.objects.filter(client__user=my_user).order_by('wishitem__added_at')

Это также сделает запрос на .wishlist из Client более ковенантным, из Product, где .client_set является менеджером, который управляет Client, у которых есть этот Product в списке желаний.


Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.

Вернуться на верх