Ali
Ali

Reputation: 339

Get data from a model based on a list from another model object

I have two models as follow :

class Books(models.Model):
    poster = models.CharField(max_length=2000)
    bookid = models.CharField(max_length=10)
    title = models.CharField(max_length=150)
    year = models.IntegerField()

    def __str__(self):
        return self.title



class UserRating(models.Model):
    userid = models.CharField(max_length=20)
    rating = models.CharField(max_length=5)
    bookid = models.CharField(max_length=10)

In the views.py I get all the current logged in user rates and put it in bookid list :

def rated(request):

    rate = UserRating.objects.filter(userid=request.user.id)[:5]
    bookid =  []

    for i in rates:
        bookid.append(i.bookid)

What I want to do is getting every book poster by its bookid.diplaying all books that the user rated with its poster and the rate.

How can I do that?

Upvotes: 1

Views: 693

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476594

The modeling is rather strange: you ue CharFields as a way to link objects together. But that is not a good practice. Django has a tool to link model objects together: ForeignKeys:

class Book(models.Model):
    poster = models.CharField(max_length=2000)
    title = models.CharField(max_length=150)
    year = models.IntegerField()

    def __str__(self):
        return self.title

class UserRating(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    rating = models.IntegerField()
    book = models.ForeignKey(Books, on_delete=models.CASCADE)

Furthermore a rating is probably more numerical, so an IntegerField, or a DecimalField. A model name is typically singular (so Book instead of Books). Finally usually one does not assign an id to a model instance: Django does this automatically. If the bookid is more something like an ISBN, then you can create a field isbn = ... in a Book.

With these changes, one can exploit the ForeignKey relations, and thus use the ORM to make JOINs. For example we can obtain all the Books a user has rated (together with the rating) with:

from django.db.models import F

Book.objects.filter(
    userrating__user=request.user
).annotate(
    rating=F('userrating__rating')
)

Here the queryset will contain all the books the request.user has rated. Furtermore every Book of this querset will have an attribute .rating that contains the rating of the user for that book.

I would also advice to define a ManyToManyField for the Book model to User (the raters), and let it thus pass through UserRating.

Upvotes: 1

Related Questions