Home > Software engineering >  How to query all the fields in parent as well as child model related with a foreign key in DRF ? and
How to query all the fields in parent as well as child model related with a foreign key in DRF ? and

Time:03-18

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.

  • Related