garreth
garreth

Reputation: 131

Django 1 Models - DateTimeField()

I am very new to Django and programming in general and I am facing a challenge I have not seen before. I a looking for a bit of help with DateTimeField().

As a learning project, I am setting up a simple travel app. I would like users to be able to add trips, descriptions, etc. So far, so good.

I would like to add two DateTimeFields to my trips model. The start_date entered must be a date in the future (from the time they are using the app), while the end_date will have to be after the start_date (natch). How do I program this into my models?

Here is my current code for my Trip class:

class Trip(models.Model):
    destination = models.CharField(max_length=55)
    description = models.TextField()
    start_date = models.DateTimeField(??)
    end_date = models.DateTimeField(??)

    travellers = models.ManyToManyField(User, related_name="trips")

    planned_by = models.ForeignKey(User, on_delete=models.CASCADE, related_name="trips_added")

    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

Thank you.

Update

Thanks to you guys I am getting closer. However, I think there is a wrinkle or two in DateField (I don't actually need DateTimeField) that I am missing. Here is my Trip table in models:

class Trip(models.Model):
    destination = models.CharField(max_length=55)
    description = models.TextField()
    start_date = models.DateField(null=True)
    end_date = models.DateField(null=True)

    travelers = models.ManyToManyField(User, related_name="trips")

    planned_by = models.ForeignKey(User, on_delete=models.CASCADE, related_name="trips_added")

    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    objects = TripManager()

Also in models, under my TripManager, I have the following validation method:

def trip_validation(self, postData):

        errors = {}

        if len(postData['destination']) < 1:
            errors['destination'] = 'You must enter trip destination.'

        if len(postData['description']) < 1:
            errors['description'] = 'You must enter trip description.'

        if len(postData['start_date']) < 1:
            errors['start_date'] = 'Please enter a start date for your trip.'
        elif not postData['start_date'] > timezone.now():
            errors['start_date'] = 'Your trip start date must be in the future.'

        if len(postData['end_date']) < 1:
            errors['end_date'] = 'Please enter an end date for your trip.'
        elif not self.end_date > self.start_date:
            errors['end_date'] = 'Trip end date must be after start date.'

        return errors

In views, I call the trip_validation method and sent the errors to the template via a context dict.

All of the validation methods work save elif not postData['start_date'] > timezone.now(): and elif not self.end_date > self.start_date:.

I get the following error: TypeError at /trips/add/ can't compare datetime.datetime to unicode.

This leads me to believe that I am not using the built-in DateField function properly somewhere along the line.

Thank you.

Upvotes: 2

Views: 3651

Answers (3)

Angela
Angela

Reputation: 1731

You need to convert into the right data type before comparing. You can use datetime.strptime() as shown below.

from datetime import datetime

s_date = datetime.strptime(postData['start_date'], "%Y-%m-%d")
e_date = datetime.strptime(postData['end_date'], "%Y-%m-%d")

Upvotes: 0

JPG
JPG

Reputation: 88449

I prefer to set those fields to blank=True and null=True and do some Validation checks by overriding the save() method of the Trip model, as

from django.utils import timezone
from django.core.exceptions import ValidationError


class Trip(models.Model):
    # your fields
    start_date = models.DateTimeField(blank=True, null=True)
    end_date = models.DateTimeField(blank=True, null=True)

    # your fields

    def save(self, *args, **kwargs):
        if self.start_date:
            if not self.start_date > timezone.now():
                raise ValidationError("start_time must be greater than current time")
        if self.end_date:
            if not self.start_date:
                raise ValidationError("start time missing. Please check the data")
            if not self.end_date > self.start_date:
                raise ValidationError("end time must be greater than start time")
        super().save(*args, **kwargs)

Upvotes: 1

Adrian
Adrian

Reputation: 198

You don't do that in the model. The model is simply a table in a database, so there you just define that the fields start_date and end_date are of the type DateTimeField. You can find more info here: Django Models

What you are trying to accomplish you ca do it in other part of Django, like in the view. There, when you get the dates inserted by the user, you can validate that start_date is in the future and end_date is after.

Upvotes: 0

Related Questions