Я пытаюсь заполнить таблицу html из базы данных, но не могу найти хорошее решение для этого. Надеюсь, это не слишком широкий вопрос.
Я собираю данные о бронировании отелей и ценах на них, и хочу показать их на столе. Я работаю над этим довольно долго, но все еще борюсь, надеюсь, кто-нибудь сможет мне помочь.
Результат таблицы, который я пытаюсь получить:
В первом столбце указано время, когда было выполнено извлечение данных, а в верхнем столбце указано, на какие даты выполняется бронирование (дата заезда). Остальные - это цены.
+--------+-------+-------+-------+-------+
| | 1Apr | 2Apr | 3Apr | 4Apr |
+--------+-------+-------+-------+-------+
| 11am | 40(A) | 40(A) | 40(A) | 40(A) |
| 1110am | 40(X) | 40(X) | 42(A) | 42(A) |
| 1120am | | | | |
+--------+-------+-------+-------+-------+
Основная модель - это PriceDatum, где хранятся все цены, а другой важной моделью для этой таблицы является RoomScans, в которой хранится время, когда было выполнено сканирование.
models.py :
class PriceDatum(models.Model):
room_scan = models.ForeignKey(RoomScan,default=1, on_delete=models.CASCADE)
room = models.ForeignKey(Room, on_delete=models.CASCADE)
checkin = models.DateField(db_index=True, help_text="Check in date", null=True)
checkout = models.DateField(db_index=True, help_text="checkout date", null=True)
price = models.PositiveSmallIntegerField(help_text="Price in the currency stated")
refund_status = models.CharField(max_length=100, default="N/A")
scanned = models.DateTimeField(db_index=True, help_text="Check in date", null=True)
availability_count = models.PositiveSmallIntegerField(help_text="How many rooms are available for this price")
max_people = models.PositiveSmallIntegerField(help_text="How many people can stay in the room for this price")
meal = models.CharField(max_length=100, default="N/A", help_text="Tells if breakfast is included in room price")
class RoomScan(models.Model):
property_scan = models.ForeignKey(PropertyScan, on_delete=models.CASCADE)
room = models.ForeignKey(Room, on_delete=models.CASCADE, default=None)
time_scanned = models.DateTimeField(auto_now_add=True, null=True)
class Room(TimeStampedModel):
property = models.ForeignKey(Property, on_delete=models.CASCADE,
help_text="The BDC property in which the room is located")
room_id = models.PositiveIntegerField(unique=True, help_text="The bdc_id is unique from bdc website", null=True)
name = models.CharField(max_length=300, null=True, blank=True)
views.py
class AverageHistory(TemplateView):
template_name = "Scan/average.html"
def get_context_data(self, room_id=None, **kwargs):
filter_class = RoomFilter
ordering_fields = ('meal', 'refund', 'people')
search_fields = ('meal', 'refund', 'people')
selected_room = Room.objects.get(room_id=room_id)
max_people_count = selected_room.pricedatum_set.all().aggregate(Max('max_people'))['max_people__max']
meal_count = selected_room.pricedatum_set.filter(meal='not_included').count()
# todo think how to handle unavailable rooms so we don't need query them separately and join queryset,
if meal_count == 0:
meal = 'included'
else:
meal = 'not_included'
unavailable_rooms_prices = selected_room.pricedatum_set.filter(availability_count=0).distinct()
available_rooms_prices = selected_room.pricedatum_set.filter(refund_status='refund', max_people=max_people_count,
meal=meal).order_by().order_by('checkin').distinct()
x = len(available_rooms_prices)
price_data = sorted(
chain(unavailable_rooms_prices, available_rooms_prices),
key=attrgetter('checkin'))
ur_dates = list(unavailable_rooms_prices.values('checkin', 'checkout').distinct().order_by('checkin'))
ar_dates = list(available_rooms_prices.values('checkin', 'checkout').distinct().order_by('checkin'))
a = len(ar_dates)
if ur_dates is not None:
ar_dates.extend(ur_dates)
col_count = list(range(len(ar_dates)))
# todo: keep an eye if rooms might be only 'non_refundable' or 'partially_refundable', now we read only refundable one's
# because we need highest price.
# Room list to have details about selected room to show the name on the template.
room_list = []
# Room dictionary to store details about room.
room_name_dict = {
'room': selected_room
}
room_scan = selected_room.roomscan_set.all()
# Room dictionary appended to room list, so it can be added to data context.
room_list.append(room_name_dict)
ar_dates = sorted(ar_dates, key=lambda r: r['checkin'])
context = {'room_details': room_list,
'room_scan': room_scan,
'price_data': price_data,
'dates': ar_dates,
'table': available_rooms_prices,
'col_count': col_count
}
return context
template
<table class="table table-bordered table-striped">
<tbody>
<tr>
<td>
Booking Dates >
##############
Time Scanned v
</td>
{% for d in dates %}
<td>
{{ d.checkin|date:"d/m/y" }}-{{ d.checkout|date:"d/m/y" }}
</td>
{% endfor %}
</tr>
{% for i in room_scan %}
<tr>
<td>
{{ i.time_scanned|date:"d/m/y h:i" }}
</td>
{% for x in col_count %}
<td>
{{ price_data|get_at_index:x}} [{{forloop.counter}}]
</td>
{% endfor %}
{% endfor %}
</tr>
</tbody>
</table>
Вопрос: Мой вопрос: как мне заполнить таблицу, чтобы каждая цена отображалась только в той строке, где она связана со временем очистки на левой стороне
Текущий результат:
С моим текущим кодом одна и та же цена печатается в каждой строке. Потому что я печатаю их из списка price_data, где хранятся все цены, поэтому мне нужно выполнить некоторую фильтрацию по шаблону или даже по представлению.
Извините, если он слишком широк или недостаточно объяснен, попробовал мойлучший.