I have a model
class Session(models.Model):
name = models.CharField(max_length=12)
active = models.BooleanField(default=False)
date = models.DateField()
startTime = models.TimeField()
The active field is set based on the date and start time.
For eg -
Suppose during the creation of an object, the date is for tomorrow, and let there be any time, I want to know the process and not the code on how and what to study to make this object active on that particular date and time.
BY default the active field is False, or should I change the way I'm thinking to implement it?
Thanks
I would advise to use a DateTimeField for the start timestamp, and make active a property, so:
from django.utils import timezone
class Session(models.Model):
name = models.CharField(max_length=12)
start = models.DateTimeField()
#property
def active(self):
return timezone.now() >= self.start
This will thus not store the active field in the database, but simply determine the value when needed.
Related
Some of my app models define date ranges (e.g. of contracts), where the current instance has no fixed end date (i.e. it should always evaluate to today). Setting the default parameter on the end field –
class Contract(models.Model):
building = models.ForeignKey(Building, on_delete=models.CASCADE)
service = models.ForeignKey(Service, on_delete=models.CASCADE)
begin = models.DateField()
end = models.DateField(default=datetime.date.today)
– will populate the field with a fixed value. A property to work around the problem –
class Contract(models.Model):
building = models.ForeignKey(Building, on_delete=models.CASCADE)
service = models.ForeignKey(Service, on_delete=models.CASCADE)
begin = models.DateField()
end = models.DateField(blank=True)
#property
def get_end(self):
if not self.end:
return datetime.date.today()
return self.end
– does not work with querysets. Is there any way to implement a truly dynamic value on the database level using Django's ORM?
The best options available for a sudo-dynamic DateField are auto_now and auto_now_add as mentioned in the comments. The former updates the DateField on each .save() call and the latter does it at creation (Django doc).
The other option, as mentioned by Adrian, is to set the end as Null and use a conditional query for your claen() function. You can do that either by introducing an if statement or by using Case() and When(). You can check this Django doc or see this answer for more information.
Update: In your case something like this should work:
today = datetime.today()
conflicts = Contract.objects.filter(building=building, begin__lte=Case(
... When(end=Null, then=today), default=end), end__gte=begin)
There are also other options for having a dynamic date in your model but not as a DateField, which I assume is not what you are looking for nor anything near a 'clean code'.
I have a model with a models.DateTimeField field and a CheckConstraint that prevents it from being in the past:
from django.db.models.functions import Now
class MyModel(models.Model)
title = models.CharField()
mydate = models.DateTimeField()
class Meta:
models.CheckConstraint(
check=Q(mydate__gte=Now()),
name='mydate_no_past'
),
I want the constraint to apply only when the record is first created, ideally using Django and not raw SQL (per this answer).
In the above example, if a valid entry is created but then later the system datetime moves past the mydate value, when the record is updated the CheckConstraint fails.
How do I avoid this?
What also confuses me is if I update only other fields on the record and not mydate the CheckConstraint still fails. E.g the following will also fail if the system date is after the mydate value:
mymodel = MyModel.objects.get(pk=1)
mymodel.title = 'Title'
mymodel.save(update_fields=['title'])
Why is this?
I'm developing a maintenance app, I can add tasks and get the exact time when it was created by implementing this:
created_date = models.DateTimeField(db_column='Date', auto_now_add=True) # Field name made lowercase.
I have a field called done:
done = models.BooleanField(db_column='Done', default=False) # Field name made lowercase.
Now what I need is to, when I set the done to 'True' it gives me the date and time at that moment, how can I achieve this?
Thanks
Create a method within the model and call that
class MyModel (models.Model):
done = models.BooleanField(db_column='Done', default=False)
complete_date = models.DateTimeField(blank=True, null=True)
def set_done(self):
self.done = True
self.complete_date = timezone.now()
self.save()
in your view you call object.set_done() where object is the instance of MyModel
I want to create a log system to register some faults I need to handle at my work. I use Django and my models look like these:
class Chan(models.Model):
channelname = models.CharField(max_length=30)
freq = models.FloatField(default = 0.0)
def __unicode__(self):
return u'%s' % (self.channelname)
# timestamp object
class EventTime(models.Model):
since = models.DateTimeField()
till = models.DateTimeField()
def __unicode__(self):
return u'%s' % self.since.strftime('%Y-%m-%d %H:%M')
class Fault(models.Model):
channel = models.ManyToManyField(Chan)
description = models.CharField(max_length=200, default="-")
message = models.TextField()
timeevent = models.ManyToManyField(EventTime,null=True)
visible = models.BooleanField()
Firstly I used just one EventTime object but I soon realized I need to be able to choose several time periods because the same event could happen several times a day. So it would be too tedious to create a new record of Fault each time. So I basically needed something like this:
The problem is that 'ManyToManyField' is too unhandy to use because I don't need to keep these values for other faults. So I don't know what solution I can use for it. I don't know how many time periods I need. Maybe I could add an extra Text field to my table where I would keep comma-separated datetime objects converted into a string like '2017-11-06 18:36,2017-11-06 18:37'. But I don't know where to set this extra-conversion because I want to use a standart DateTimeField in Django admin site to set it before I make this conversion. Or maybe I could change the interface itself and add some Javascript. Maybe someone could give me advice or share some useful links. Thank you.
I would recommend using a Many-to-one relation together with InlineModelAdmin for the django admin.
models.py
class Fault(models.Model):
channel = models.ManyToManyField(Chan)
description = models.CharField(max_length=200, default="-")
message = models.TextField()
visible = models.BooleanField()
class EventTime(models.Model):
since = models.DateTimeField()
till = models.DateTimeField()
fault = models.ForeignKey(Fault, on_delete=models.CASCADE, related_name='timeevents')
def __unicode__(self):
return u'%s' % self.since.strftime('%Y-%m-%d %H:%M')
admin.py
from .models import Fault, EventTime
from django.contrib import admin
class EventTimeInline(admin.TabularInline):
model = EventTime
#admin.register(Fault)
class FaultAdmin(admin.ModelAdmin):
# ...
inlines = [EventTimeInline,]
I am strungling to use the django queryset API reference with filters based on the DateTimeField.
I have prepared the following model, in my models.py:
class KleedkamerIndeling(models.Model):
gametimedate = models.DateTimeField(auto_now=False, auto_now_add=False) # date and time of game
hometeam = models.CharField(max_length=25, blank=True) # name of home playing team team
homedressroom = models.CharField(max_length=25, blank=True) # dressing room of home playing team
awayteam = models.CharField(max_length=25, blank=True) # name of visiting team team
awaydressroom = models.CharField(max_length=25, blank=True) # dressing room of visiting team team
pitch = models.CharField(max_length=25, blank=True) # name / number of playing pitch
referee = models.CharField(max_length=25, blank=True) # name of referee
refdressroom = models.CharField(max_length=25, blank=True) # name/number of referee dressroom
timestamp = models.DateField(auto_now_add=True, auto_now=False)
indelings_datum = models.DateField() # need to change to datum added later
def __unicode__(self):
return smart_unicode(self.hometeam)
I want to access the database based on the present date. Should be something like:
queryset = KleedkamerIndeling.objects.all().filter(gametimedate=date.today())
This worked before when I used a 'datefield' but I decided to go to a datetimefield because I also need the starting time of the game played.
I have seached the web and stackoverflow and found the following older topic, How can I filter a date of a DateTimeField in Django? but I stungle on the implemenation.
I want to create a queryset that obtains all the 'KleedkamerIndeling' that are available for today's date. Subsequently I want to check if there are more then 10 objects in the list. If that's the case than I want to further narrow it down based on the current time, also via a filter on the datetimefield. Lastly I want to sort the object list such that it is sorted on time.
I know that my problem has to do which the caracteristics of the datetimefield van I appreciate a couple lines of code to help me move foreward. I have been trying to find the right query in the python manage.py shell all afternoon....
My model most work because the queryset = KleedkamerIndeling.objects.all() seems to work and I am able to set up seperate list for each object called 'game0 through game10 from the queryset list.
I have a further issue on the datetimefield format:
I have defined a 'KleedkamerIndeling' that describes a game that starts at 13:00. I have used the objects in the queryset list to define 10 different 'game'objects. i.e. game0 = [queryset[0].hometeam etc... though game10 if applicable. The gametime field is displayed in the template via a filter like: {{game0.0|date:"H"}}:{{game0.0|date:"i"}}. I still end up with the ':' in the case of no game0 object. I plan to solve this via a if else script in the template or in the view, or is there a better way to fix this?
Since you are using a datetime field you want to make your query’s using datetime objects. so first order the queryset from earliest to latest then filter out the events tat arn't occurring today.
from datetime import datetime, timedelta, time
today = datetime.now().date()
tomorrow = today + timedelta(1)
today_start = datetime.combine(today, time())
today_end = datetime.combine(tomorrow, time())
queryset = KleedkamerIndeling.objects.order_by('-gametimedate').filter(gametimedate__gte=today_start).filter(gametimedate__lt=today_end)
After that we can check if there are more then 10 objects, filter by the current time, and limit the queryset to 10 objects.
if queryset.count() > 10:
queryset = KleedkamerIndeling.objects.filter(gametimedate__gte=datetime.now())[:10]