I'm building a bus booking website using Django. I have an attribute position in my table 'seat'. It is linked to bus(table) by ForeignKey. Whenever a bus is created, seat instances are created equal to the capacity of the bus(capacity is defined by the user in bus table). I want to name the positions like 1_1, 1_2, 1_4, 1_5, 2_1, 2_2, 2_4, 2_5 etc.. where the first digit before underscore represents row and digit after underscore represents a column. I'm not using 3 because it's the aisle.
this is my models.py
class Seat(models.Model):
class Meta:
verbose_name_plural = "Seat"
id = models.AutoField(primary_key=True,)
position = models.CharField(max_length=4)
bus = models.ForeignKey(Bus)
status = models.CharField(max_length=20, choices=(('available', 'available'), ('reserved', 'reserved'), ('unavailable', 'unavailable'),), default='Available')
def __str__(self):
return '{0}-{1}-{2}'.format((self.bus),(self.id),(self.status))
@receiver(post_save, sender=Bus)
def create_seats(sender, instance, created, **kwargs):
if created:
for seat in range (0, int(instance.capacity)):
instance.seat_set.create( )
This is how the naming of position is done
as you can see it's empty in the middle so for that 3rd column is not used. My question is how can automatically name the positions (like I create seats whenever a bus object is created) according to the chart without having to go in individual seat object and name the position. I hope you get my question. If you need any more info please let me know.
Assuming that the bus layout is always the same:
@receiver(post_save, sender=Bus)
def create_seats(sender, instance, created, **kwargs):
if created:
for place_num in range(1, int(instance.capacity)+1):
row = (place_num // 5) + 1
col = (place_num % 5) + 1
if col != 3 and row*col not in [24, 25]:
instance.seat_set.create(position='%i_%i' % (row, col))
This answer assumes the buses can have different seat layouts, which means you’ll need to define the seating pattern for each bus type.
The most basic way would be to define them as constants, as 2-dimensional lists/arrays, entering 1 for a seat and 0 for no seat:
#seating_patterns.py
BUS_1 = [
[1, 1, 0, 1, 1],
[1, 1, 0, 1, 1],
[1, 1, 0, 1, 1],
[1, 1, 0, 1, 1],
[1, 1, 0, 0, 0],
[1, 1, 0, 1, 1],
[1, 1, 0, 1, 1],
[1, 1, 0, 1, 1],
[1, 1, 1, 1, 1],
]
BUS_2 = [etc]
SEATING_ARRAYS = {'BUS_1': BUS_1, 'BUS_2': BUS_2}
To make this more maintainable you could create a SeatingPattern model, for instance with an ArrayField if that is an option for you.
Otherwise import the seating arrays into your models file:
# models.py
from .seating_patterns import SEATING_ARRAYS
and add a seating_pattern field to your bus model, with a choices tuple for the buses:
class Bus(models.Model):
…
SEATING_PATTERNS = (
('BUS_1', 'BUS_1'),
('BUS_2', 'BUS_2'),
)
…
seating_pattern = models.CharField(choices=SEATING_PATTERNS, max_length=50)
And create the correct format output (1_1, 1_2, etc) like this in your post_save signal:
if created:
seating_pattern = SEATING_ARRAYS[instance.seating_pattern]
for row,seats in enumerate(seating_pattern):
for pos,seat in enumerate(seats):
if seat:
Seat.objects.create(
bus=instance,
position="{}_{}".format(str(row+1), str(pos+1))
)