i used last() to get last item of queryset after exclude some items as below:
holidays = HolidayModel.objects.all().values_list('date', flat=True)
result = BorseExchangeLog.objects.exclude(
hint_time__date__in=holidays
)
# output 1
print(list(result.valuse_list('hint_time__date',flat=True).distinct('hint_time__date')))
#output2
print(result.last().hint_time.date())
but in output2 print item that not exists in output1
i test some other codes as below:
print(list(logs.values_list('hint_time__date',flat=True).distinct('hint_time__date')))
print(list(logs.values_list('hint_time__date', flat=True).distinct('hint_time__date'))[-1])
print(logs.order_by('hint_time__date').last().hint_time.date())
[..., datetime.date(2020, 10, 21), datetime.date(2020, 10, 26)]
2020-10-26
2020-10-25
my holiday model:
class HolidayModel(models.Model):
creator = models.ForeignKey('accounts.Account', on_delete=models.PROTECT, verbose_name=_('Creator'))
reason = models.CharField(default='', max_length=200, verbose_name=_('Reason'))
date = models.DateField(default=timezone.now, verbose_name=_('Date'))
and other model is :
class BorseExchangeLog(models.Model):
create_time = models.DateTimeField(default=timezone.now)
hint_time = models.DateTimeField(default=timezone.now)
i test that by first() and problem was there too
what is problem? my code is wrong or bug from django orm?
using django2.2 and postgresql
Your datetimes are timezone aware but the date() method on datetime objects does not take the timezone into account, __date will take the timezone into account provided your DB supports it. Use the django.utils.timezone.localdate function to get a date taking into account the timezone
from django.utils.timezone import localdate
print(localdate(result.last().hint_time))
Related
I want to bring users who have not updated their salary information in the last 1 year. BUT WITH ORM not For Loop.
from simple_history.models import HistoricalRecords
class User(AbstractUser):
...
salary_expectation = models.IntegerField()
history = HistoricalRecords(cascade_delete_history=True)
################################################################
User.objects.filter(# MAGIC ) # Get users who have NOT updated their salary information in the last year
I can see that this is a package which has its documentation in querying its entries, see below:
https://django-simple-history.readthedocs.io/en/latest/querying_history.html
nevertheless you can do that intuitively following Django's normal behavior and a couple of SQL knowledge, I'd expect that history field's table most likely has a one-to-many relationship with the users table, so what I'd do is first open the database, find the column that shows the date of change, write down its name and then write this ORM query below
sub_query = ~Q(history__history_date__lte= "Replace with end of date", history__history_date__gte= "Replace with beginning of date", salary_expectation__isnull=False)
users = User.objects.filter(sub_query)
dont forget to import Q
from django.db.models import Q
You do not need to check HistoricalRecords class for this information.
Add created_at and updated_at (date_time_fields) fields to your User model
class User(...):
...
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
Queryset Code
from django.db.models.functions import Now, ExtractDay
from django.contrib.auth import get_user_model
User = get_user_model()
users = User.objects.annotate(
# Calculate duration between now and last update date saved
duration=models.ExpressionWrapper(
Now() - models.F("updated_at"),
output_field=models.DurationField()
),
# Extract the amount of days in the duration
days=ExtractDay('duration'),
# Check if the number of days between the 2 fields exceeds 1 year (365.25 Days)
last_update_beyond_a_year=models.Case(
models.When(
models.Q(days__gte=365.25),
then=True
),
default=False,
output_field=models.BooleanField()
)
# Then filter
).filter(last_update_beyond_a_year=True)
and Voila !
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
)
)
models.py
class Dibbs_Fields(models.Model):
hash = models.CharField(max_length=16)
nsn = models.CharField(max_length=32)
nomenclature = models.TextField()
technical_documents = models.TextField()
return_by = models.DateField()
How to filter this class in django views according to the date return_by ? I don't want to show the data that is expired i.e. if the return_by date is earlier than today's date, then it should not show.
You can do this:
from datetime import date
def func(request):
today = date.today()
data = Dibbs_Fields.objects.filter(
return_by__lt=today)
The code simply returns data are earlier than today's date.
EDIT
return_by__lt # less than
return_by__gt # greater than
return_by__gte # greater than or equal to
return_by__lte # less than or equal to
class MyModel(models.Model):
TRANSACTION_TYPE_CHOICES = (
('p', 'P'),
('c', 'C'),
)
status = models.CharField(max_length=50, choices=TRANSACTION_TYPE_CHOICES, default='c')
user = models.ForeignKey(User, db_index=True, on_delete=models.CASCADE,related_name='user_wallet')
date = models.DateField(auto_now=True)
amount = models.FloatField(null=True, blank=True)
def __unicode__(self):
return str(self.id)
I am a fresher in Python django and have a little knowledge in Django Rest Framework.
I have a model like above and I want to filter the date field by month and get distinct queryset by month.....Is there any default way to do this...
Thanks in advance
you can use TruncMonth with annotations
from django.db.models.functions import TruncMonth
MyModel.objects.annotate(
month=TruncMonth('date')
).filter(month=YOURVALUE).values('month').distinct()
or if you need only filter date by month with distinct you can use __month option
MyModel.objects.filter(date__month=YOURVALUE).distinct()
Older django
you can use extra, example for postgres
MyModel.objects.extra(
select={'month': "EXTRACT(month FROM date)"},
where=["EXTRACT(month FROM date)=%s"],
params=[5]
# CHANGE 5 on you value
).values('month').distinct()
This may help you
MyModel.object.values('col1','col2',...,'date').distinct('date')
OR try this:
from django.db.models.functions import TruncMonth
MyModel.objects
.annotate(month=TruncMonth('date')) # Truncate to month and add to select list
.values('month') # Group By month
.annotate(c=Count('id')) # Select the count of the grouping
.values('month', 'c') # (might be redundant, haven't tested) select month and count
I have a django model like this
class AthleteSubscription(models.Model):
user = models.ForeignKey(User, related_name="user_subscription", default='')
subscription_start = models.DateField(default=datetime.date.today)
subscription_end = models.DateField(default=datetime.date.today() + timedelta(30))
Where subscription_start is start date of subscription and subscription_end is the end date of subscription. Subscription is of 30 days. I want to get those records in which current date (date today) lies between subscription_start and subscription_end. How can I do this with django ORM.
qv = AthleteSubscription.objects.filter(subscription_start__gte=some_date, subscription_end__lte=some_date)