Home > OS >  how do I get foreighkey of foreighkey without a loop in django?
how do I get foreighkey of foreighkey without a loop in django?

Time:04-08

It is a Django project, I am trying to create a wishlist (many-to-many will not help because I need DateTime of getting that wished item in the wishlist).

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)

What I could do is only this:

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

But I need something like this, without a loop but with a single SQL query and single line

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

When I try to run this code I get an error AttributeError: 'RelatedManager' object has no attribute 'product'

CodePudding user response:

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')

You can make it more covenient to query by spanning a ManyToManyField with your 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)

then you can query with:

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

It will also make querying for the .wishlist of the Client more covenient, of the Products where the .client_set is a manager that manages the Clients that have that Product on the wishlist.


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.

CodePudding user response:

Many to many relationship will fix the problem you can add extra fields to your WishItem class you can try this :

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)
  • Related