Desert Camel
Desert Camel

Reputation: 137

I got the first result only of the for loop in Django views

i have a PositiveIntegerField in a model, in which i need to loop through that model to check all the values of this field and get its results to use it in my views..

The Problem is when i did that i just get the value of the first row in the database only!

models.py

class RoomType(models.Model):
    hotel = models.ForeignKey(Hotel, on_delete=models.CASCADE)
    room_type = models.ForeignKey(RoomTypesNames, on_delete=models.CASCADE)
    room_capacity = models.PositiveIntegerField() ## Thats the field i wanna check its value

views.py

def SearchHotels(request):
    x = None
    z = None
    t = None

    if request.method == 'GET':
        destination = request.GET.get('cityHotels')
        numAdultStr = request.GET.get('numAdult')
        numChild = request.GET.get('numChild')
        numAdult = int(numAdultStr)

        if destination:
            q_city2 = Q(hotel__city__name__icontains = destination)
            rooms2  = RoomType.objects.filter(q_city2)
      ################################
      ### next is my question:
            if rooms2:
                for r in rooms2:
                    if r.room_capacity < numAdult and numAdult % r.room_capacity == 0:
                        x = numAdult / r.room_capacity

### i want to loop through this query and check the values of 'room_capacity' in all models, but i only get the result of only the first row in my database

Upvotes: 1

Views: 159

Answers (1)

ruddra
ruddra

Reputation: 51988

Probably you should get the last entry of your table unless your order_by is reversed. As @furas mentioned in comments, when you are dealing with multiple entry in a loop, its better to add the calculated values in a list.

But an alternative solution is to use annotate with conditional expression to use the DB to calculate the values for you:

from django.db.models import FloatField, IntegerField, ExpressionWrapper, F, Case, When, Value

room2 = RoomType.objects.filter(q_city2).annotate(
    x_modulo=ExpressionWrapper(
            numAdult % F('room_capacity'),
            output_field=IntegerField()
         )
    ).annotate(
        x=Case(
            When(
                room_capacity__lt=numAdult,
                x_modulo=0,
                then=numAdult/F('room_capacity')
            ),
            default_value=Value('0'),
            output_field=FloatField()
        )
    )
all_x = []
for r in room2:
    all_x.append(r.x)
print(all_x)
# or
print(room2.values('x'))

# filter usage
room2.filter(x__gt=0)

Explanation: In here, I am annotating of x_modulo which is modular value of numAdult and room_capacity. Then I am annotating the value of x which checks if room capacity is less than number of adults and value of x_modulo is 0. Then I am just annotating the fraction of numAdults and room_capacity.

Upvotes: 1

Related Questions