0

Im working on a Django project and I have to make a query that returns all my record that are active at the moment. The query must be between(startdate, startdate + duration)

I got this query so far, but I don't know how to query startdate + duration < datetime.now()

View:

def home(request):
  active_tasks = Task.objects.all().filter(start_time__lte=datetime.now())
  context = {'active_tasks' : active_tasks}
  return render(request, "main/home.html", context)

Task model:

class Task(models.Model):
  start_time = models.DateTimeField(default=datetime.now())
  duration = models.IntegerField(default=10)
Ron Nabuurs
  • 1,528
  • 11
  • 29
  • 1
    Is there a good reason you store a duration in your model instead of an end time? An end time would be significantly easier to query. You could still have a duration as a calculated property if you need to display it somewhere. – solarissmoke Jun 14 '16 at 13:01
  • He could somehow use django annotation, for example the postgresql has a lot of extra function for datetime so something like this: http://stackoverflow.com/questions/8432926/aggregate-difference-between-datetime-fields-in-djano would be possible. But I think its an overkill – Visgean Skeloru Jun 14 '16 at 13:19
  • I used a duration of minutes, because its easier to fill in a form then to fill in an enddate everytime. And the tasks only take a few minutes. – Ron Nabuurs Jun 14 '16 at 13:46

1 Answers1

1

Your code has several defects. First, it's not clear for us what unit does duration have, days, months, years, minutes?

I assume you were using days, but you couldn't query that because you need to convert start_time + duration to datetime and treat it as end time for each record, which is not possible in single query. As @solarissmoke mentioned, you should store the end_time instead. You could keep the duration field if you want, but you could also use a property method to calculate it.

Also, your field definition start_time = models.DateTimeField(default=datetime.now()) would not work, because the default time would only be evaluated once when django starts(when the model is loaded). It's a common mistake that new django developers make. You should change it to:

start_time = models.DateTimeField(default=datetime.now)

This case, datetime.now would be treated as a function object and be called every time you create a new object, which is what you want. Note that django has the built in flag to do that: auto_now_add.

Check this SO answer on more detailed explanation.

Community
  • 1
  • 1
Shang Wang
  • 24,909
  • 20
  • 73
  • 94
  • Ill change my datetime.now() to datetime.now. Im using a duration of minutes. I choose for this, because its easier to fill in a form instead of an end date. I know its alot more difficult to query now, but isn't there a solution for this? – Ron Nabuurs Jun 14 '16 at 13:45
  • As I said, just add a field called `end_time`, so when you save the model, calculate the `end_time` from `start_time` and `duration` and fill the field. Does that make sense? – Shang Wang Jun 14 '16 at 13:46
  • That makes a lot of sense. I'll try to implement this in a bit, first I have some other stuff to do. I'll report back. – Ron Nabuurs Jun 14 '16 at 13:49
  • Now im trying to calculate the endtime with the starttime and duration. You said you can do it when you save the model. But isnt there a possibility to do this in de model it self? – Ron Nabuurs Jun 14 '16 at 14:17
  • What do you mean `do this in the model itself`? – Shang Wang Jun 14 '16 at 14:19
  • In the form to fill in I only want to have start_time and duration. Then the model calculates the end_time field it self. It that possible? – Ron Nabuurs Jun 14 '16 at 14:22
  • You could save the form `obj = form.save()`, do the calculation in the views, then do `obj.end_time = calculated_end_time`, `obj.save()`, right? – Shang Wang Jun 14 '16 at 14:27
  • I think I'll go with that. I think it would be nicer if the model it self calculates the end date, but the view can also handle that I suppose. – Ron Nabuurs Jun 14 '16 at 14:31
  • You can do that, but if your model calculates the end date but not storing it, we came back to the problem of not being able to do the query, right? – Shang Wang Jun 14 '16 at 14:32
  • In fact, I would rather you store `start_time` and `end_time`, but calculate `duration` in model instead. – Shang Wang Jun 14 '16 at 14:33
  • The model can calculate the enddate indeed, but then we are at my point again. I rather dont want to input a datetime for the endate, because filling in a duration is much easier. – Ron Nabuurs Jun 14 '16 at 14:42
  • Well im trying to do the `obj = form.save()` , but I get an error: `obj.end_date = obj.start_date + timedelta( AttributeError: 'Task' object has no attribute 'start_date'` – Ron Nabuurs Jun 14 '16 at 14:50
  • No, you still let user fill in duration, but in views you only store `start_time` and `end_time`. You should make your project more flexible as a common practice, you shouldn't always model exactly what the user input is, even if it's a `ModelForm`, think outside the box. – Shang Wang Jun 14 '16 at 14:50
  • Stackoverflow is no place for interactive exercise. I can only help you so much on the general thinking, you should be able to figure out the debug stuff yourself. Your variable name is wrong, not `start_date`, it's `start_time`. – Shang Wang Jun 14 '16 at 14:55
  • Haha wow, I didnt see that. Well I thank you for your help and I hope i'll work it out. – Ron Nabuurs Jun 14 '16 at 15:01