im using the range fields feature for postgrest in Django, and i made a model in wich the date from and date to are stored in a range for checking if it overlaps, but there is a problem, if the date from and date to are the same date the model get stored like this.
DateRange(empty=True)
I tested that this DateRange feature can store a range that has the same date at start and at the end if i test it in the shell, but, in the model when it gets saved it just save it like i just mentioned before.
¿What can i do?
Edit:
This is the code.
class Reservaciones(models.Model):
class Meta:
verbose_name_plural = "Reservaciones"
def random_string():
return str(
randint(10000, 999999999)
)
fechas_semana = [
timezone.localdate() + timedelta(days=i)
for i in range (
0 - date.today().weekday(),
7 - date.today().weekday()
)
]
fecha_vie = fechas_semana[4]
ESTADOS= (
("Pendiente", "Pendiente"),
("Reservado", "Reservado"),
("Usado", "Usado"),
)
nucleo = models.ForeignKey(
Nucleo,
on_delete = models.CASCADE,
null = False,
blank = False,
limit_choices_to = {
'estado': "Activo"
}
)
cabaña = models.ForeignKey(
Cabaña,
on_delete = models.CASCADE,
null = False,
blank = False,
limit_choices_to = {
'estado': "Activo"
}
)
estado = models.CharField(
max_length = 10,
choices = ESTADOS,
default = "Pendiente",
null = False,
blank = False
)
fecha_desde = models.DateField(
null = True,
blank = True,
)
fecha_hasta = models.DateField(
null = True,
blank = True,
)
fechas = DateRangeField(
)
fecha_exp = models.DateField(
null = False,
blank = False,
)
usuario = models.ForeignKey(
get_user_model(),
on_delete = models.CASCADE,
null = False,
blank = False
)
codigo = models.CharField(
max_length = 10,
editable = False,
unique = True,
default = random_string,
null = False,
blank = False
)
envio = models.DateTimeField(
auto_now = False,
auto_now_add = True
)
envio_dia = models.DateField(
auto_now = False,
auto_now_add = True
)
actualizado = models.DateTimeField(
auto_now = True,
auto_now_add = False
)
observacion = models.TextField(
null = True,
blank = True
)
id = models.UUIDField(primary_key=True, default=uuid4, editable=False)
def __str__(self):
return "%s" % self.codigo
def save(self, *args, **kwargs):
self.fechas = DateRange(self.fecha_desde, self.fecha_hasta)
super(Reservaciones, self).save(*args, **kwargs)
def clean(self):
if Reservaciones.objects.filter(fechas__overlap=DateRange(self.fecha_desde - timedelta(days=1), self.fecha_hasta + timedelta(days=1))
).filter(
nucleo = self.nucleo
).filter(
cabaña=self.cabaña
).exclude(
codigo = self.codigo
).difference(
Reservaciones.objects.filter(estado="Pendiente", fecha_exp__lt=timezone.localdate())
).exists():
raise ValidationError("Ya existe una reservación para esta cabaña en las fechas que haz seleccionado.")
elif self.fecha_desde == self.fecha_hasta and Reservaciones.objects.filter(
fecha_desde=self.fecha_desde
).filter(
fecha_hasta=self.fecha_hasta
).filter(
nucleo = self.nucleo
).filter(
cabaña=self.cabaña
).exclude(
codigo = self.codigo
).difference(
Reservaciones.objects.filter(estado="Pendiente", fecha_exp__lt=timezone.localdate())
).exists():
raise ValidationError("Ya existe una reservación para esta cabaña en las fechas que haz seleccionado.")
elif self.fecha_hasta < self.fecha_desde:
raise ValidationError("La fecha maxima de la reservación no puede ser inferior a la fecha de inicio de la misma.")
elif self.cabaña_id not in list(Cabaña.objects.filter(nucleo=self.nucleo, id=self.cabaña_id).values_list('id', flat=True)):
raise ValidationError("Esta cabaña no existe en este nucleo.")
This work just perfect to validate the dates.
But for this bussines logic, i just let the users choose from the form the dates and room (Cabaña) that are not occupied
def ReservacionCargarCabañaView(request):
nucleo = request.GET.get('nucleo')
fecha_desde = request.GET.get('fecha_desde')
fecha_hasta = request.GET.get('fecha_hasta')
fecha_desde = datetime.strptime(fecha_desde, '%Y-%m-%d') - timedelta(days=1)
fecha_hasta = datetime.strptime(fecha_hasta, '%Y-%m-%d') + timedelta(days=1)
fecha_desde = date(fecha_desde.year, fecha_desde.month, fecha_desde.day)
fecha_hasta = date(fecha_hasta.year, fecha_hasta.month, fecha_hasta.day)
cabaña = Cabaña.objects.filter(
nucleo=nucleo
).exclude(
estado="Inactivo"
).exclude(
id__in=Reservaciones.objects.filter(fechas__overlap=DateRange(fecha_desde, fecha_hasta)
).exclude(
id__in=Reservaciones.objects.filter(estado="Pendiente", fecha_exp__lt=timezone.localdate()).values_list('id')
).values_list(
'cabaña'
)
).order_by(
'cabaña'
)
return render(
request,
'socios/formulario/cabaña_opciones_lista.html',
{
'cabaña': cabaña,
}
)
But if for example i choose in fecha desde and fecha hasta the same date to make a reservation for a single date, the form does not hide the rooms (Cabañas).
The form ajax list does not hide the "Cabaña 1" because that reservation made for date 18/4/2018 has a DateRange empty has i stated before.