Django auto_now count results in a certain date - django

I want filter of all request done is done in a certain date
class Log(models.Model):
request = models.CharField(max_length=255)
created_at = models.DateField(default=now, blank=True)
def __str__(self):
return self.request
But I don't how to do it correctly compare both the created_at and the date today
quantity_of_requests = Log.objects.filter(created_at=now()).count()
The objective is to take the current of date and count how many logs was added until now. But I also want to keep track of the time the request made.
I tried with this function but it takes of the time and put to 0:
datetime.today().strftime('%Y-%m-%d')
Edit:
I did by doing this:
class Log(models.Model):
request = models.CharField(max_length=255)
created_at = models.DateTimeField(blank=True, auto_now=True)
def __str__(self):
return self.request
quantity_of_requests = Log.objects.filter(created_at__contains=datetime.today().strftime('%Y-%m-%d')).count()
I would like to know a better way to write this code

Your now gets initated when your django process runs. To correctly get local time every time, either override save() to set it or use auto_now=True on DateField.
Ref: https://docs.djangoproject.com/en/3.1/ref/models/fields/#django.db.models.DateField.auto_now

Related

Checking if a field in model is modified and creating instance of another model

I have two models
Project Model
class Project(models.Model):
name = models.CharField(max_length=200)
workflow = models.ForeignKey("WorkflowType", null=True, blank=True, on_delete=models.SET_NULL)
created_on = models.DateTimeField(auto_now_add=True)
id = models.UUIDField(default=uuid.uuid4, editable=False, unique=True, primary_key=True)
def __str__(self):
return self.name
Workflow Instance Model
class WorkflowInstance(models.Model):
workflow_step = models.ForeignKey('WorkflowStep', null=True, blank=True, on_delete=models.CASCADE)
project = models.ForeignKey('Project', null=True, blank=True, on_delete=models.SET_NULL)
I want to check if the value of workflow field in "Project" models is added or changed for a particular project.
I am approaching the problem in following manner:
Checking if the previous and the new value of the "workflow" field in a project are different. If yes (modifies), then create the new instance of a project.
#receiver(pre_save, sender=Project)
def projectToBeUpdated(sender, instance, **kwargs):
if instance.id is None:
pass
else:
previous = Project.objects.get(id=instance.id)
if previous.workflow != instance.workflow:
print("workflow value modified. Please create a WorkflowInstance")
Problem: The comparison for previous and new value of the "workflow" field are happening in "pre_save" signal. But my new instance creation for workflowInstance is to be created in "post_save" signal. How can I do this?
Also, ideally I would like to store the previous value of workflow field in "pre_save" and get the new value of the field in "post_save". Reason being, save() method might fail for any reason, while I am comparing the previous and new value in "pre_save" method itself. Making changes in the database without confirming if the save() method executed successfully would be a wrong approach in my view.
You can override the model save method itself and use the following code logic, additionally if you want to identify what fields got modified you can use the dirtyfields package as well.
def save(self, *args, **kwargs):
if not self._state.adding:
changed_attr = self.get_dirty_fields()
else:
is_new = True
super().save(*args, **kwargs)```

how can i add an expiration date function on a model?

i am trying to make a key verification app that when accepted it would create the same app on the user's profile, so i have done everything but i have struggled making the expiration date part, i want the expired boolean become true when the date is expired, but i have no idea on how to implement it
#models.py
class ProductKey(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE,
unique=False)
key = models.CharField(max_length=14)
valid_from = models.DateTimeField(default=timezone.now)
valid_to = models.DateTimeField()
expired = models.BooleanField(default=False)
Please do not add a database field for this. You will introduce data duplication: if you later set the valid_to, you will have to update expred as well, so the logic would introduce extra challenges.
You can annotate your ProductKey model, such that objects that arise from this have an attribute expired:
from django.db.models import BooleanField, ExpressionWrapper, Q
from django.db.models.functions import Now
ProductKey.objects.annotate(
expired=ExpressionWrapper(Q(valid_to__lt=Now()), output_field=BooleanField())
)
You can then filter on that property. For example you can retrieve the ProductKeys that are expired with:
ProductKey.objects.annotate(
expired=ExpressionWrapper(Q(valid_to__lt=Now()), output_field=BooleanField())
).filter(expired=True)
If you need this often, you can annotate this in the manager, like:
class ExpiredManager(models.Manager):
def get_queryset(self):
return super().get_queryset().annotate(
expired=ExpressionWrapper(Q(valid_to__lt=Now()), output_field=BooleanField())
)
class ProductKey(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE,
unique=False)
key = models.CharField(max_length=14)
valid_from = models.DateTimeField(default=timezone.now)
valid_to = models.DateTimeField()
objects = ExpiredManager()
You could use a property for this use case and calculate that on the fly.
#property
def expired(self):
# calculate here if its still valid

Why doesn't function call in Django models refresh values if it includes a db query while other functions work fine?

Here's my code from models.py which only pulls values the first time but not again:
def slist():
return list(set(Product.objects.values_list('servicecat', flat=True)))
class CustomerProduct(models.Model):
pub_date = models.DateField(verbose_name="Date Data Last Refreshed", default=timezone.now)
servicecat = models.CharField(max_length=50, verbose_name='Service Category', null=True, blank=True, choices=tuple(zip(slist(), slist())))
It works fine, but it will only pull the values once. timezone.now works dynamically, but slist() does not. Why?

Django: DateTime not good when saved on my database

It seems stupid but i have hard time since hours and hours about saving my dateTime on db. I'm pretty new in Python and it's not everyday that i'm manipulating datetime.
I have one hour of difference when i'm saving my value. So 18h is now 17h (sorry for my english)
My models is like this:
class Event(models.Model):
title = models.CharField(max_length=245)
description = models.TextField(max_length=750, null=True, blank=True)
start = models.DateTimeField()
end = models.DateTimeField()
created_at = models.DateTimeField(editable=False)
updated_at = models.DateTimeField(editable=False)
slug = AutoSlugField(populate_from='title', unique=True, editable=False)
nb_participant = models.PositiveSmallIntegerField(default=1)
price = models.PositiveSmallIntegerField(default=0)
user = models.ForeignKey(User, editable=False, related_name='author')
address = models.ForeignKey('Address', editable=False, related_name='events')
participants = models.ManyToManyField(User, related_name='participants', blank=True)
class Meta:
db_table = 'event'
def save(self, *args, **kwargs):
if not self.pk:
self.created_at = timezone.localtime(timezone.now())
print self.created_at
self.updated_at = timezone.localtime(timezone.now())
super(Event, self).save(*args, **kwargs)
As you see i have 4 fields with datetime. 2 are actually save automatically save when the model is created.
I resolved the probleme by using timezone.localtime(timezone.now()) instead of timezone.now(). I find that there enter link description here at the bottom of the page. But they said to use timezone.now() in most case. So i don't know why i have this one hour difference.
I have two other fields that are send from my angular frontend to my API( using django rest framework)
I put a screenshot. The first object i send by angular.As you seen the date is well formatted.
The second object is the response from my API and i have lost one hour (so the GMT +1)
Why ? I'm totally block so if someone has a solution, i'll be very happy :)
My settings.py:
LANGUAGE_CODE = 'fr-fr'
TIME_ZONE = 'Europe/Paris'
USE_L10N = True
USE_TZ = True
Thanks.
In settings file try with USE_TZ=False, and use normal datetime.now().

How to Model a TimeField in Django?

I have modeled a class called ConversationHistory. Whenever an instance is created I wish to set the current date and current time.
class ConversationHistory(models.Model):
contact_date = models.DateField(_(u"Conversation Date"), blank=True)
contact_time = models.DateTimeField(_(u"Conversation Time"), blank=True)
def __init__(self, *args, **kwargs):
super(ConversationHistory, self).__init__(*args, **kwargs)
self.contact_date = datetime.datetime.now()
self.contact_time = datetime.datetime.now()
The idea is that the user can later still adjust the date and time as two different fields.
I am now a bit lost how to make the time field only to show and accept time, rather than date and time. I recon it is not possible to have a time field without datetime, but then how would I show only the time in the form?
If you want only time, TimeField is what you need:
class ConversationHistory(models.Model):
contact_date = models.DateField(_(u"Conversation Date"), blank=True)
contact_time = models.TimeField(_(u"Conversation Time"), blank=True)
You can take advantage of the auto_now_add option:
class TimeField([auto_now=False, auto_now_add=False, **options])
A time, represented in Python by a datetime.time instance. Accepts the
same auto-population options as DateField.
If you use the auto_now_add, it will automatically set the field to now when the object is first created.
class ConversationHistory(models.Model):
contact_date = models.DateField(_(u"Conversation Date"), auto_now_add=True, blank=True)
contact_time = models.TimeField(_(u"Conversation Time"), auto_now_add=True, blank=True)