I have model like this:
class Order(models.Model):
dateTime = models.DateTimeField()
and I want to get object with specific hour
how can I do that?
the code below doesn't work:
o=Order.objects.get(dateTime.hour=12)
and has this problem: keyword can't be an expression
now.. How should I give the order object with specific time?
The following will give you all the objects having hour value as 12.
o = Order.objects.filter(dateTime__hour=12)
which can be used in place of
o = Order.objects.get(dateTime__hour=12)`
to get that one object, in case you have unique hour values for objects.
But if already know that you have unique value of hour then you should use
the later.
https://docs.djangoproject.com/en/1.9/ref/models/querysets/#hour
o = Order.objects.filter(dateTime__hour=12)
Related
I'll demonstrate by using an example. This is the model (the primary key is implicit):
class Item(models.Model):
sku = models.CharField(null=False)
description = models.CharField(null=True)
I have a list of skus, I need to get the latest descriptions for all skus in the filter list that are written in the table for the model Item. Latest item == greatest id.
I need a way to annotate the latest description per sku:
Item.objects.values("sku").filter(sku__in=list_of_skus).annotate(latest_descr=Latest('description').order_by("-id")
but this won't work for various reasons (excluding the missing aggregate function).
Item.objects.values("sku").filter(sku__in=list_of_skus).annotate(latest_descr=Latest('description').lastest("-id")
Or use this
Item.objects.values("sku").filter(sku__in=list_of_skus).annotate(latest_descr=Latest('description').order_by("-id").reverse()[0]
I used postgres ArrayAgg aggregate function to aggregate the latest description like so:
from django.contrib.postgres.aggregates import ArrayAgg
class ArrayAggLatest(ArrayAgg):
template = "(%(function)s(%(expressions)s ORDER BY id DESC))[1]"
Item.objects.filter(sku__in=skus).values("sku").annotate(descr=ArrayAggLatest("description"))
The aggregate function aggregates all descriptions ordered by descending ID of the original table and gets the 1st element (0 element is None)
Answer from #M.J.GH.PY or #dekomote war not correct.
If you have a model:
class Item(models.Model):
sku = models.CharField(null=False)
description = models.CharField(null=True)
this model has already by default order_by= 'id',
You don't need annotate something. You can:
get the last object:
Item.objects.filter(sku__in=list_of_skus).last()
get the last value of description:
Item.objects.filter(sku__in=list_of_skus).values_list('description', flat=True).last()
Both variants give you a None if a queryset is empty.
Hi guys would appreciate some help. I'm analyzng a series (a set of columns) that has a date format like this:
'1060208'
The first three digits represent the year where the first digit, '1' exists for comparison purposes. in the case above, the year is 2006. the 4th and 5th digit represent the month and the rest represents the day. I want to convert these dates to something like this
106-02-08
So that i can use .groupby to sort per month or year. Here is my code so far
class Data:
def convertdate(self):
self.dates.apply(lambda x:x[0:3] + '-' + x[3:5] + '-' + x [5:7])
return self.dates
when I run this, I get the error:
TypeError: 'int' object is not subscriptable
Can you please tell me what went wrong? Or can you suggest some alternative way to do this? Thank you so much.
Assumings that dates is a list of int, you can do:
input_dates = [1060208, 1060209]
input_dates_to_str = map(lambda x: str(x), input_dates)
output = list(map(lambda x: '-'.join([x[0:3], x[3:5], x[5:]]), input_dates_to_str))
Anyway, when working with dates I suggest you using datetime package.
Quick answer to your question: 1060208 is an integer, integers are not subscriptable, so you need to change it to a string.
Some other thoughts:
Where is your data? Is this all in a pandas dataframe? If so why are you writing classes to convert your data? There are better/faster ways of doing it. Like convert your intgeger date to a string, get rid of the first digit, and convert it to datetime.
What does "where 1 is put for comparison purposes" mean? It could have been recorded that way but obviously a date and a flag (I assume it is some kind of flag) should not be represented in the same field. So why don't you put that 1 in a field of its own?
I want to make a request in Django where I group by day but I want to fill the day where there is no result with 0, is it possible?
# I use the following query
AccessLog
.objects
.filter(attempt_time__gte=last_30_days)
.annotate(day=TruncDay('attempt_time'))
.values('day', 'username')
.annotate(c = Count('username'))
.order_by('day')
No, it is not possible with annotations. Annotations work with the similar types, for example, Coalesce function requires similar types and mixing datetime and numbers will result in a database error. The same for the Case function there is only one output field per result.
The function TruncDay returns a DateTime (in this case) with fields up to Day set to their minimum value, so for instance 2015-06-15 14:30:50.000321+00:00 will be converted to 2015-01-01 00:00:00+00:00 how documentation outlines. And actually annotated value cannot be sometimes integer and sometimes datetime object.
Occasionally to denote that the values are "None" in such situations preferable way would be to set it to the minimal/maximum value (we assume that the value cannot be equal to it), for instance:
AccessLog.objects.filter(
attempt_time__gte=last_30_days
).annotate(
day=Coalesce(TruncDay('attempt_time'), datetime.min)
).values('day', 'username').annotate(
c=Count('username')
).order_by('day')
I'm building a booking form, and want to allow users to pick a date of booking from available dates in the next 60 days.
I get the next 60 days by:
base = datetime.date.today()
date_list = [base + datetime.timedelta(days=x) for x in range(60)]
Then I subtract already booked dates which are stored in the db:
bookings = list(Booking.objects.all())
primarykeys = []
unav = []
for b in bookings:
primarykeys.append(b.pk)
for p in primarykeys:
unav.append(Booking.objects.get(pk=p).booking_date)
for date in unav:
if date in date_list:
date_list.remove(date)
Then I change the result into tuple for the forms(not sure if this is right?):`
date_list = tuple(date_list)
Then I pass it into the form field as such:
booking_date = forms.ChoiceField(choices=date_list, required=True)
This gives me an error of cannot unpack non-iterable datetime.date object
And now am I stumped...how can I do this? I have a feeling i'm on the complete wrong path.
Thanks in advance
The docs for Django Form fields says the following:
choices
Either an iterable of 2-tuples to use as choices for this field, or a callable that returns such an iterable. This argument accepts the
same formats as the choices argument to a model field. See the model
field reference documentation on choices for more details. If the
argument is a callable, it is evaluated each time the field’s form is
initialized. Defaults to an empty list.
It looks like what you're passing is a tuple in this format:
(date object, date object, ...)
But you need to be passing something like a list of 2-tuples, with the first element of each tuple being the value stored for each choice, and the second element being the value displayed to the user in the form:
[(date_object, date_string), (date_object, date_string), ...)
Change your code to the following and see if that works for you:
base = datetime.date.today()
date_set = set([base + datetime.timedelta(days=x) for x in range(60)])
booking_dates = set(Booking.objects.all().values_list('booking_date', flat=True))
valid_dates = date_set - booking_dates
date_choices = sorted([(valid_date, valid_date.strftime('%Y-%m-%d')) for valid_date in valid_dates],
key=lambda x: x[0])
I've used sets to make it simpler to ensure unique values and subtract the two from each other without multiple for loops. You can use values_list with flat=True to get all the existing booking dates, then create a list of 2-tuples date_choices, with the actual datetime object as the value and display a string representation in whatever format you choose using strftime.
Then the dates are sorted using sorted by date ascending based on the first key, since using sets will mess up the sort order.
Then take a look at this question to see how you can pass these choices into the form from your view, as I don't think it's good to try to dynamically set the choices when defining the Form class itself.
Why is it that when trying to set the value of a field of a model object contained in a list, the value doesn't get set, but when I store the object at that index into a variable, and then try to change it, I am successful? Below is an example of what I mean.
In [64]: profile[0].screen_name = "clutch"
In [65]: profile[0].screen_name
In [66]: p = profile[0]
In [67]: p.screen_name = "clutch"
In [68]: p.screen_name
Out[68]: 'clutch'
My guess is that profile in your case is not a list but a QuerySet. So every time you index it, it will execute the query against your database to get the object.
Try this before your code:
profile = list(profile)
That way the query executes and the results are now in a list.