YoYo YoYo - 3 months ago 10
Python Question

Django Filter Objects and Get First Corresponding Values

I have two models.

class House(models.Model):
name= models.Charfield(max_length=100)
city= models.Charfield(max_length=100)
area= models.CharField(max_length=200)
country=models.CharField(max_length=30)

class HouseRooms(models.Model):
room_name=models.Charfield(max_length=200)
house= models.ForeignKey(House, related_name='house_hr')
room_price=models.PositiveIntegerField()


When a user run a keyword search, I want to return the name of each 'House' and the first room_price of the corresponding 'HouseRooms'. See my views below.

def my_house_search(request):
query_string= ''
rms= None
sms=None
if ('q' in request.GET) and request.GET['q'].strip():
query_string = request.GET['q']

entry_query= get_query(query_string, ['city','country',])

rms= House.objects.filter(entry_query).order_by('-pub_date')
sms= HouseRooms.objects.filter(house_id__in=rms)


return render(request, 'search/my_house_search.html',{'rms':rms, 'sms':sms, 'query_string':query_string})


Template:

{% if query_string %}
<p> Results </p>


{% if rms %}
{% for m in rms %}
<p> Name: {{ m.name }} </p>
{% empty %}
<p> No house found </p>
{% endfor %}

{% for sd in sms %}
<p> price: {{ sd.room_price }} for {{sd.room_name}}</p>
{% empty %}
<p> no price found </p>
{% endfor %}

{% endif %}

{% endif %}


With the code I wrote, it will return the name of each house and show all prices to all houses like this:

Coker House

Klopp House

$50/day for small room
$100/day for medium room
$200/day for big room

$200/day for quack room
$400/day for master room
$500/day for big room


I just want it to return the result like this.

Coker House
$50/day for small room

Klopp House
$200/day for quack room


What am I missing? How do I go about this?

Answer

You shouldn't query HouseRooms explicitly in the view. Instead, you can use the reverse relationship accessor inside your iteration in the template itself.

{% for m in rms %}
  <p> Name: {{ m.name }} </p>
  {% with m.house_hr.first as sd %}
    {% if sd %}
      <p> price: {{ sd.room_price }} for {{sd.room_name}}</p>
    {% else %}
      <p> no price found </p>
    {% endif %}
  {% endwith %}
{% empty %}
  <p> No house found </p>
{% endfor %}