I have 3 models in this project
class products(models.Model):
product_id = models.CharField(max_length=10, blank=False, null=False, primary_key=True)
name = models.CharField(max_length=20, blank=False)
description = models.TextField(blank=True, null=True)
userslikedproduct = models.ManyToManyField(UserAccount, blank=True)
def __str__(self):
return self.product_id
class productReviews(models.Model):
review_id = models.CharField(max_length=10, blank=False, null=False, primary_key=True)
product = models.ForeignKey(products, related_name='reviews', on_delete=models.CASCADE)
user = models.ForeignKey(UserAccount, related_name='users', on_delete=models.CASCADE)
review_desc = models.TextField(blank=True, null=True)
review_rating = models.IntegerField(choices=RATING, null=True)
date_added = models.DateTimeField(verbose_name='date_added', auto_now_add=True)
class ReviewImage(models.Model):
review = models.ForeignKey(productReviews, related_name='review_images', on_delete=models.CASCADE)
image = models.ImageField(null=True, blank=True, upload_to="/images/")
I want to fetch all the reviews related to a product id along with review images.
I tried using
Query1 = productReviews.objects.all().filter(product=product).values().order_by('-date_added')
Query2 = ReviewImage.objects.filter(review__product__product_id=product).values_list('review', 'image')
Query1 results in all the objects without images Query2 reults in all the images and review ids without review objects
How can I fetch all the reviews of one particular product along with the review images?
Here's my views.py file before being able to access the foreign key objects
class productReviews(APIView):
def post(self, request, *args, **kwargs):
product = request.data.get('product', False)
result = productReviews.objects.all().filter(product=product).values().order_by('-date_added')
# Set up Pagination
p = Paginator(result), 2)
page = request.GET.get('page')
try:
page_obj = p.get_page(page)
except PageNotAnInteger:
page_obj = p.page(1)
except EmptyPage:
page_obj = p.page(p.num_pages)
context = {'page_obj': page_obj}
print(context)
samp_obj = page_obj.object_list
print(samp_obj)
a = page_obj.has_next()
print(a)
context = str(context)
return Response({
'data': samp_obj,
'has_next_page': a,
})
After using it from dict my views.py file
class productReviews(APIView):
def post(self, request, *args, **kwargs):
product = request.data.get('product', False)
reviews = productReviews.objects.all().filter(product=product).order_by('-date_added')
print(reviews)
reviews_as_dict = reviews.values()
for review, review_dict in zip(reviews, reviews_as_dict):
# Now you can get review images assigned to each review like this
review_images = review.review_images.all()
# Update the review_dict to include the review_image data
review_dict['review_images'] = review_images.values()
print(review_dict)
# Set up Pagination
p = Paginator(review_dict), 2)
page = request.GET.get('page')
try:
page_obj = p.get_page(page)
except PageNotAnInteger:
page_obj = p.page(1)
except EmptyPage:
page_obj = p.page(p.num_pages)
context = {'page_obj': page_obj}
print(context)
samp_obj = page_obj.object_list
a = page_obj.has_next()
return Response({
'data': samp_obj,
'has_next_page': a,
})
But now I am unable to use dict object in pagination
How do I apply pagination ?
CodePudding user response:
I think you don't need to use values
or values_list
. That makes your objects into Python dicts, or lists.
I think you might be looking for something like this:
# To get all reviews
reviews = product.reviews.order_by('date_added')
# To get all reviews as Python dicts
reviews_as_dict = reviews.values()
for review, review_dict in zip(reviews, reviews_as_dict):
# Now you can get review images assigned to each review like this
review_images = review.review_images.all()
# Update the review_dict to include the review_image data
review_dict['review_images'] = review_images.values()
This should give you a list of dicts which should look like:
[
{
... other review attributes,
review_images: [
{
... ReviewImage attributes
}, ...
]
}, ...
]
However, this seems kind of unnecessary. If you're passing this data to a template, you could just add the first reviews
variable to the context and use it in the template like so:
<div>
{% for review in reviews %}
<h1>Review {{ review.review_rating }}</h1>
<small>Description {{ review.review_desc }}</small>
<h3>Review images for this review</h3>
<ul>
{% for review_image in review.review_images.all %}
<li><img src="{{ review_image.image.url }}"></img></li>
{% endfor %}
</ul>
{% endfor %}
</div>
I hope that answers your question.