I am trying to get a distinct list of items. The db has a created field which is datetime and I need it as a date for my query. So I added an annotation. The problem is that distinct won't work on the annotation...
distinct_failed_recharges = recharges.filter(
status=FAILED
).annotate(
created_date=TruncDate('created')
).distinct(
'created_date', 'sim', 'product_type', 'failure_reason'
).values_list('id', flat=True)
This is the error that I get:
django.core.exceptions.FieldError: Cannot resolve keyword 'created_date' into field
I get the same error in django 1.11 doing:
qs = queryset.annotate(day=TruncDay('date')).distinct('day')
ids = list(qs.values_list('id', flat=True))
results with this error:
FieldError: Cannot resolve keyword 'day' into field.
This is very weird since I try to evaluate 'id'...
The only workaround that I've found is:
qs = queryset.annotate(day=TruncDay('date')).distinct('day')
objects_list = list(qs)
ids = [object.id for object in objects_list]
This is very inefficient, but hopefully my list is not too long...
Related
I'm performing a query in a function inside the views.py as follows:
input_dict = {'id': 'id',
'table': 'my_table',
'first_col': 'my_first_col',
'first_name': 'my_first_name'}
query = '''
SELECT %(id)s
FROM %(table)s
WHERE %(first_col)s = %(first_name)s '''
qs = my_model.objects.raw(query, input_dict)
print(qs)
which prints:
qs: <RawQuerySet:
SELECT id
FROM my_table
WHERE my_first_col = my_first_name >
However, when I try to run this line:
ids = [item.id for item in qs]
it gives me an error:
psycopg2.errors.SyntaxError: syntax error at or near "'my_table'"
LINE 3: FROM 'my_table'
and also:
django.db.utils.ProgrammingError: syntax error at or near "'my_table'"
LINE 3: FROM 'my_table'
What should I do?
django are not able to excecut your query.
I believe what you trying to acheive via the raw function it is not possible.
read the docs https://docs.djangoproject.com/en/3.0/topics/db/sql/ for better understanding how the function work
your dynamic options are realted either to the table fields and the where params:
the select fields
you can map fields in the query to model fields using the translations
argument to raw()
like :
name_map = {'first': 'first_name', 'last': 'last_name', 'bd': 'birth_date', 'pk': 'id'}
Person.objects.raw('SELECT * FROM some_other_table', translations=name_map)
the where params
If you need to perform parameterized queries, you can use the params
argument to raw()
lname = 'Doe'
Person.objects.raw('SELECT * FROM myapp_person WHERE last_name = %s', [lname])
at the end of the day, this will work, although it's not recomended unless you know exactly what you are doing as it might expose your system to sql attacks
query = '''
SELECT %(id)s
FROM %(table)s
WHERE %(first_col)s = %(first_name)s '''
query = query%input_dict
qs = my_model.objects.raw(query)
I'm trying to return a list of items in between 2 different dates, a date in the past and the current time using a queryset.
The error I'm getting is TypeError: an integer is required (got type str)
views.py
import datetime
import pytz
first_date = "2020-01-01 19:17:35.909424"
last_date = timezone.now()
I don't want anything returned that has a date in the future
Here is the filter in the query
.filter(hide_sentance_until=(date(first_date), date(last_date)))
This is the full queryset, but it's the above filter causing he issue
zip_flash_sentances = (
model.objects
.filter(show_sentance=True)
.filter(
hide_sentance_until=(date(first_date), date(last_date))
)
.order_by("?")
.filter(username_id = user_id_fk)
.values_list('sentance_eng', 'sentance_esp', 'id')
.first()
)
I thought it might be a comparison problem with dates but here is my model field
models.py
hide_sentance_until = models.DateTimeField(default=datetime.now(), blank=True)
Thanks
You can use gte and lte query attributes:
first_datetime = datetime.datetime.strptime(first_date, '%Y-%m-%d %H:%M:%S.%f')
last_date = timezone.now()
.filter(hide_sentance_until__lte=last_date,hide_sentance_until__gte=first_time)
One thing is that you're specifying a specific value that's determined when your code is compiled to be your default value. To have the actual current date be the value you want:
hide_sentance_until = models.DateTimeField(default=datetime.now, blank=True)
Then you need to parse the datetime out of the string.
date_value = datetime.strptime(first_date, DATETIME_FORMAT_YOU_USE)
Where DATETIME_FORMAT_YOU_USE is the series of format codes from Python that you're using.
Finally you should use the __range queryset field lookup.
.filter(
hide_sentance_until__range=(date_value, timezone.now())
)
I am using django admin (1.11.x) and I defined a calculated field (_due_date_in_days) to display it as a column. I wanted to be able to sort of this column like regular fields.
I have a model class "Registration" that contains a date field "due_date" and a calculated field "_due_date_in_days"
def _due_date_in_days(self):
return (now().date() - self.due_date).days
On the manager of class "RegistrationManager", I added an annotation
def get_queryset(self):
qs = super(RegistrationManager, self).get_queryset().filter()
return qs.annotate(_due_date_in_days=now() - F('due_date'))
In RegistrationAdmin I added format_due_date_in_days in the order list
def format_due_date_in_days(self, obj):
return (now().date() - self.due_date).days
format_due_date_in_days.admin_order_field = '_due_date_in_days'
The sort on the calculated field is working well until I am using an action (https://docs.djangoproject.com/fr/1.11/ref/contrib/admin/actions/) define on the ExampleAdmin class :
def mark_as_printed(self, request, queryset):
rows_updated = queryset.update(is_printed=True)
When I am sorting on the calculated field AND I am using this action than error occured :
django.core.exceptions.FieldError: Cannot resolve keyword '_due_date_in_days' into field. Choices are: ...
Actually I my case there is a simple solution :
remove the annotate
define order_field on "-due_date"
The behavior will be the one expected
format_due_date_in_days.admin_order_field = '-due_date'
I have two models:
class Property(models.Model):
# code here...
class AccommodationType(models.Model):
property = models.ForeignKey(Property, related_name='accommodation_types')
# rest of code here...
What I'm trying to to is to annotate Property's queryset with count of related AccommodationType's and filter it by the value of this count. So here is my code:
qs = Property.objects.all()
qs.annotate(acc_types_count=Count('accommodation_types'))
filtered = qs.filter(acc_types_count=1)
and here I got the error:
django.core.exceptions.FieldError: Cannot resolve keyword 'acc_types_count' into field. Choices are: # ...rest of the fields
Where I am wrong?
annotate, like filter, doesn't mutate the queryset but returns a new one. You need to reassign that to qs:
qs.annotate(acc_types_count=Count('accommodation_types'))
Or combine it with the original query:
qs = Property.objects.all().annotate(acc_types_count=Count('accommodation_types'))
I want to include a month number in a queryset where the date is in a related model. This is what I tried:
OrderItem.objects.all().annotate(order_month=Sum('order__payment_date__month'))[0].__dict__
Join on field 'payment_date' not permitted. Did you misspell 'month' for the lookup type?
and then I tried
OrderItem.objects.all().extra(select={'order_month': "order__payment_date__month"})
(1054, "Unknown column 'order__payment_date__month' in 'field list'")
OrderItem.objects.all().extra(select={'order_month': "order.payment_date"}).select_related('Order')
(1054, "Unknown column 'order.payment_date' in 'field list'")
But this works so no problem with order.payment_date
OrderItem.objects.all().values('id','order__payment_date').select_related('Order')
I need it in the querset result as I'm using the queryset in Geraldo. Anyone know how I can get this?
THE ANSWER was that in the extra section you need to specify what you want so the MySQL understands it. In my case adding the app in front of the model name. In this case web_order.payment_date. This worked:
OrderItem.objects.all().extra(select={'order_month': "MONTH(web_order.payment_date)"}).select_related('order')[0].__dict__
{'product_id': None, 'order_id': 1L, 'price': Decimal("1.00"), 'order_month': 7L, 'id': 1L}
In Django 1.10+, you can use the ExtractMonth function.
from django.db.models.functions import ExtractMonth
OrderItem.objects.all().annotate(order_month=ExtractMonth('order__payment_date'))
You'll need to drop down into SQL to get this done, which sadly means the solution won't be database agnostic.
This works in Postgres:
# Grab the base queryset
items = Item.objects.all()
# Annotate
extra_query = "EXTRACT(MONTH FROM relatedtable.mydatefield)"
items = items.extra(select={'mydatefield_month': extra_query}
# We have to use a select_related so that 'relatedtable' is
# available in the SQL statement.
items = items.select_related('relatedmodel')
print items[0].mydatefield_month
For MySQL you might try:
extra_query = "MONTH(relatedtable.mydatefield)"