Search code examples
djangodjango-templatesdjango-template-filters

Django templates - how to run a method on a variable?


I'm new to Django, so maybe my attempts are pure heresy ;)

I'm trying to make a view which lists disponible conference rooms with its attributs, availability included. I have 2 models: Room and Reservation. I'd like in the view to have a column saying if the room is available the day the page is displayed.

My models.py:

from django.utils import timezone
from django.db import models


class Room(models.Model):
    name = models.CharField(max_length=255, unique=True)
    capacity = models.IntegerField()
    projector = models.BooleanField()


class Reservation(models.Model):
    room = models.ForeignKey(Room, on_delete=models.CASCADE)
    date = models.DateField()
    comment = models.CharField(max_length=255)

    class Meta:
        unique_together = ('room', 'date',)

my views.py:

class ShowRoom(View):
    def get(self, request):
        rooms = Room.objects.all()
        time_now = timezone.now().date()
        context = {
            'rooms': rooms,
            'time_now': time_now
        }
        return render(request, 'rooms/list_rooms.html', context)

My template:

{% extends 'rooms/base.html' %}

{% block block_title %} Home {% endblock %}

{% block block_content %} 
{% if rooms %}

    <table  class="table">
        <thead>
            <td> Name </td>
            <td> Capacity </td>
            <td> Available </td>
            <td> Projector </td>
        </thead>
        <tbody>
    {% for room in rooms|dictsort:'capacity'  %}
        <tr>
            <td>  <a href="{% url 'rooms:detail_room' room_pk=room.pk %}">{{ room.name }}</a>  </td>
            <td> {{ room.capacity }} </td>
            <td>  Available? </td>
            <td> {{ room.projector|yesno:'yes,no' }} </td>
            
        </tbody>
    {% endfor %}
</table>
{% else %}
    <h1> You have no registered rooms yet. </h1>
{% endif  %}
{% endblock %}

Everything works fine, I need just to replace this <td> Available? </td> line with a code, which would display "free" or "occupied" according to existing room reservations.

I've found out that maybe I should write a custom filter.

Here is my filter:

from django import template 
from rooms.models import Room, Reservation

register = template.Library()


@register.filter
def check_reservation(queryset, now):
    return queryset.filter(date=now)

(I wanted first to make it working, and after make it display this "free" or "occupied".)

I've added to the template {% load my_extras %} and replaced the line I want to change with

<td>  {{ room.reservation_set.all|check_reservation:'time_now' }} </td>

The output is:

ValidationError at /room/ ["'time_now' value has an invalid date format. It must be in YYYY-MM-DD format."]

Before adding the filter, I was trying this solution in the shell and it was working.

I don't know if there is something wrong with the filter, or I try to approach the issue from wrong side.

Thanks in advance for any tips.


Solution

  • Try adding another field to the the Room class:

    occupied = model.BooleanField(default=False)
    

    In the views you can check the date associated with the reservation and today's date.

    if reservation.date == time_now:
      room.occupied = true
    

    You can then filter with rooms that are available and which are not.

    rooms_occupied = room.objects.filter(occupied=True)
    rooms_available = room.object.filter(occupied=False)
    

    In the template:

    {% if rooms_occupied %}
      Available
    {% endif %}