Hi I want service old book sale service for university student
I create ItemPost model and when user post their books, ItemPost's deadline saved in deadline
from django.db import models
from django.conf import settings
from django.utils import timezone
def localtime():
return timezone.localtime(timezone.now())
class ItemPost(models.Model):
title = models.TextField(
)
created_at = models.DateTimeField(
default=localtime
)
is_deleted = models.BooleanField(
default=False,
verbose_name="삭제된 포스트",
)
# 마감날짜를 구하는 함수
def deadline_def(self):
year_of_item_created = self.created_at.year
if self.created_at.month <= 6:
return timezone.datetime(year_of_item_created, 6, 30)
else:
return timezone.datetime(year_of_item_created, 12, 31)
deadline = property(deadline_def)
# 등록된 학기가 끝난 포스트인지 확인
def is_ended_semester_def(self):
now = timezone.now()
if now > self.deadline:
return True
return False
is_ended_semester = property(is_ended_semester_def)
def __str__(self):
return self.title
I want compare item's deadline, timezone.now()
and return True or False
but I can't if I command item.is_ended_semester
TypeError: can't compare offset-naive and offset-aware datetimes
how can i solved this problem?
item.deadline
> datetime.datetime(2017, 6, 30, 0, 0)
timezone.now()
> datetime.datetime(2017, 7, 14, 8, 50, 57, 91304, tzinfo=<UTC>)
I solved my problem, using timezone.utc
# 마감날짜를 구하는 함수
def deadline_def(self):
year_of_item_created = self.created_at.year
if self.created_at.month <= 6:
return timezone.datetime(year_of_item_created, 6, 30, tzinfo=timezone.utc)
else:
return timezone.datetime(year_of_item_created, 12, 31, tzinfo=timezone.utc)
Related
I have a model which contains date range i want to filter the data based on the range date
that is i want the data who's date range is 90 days from today's date.
class MyModel(models.Model):
name = models.CharField(max_length=255)
start_end_date = ranges.DateTimeRangeField(validators=
[validate_range_date_time])
so when we select the start date on page the end date will popoulate the same date but i cannot concatenate filter just by today date + timedelta(days=90) this is one single date and the field is date range, so how can i filter the date range data which is 90 days from now.
the model stores start_end_date as
'start_end_date': DateTimeTZRange(datetime.datetime(2022, 11, 29, 9, 15), datetime.datetime(2022, 11, 29, 10, 0),
Mymodel.objects.filter(start_end_date__contains=timezone.now() + timezone.timedelta(days=90))
timezone.now() + timezone.timedelta(days=90) = datetime.datetime(2022, 11, 29, 22, 52, 7, 759648)
the query is giving empty set
I think you could design the model more easily.
class MyModel(models.Model):
name = models.CharField(max_length=255)
start_date = models.DateTimeField()
end_date = models.DateTimeField()
Then you can find objects like the following.
target_time = timezone.now() + timezone.timedelta(days=90)
MyModel.objects.filter(start_date__lte = target_time).filter(end_date__gte = target_time)
As it's a DateTimeRangeField, I think your result can be achieved by using startswith and endswith just like that:
max_date = timezone.now() + timezone.timedelta(days=90)
MyModel.objects.filter(start_end_date__startswith__gte=timezone.now(), start_end_date__endswith__lte=max_date)
Hope it helps!
I haven't used this field myself, but in base of what i read from documentaition, it should be like this:
from psycopg2.extras import DateTimeTZRange
Mymodel.objects.filter(
start_end_date__contained_by=DateTimeTZRange(
timezone.now(),
timezone.now() + timezone.timedelta(days=90)
)
)
to check if any start_end_date field is in 90 days from now, you should also pass a datetime range.
edited:
from psycopg2.extras import DateTimeTZRange
Mymodel.objects.filter(
start_end_date__contained_by=DateTimeTZRange(
timezone.now(),
timezone.now() + timezone.timedelta(days=90),
start_end_date__lower_inc=False
)
)
I am currently trying to save a Django object. My code looks like this
boxscore = BoxScore.objects.create(**defaults)
print(defaults)
input(boxscore)
Here's the output:
{'away_first': 0, 'away_second': 6, 'away_third': 7, 'away_fourth': 17, 'away_final': 30, 'home_first': 0, 'home_second': 7, 'home_third': 0, 'home_fourth': 7, 'home_final': 14}
BoxScore object (190)
Here's my admin:
#admin.register(BoxScore)
class BoxScoreAdmin(ImportExportModelAdmin):
pass
Here's the model:
class BoxScore(Base):
home_final = models.IntegerField()
away_final = models.IntegerField()
home_first = models.IntegerField()
away_first = models.IntegerField()
home_second = models.IntegerField()
away_second = models.IntegerField()
home_third = models.IntegerField()
away_third = models.IntegerField()
home_fourth = models.IntegerField()
away_fourth = models.IntegerField()
home_ot = models.IntegerField(null=True)
away_ot = models.IntegerField(null=True)
Here's the whole helper function if that is relevant.
def create_boxscore(df):
defaults = {
'away_first': int(df.at[0, '1']),
'away_second': int(df.at[0, '2']),
'away_third': int(df.at[0, '3']),
'away_fourth': int(df.at[0, '4']),
'away_final': int(df.at[0, 'Final']),
'home_first': int(df.at[1, '1']),
'home_second': int(df.at[1, '2']),
'home_third': int(df.at[1, '3']),
'home_fourth': int(df.at[1, '4']),
'home_final': int(df.at[1, 'Final']),
}
try:
defaults['home_ot'] = int(df.at[1, 'OT'])
defaults['away_ot'] = int(df.at[0, 'OT'])
except:
pass
boxscore = BoxScore(**defaults)
boxscore.save()
return boxscore
However, nothing is showing in Django admin as being saved in the database. Why would this be and how do I fix it?
Update: I queried the database and confirmed nothing is being saved so it is not a Django admin display issue.
Update 2: If I run the sample above separately, it saves fine. However, if it is run within a helper function, nothing saves. Does being in a helper function cause saving difficulties?
Update 3: In the main function, I ran this line of code and nothing was saved:
if 'Final' in dfs[i].columns and '4' in dfs[i].columns:
defaults = {'away_first': 0, 'away_second': 6, 'away_third': 7,
'away_fourth': 17, 'away_final': 30, 'home_first': 0, 'home_second': 7,
'home_third': 0, 'home_fourth': 7, 'home_final': 14}
boxscore = BoxScore.objects.create(**defaults)
input(boxscore)
But this was still outputted so I know it's reaching that line of code:
BoxScore object (200)
In Django models, How to increment the date field using timezone.now?
working:
end_date = models.DateTimeField(default=timezone.now() + timezone.timedelta(days=365))
Not Working
end_date = models.DateTimeField(default=timezone.now + timezone.timedelta(days=365))
I think timezone.now is a function which runs every time when the object is created. so that error occurs.
You could use a function:
def f():
return timezone.now() + timezone.timedelta(days=365)
...
end_date = models.DateTimeField(default=f)
The current time in that timezone is the added with the timedelta anytime a new end_date is created by default:
>>> from django.utils import timezone
>>> from datetime import timedelta
>>> def f():
... return timezone.now() + timezone.timedelta(days=365)
...
>>> f()
datetime.datetime(2018, 6, 25, 19, 42, 49, 761389, tzinfo=<UTC>)
>>> f()
datetime.datetime(2018, 6, 25, 19, 43, 2, 953158, tzinfo=<UTC>)
Sample run with Django:
In [1]: from testapp import models
In [2]: models.Test.objects.create().date_added
Out[2]: datetime.datetime(2018, 6, 25, 20, 5, 28, 316214, tzinfo=<UTC>)
In [3]: models.Test.objects.create().date_added
Out[3]: datetime.datetime(2018, 6, 25, 20, 5, 33, 114624, tzinfo=<UTC>)
A good approach would be to use the post_save signal. Import it with
from django.db.models.signals import post_save and then create a handler function like this:
def handler_function(sender, instance, created, **kwargs):
if sender == YourModel and created:
instance.end_date = timezone.now() + timezone.timedelta(days=365)
instance.save()
post_save.connect(handler_function, sender=YourModel)
This will work for sure, I hope this also applies to your case. Let me know if you need further help!
Is it possible to filter a models.DateTimeField but only get the month in the filter object?
The field is:
time_stamp = models.DateTimeField(
default=timezone.now)
When I filter it, this is what I get:
[datetime.datetime(2016, 9, 22, 15, 2, 48, 867473, tzinfo=),
datetime.datetime(2016, 9, 22, 15, 4, 22, 618675, tzinfo=),
datetime.datetime(2016, 9, 22, 15, 5, 20, 939593, tzinfo=)]
The filter returns 3 rows, but clearly there is too much information. I only require the months, and maybe the year.
How can I achieve this?
Any help or direction would be appreciated,
Thanks
If you are using django 1.10.x there is Extract db function
from django.db.models.functions import Extract
months = MyModel.objects.annotate(month_stamp=Extract('time_stamp', 'month')).values_list('month_stamp', flat=True)
For django 1.9.x
from django.db.models import Func
def Extract(field, date_field='DOW'):
template = "EXTRACT({} FROM %(expressions)s::timestamp)".format(date_field)
return Func(field, template=template)
months = MyModel.objects.annotate(month_stamp=Extract('time_stamp', 'month')).values_list('month_stamp', flat=True)
You can use propety:
Class your_model(models.Model):
time_stamp = models.DateTimeField(
default=timezone.now)
#property
def _get_year(self):
return self.time_stamp.strftime("%Y-%m")
year = property(_get_year) #EDIT
I'd like to make an application that allows me to reserve an item during a specified period.
I need a function to check if the specified item is already booked during the period i want to use it (so the booking should fail). Can you help me?
models.py
from django.db import models
from datetime import *
from django.db.models import Q
import datetime
from django.core.exceptions import ValidationError
class Reservation(models.Model):
date_debut = models.DateTimeField('debut de la reservation')
date_fin = models.DateTimeField('fin de la reservation')
obj_res = models.ForeignKey('Materiel')
notice = models.CharField(max_length=200)
personne = models.ForeignKey('Personne')
def __int__(self):
return self.id
def save(self, *args, **kwargs):
new_start_date = datetime.datetime(2013, 11, 16, 10, 00)
new_end_date = datetime.datetime(2013, 11, 16, 11, 00)
material = Materiel.objects.get(nom="Bimaire 1")
clashing_reservations = Reservation.objects.filter(obj_res=material).filter(
Q(date_debut__lte=new_start_date, date_fin__gte=new_start_date) |
Q(date_debut__lt=new_end_date, date_fin__gte=new_end_date)
)
if clashing_reservations.exists():
raise ValidationError('Those dates clash with another reservation.')
return super(Reservation, self).save(*args, **kwargs)
class Materiel(models.Model):
nom = models.CharField(max_length=200)
description = models.CharField(max_length=200)
responsable = models.CharField(max_length=200)
modalites = models.CharField(max_length=200)
def __unicode__(self):
return self.nom
class Personne(models.Model):
nom = models.CharField(max_length=200)
prenom = models.CharField(max_length=200)
def __unicode__(self):
return self.nom
views.py
def reservation(request):
if request.POST:
form = ReservationForm(request.POST, request.FILES)
if form.is_valid():
form.save()
else:
form = ReservationForm()
args = {}
args.update(csrf(request))
args["form"] = form
return render_to_response("reservation.html", args)
EDIT
Thanks so far it's seems to work.
But now i want define that new_start_date and new_end_date are the actual values of the form.
This is untested code, but I believe that this logic should test whether any other reservations overlap the one submitted in the form. This should probably be put in a clean method of the form, or some other validation. Perhaps even on the save method of the Reservation model:
from django.db.models import Q
new_start_date = datetime.datetime(2013, 11, 16, 10, 00)
new_end_date = datetime.datetime(2013, 11, 16, 11, 00)
material = Materiel.objects.get(nom='Whatever')
clashing_reservations = Reservation.objects.filter(objet=material).filter(
Q(date_debut__lte=new_start_date, date_fin__gte=new_start_date) |
Q(date_debut__lt=new_end_date, date_fin_gte=new_end_date)
)
if clashing_reservations.exists():
raise ValidationError('Those dates clash with another reservation.')
I don't know the format your dates are in but regardless you can use the module datetime to compare (subtract, add, higher/lower etc.) dates and times with one another.
So I've made a simple example to illustrate its use (I presume your format is months/days/years):
from datetime import *
debut_date = datetime.strptime(date_debut_db, "%m/%d/%y")
fin_date = datetime.strptime(date_fin_db, "%m/%d/%y")
debut_date2 = datetime.strptime(date_debut_form, "%m/%d/%y")
fin_date2 = datetime.strptime(date_fin_form, "%m/%d/%y")
if (debut_date2 > debut_date and debut_date2 < fin_date) or (fin_date2 > debut_date and fin_date2 < fin_date):
print "Impossible!"
else:
print "Possible!"
date_debut_db and date_fin_db are the dates you get out of your database whereas date_debut_form and date_fin_form are the ones that the user fills in.