I want to implement a database search and I need to filter queryset by date that contains search request. The problem is that users will see formatted date (like dd.mm.yyyy) and will expect search to see it the same way, but default __contains consider date in yyyy-mm-dd format. How can I apply filter to DateField before using __contains? I need a way using django orm because otherwise it will be too long (not using sql).
I tried to set DATE_FORMAT = 'd.m.Y' to satisfying format but it has no effect (even setting USE_L10N = False)
Also thought about creating custom lookup but not sure how to implement it
I need to apply __contains to all model fields, so I can't just reformat search value
You can Annotate the date attribute to a CharField and execute your filter on Annotated attribute.
from django.db.models import Func, F, Value, CharField
queryset.annotate(string_date=Func(
F('YOUR_DATE_FIELD'),
Value('YOUR OUTPUT FORMAT'),
output_field=CharField(),
function='to_char')
).filter(string_date__contains=INPUT_DATE)
Related
I have a Django project, and I want to save created_at datetime in the database. I generate datetime.now with jdatetime (or Khayyam) python package and try to save this in DateTimeField. But sometimes it raises error because the Gregorian(miladi) date of the entry does not exist. what can I do about this?
In my idea, you can save two model fields.
One is DateTimeField contains gregorian datetime, and
another one, CharField contains converted Jalali to a String value and save it.
The DateTimeField for functionality, e.g., filter between to datetime.
The StringField for representing in response(without overload).
I need to filter another datetime field through a datetime field, but I just need to compare date. How to implement it by F expression?
F expression does not seem to format fields
My model is:
class Test():
date1 = models.DateTimeField()
date2 = models.DateTimeField()
I just need to compare date, not time.
Test.objects.filter(Q(date2__gt=F('date1')))
It keeps comparing datetime. That's not what I want. I just want to compare date. As a Django rookie, I can't find a solution.
I used time zone and Mysql, and I don't want to modify them.
You can use the __date field lookup for this.
In your case:
Test.objects.filter(Q(date2__date__gt=F('date1__date')))
Can give you the desired result.
The __date field lookup helps to extract only the date from the datetime field.
But make sure that you are using Django>1.9, for older versions of Django, you need to use other methods
I'm trying to specify a default date in a Django model, for example:
from datetime import date
class A(models.Model):
date = models.DateField(default=date.today())
This works and I can see the default date in a ModelForm, but when I change the form input_format to %d-%m-%Y, the default date never appears in the field.
I've also tried:
from datetime import date
class A(models.Model):
date = models.DateField(default=date.today().strftime('%d-%m-%Y'))
This doesn't work either. Can anyone help me?
There are two problems here:
the DateField(default=today.today()) will not work, since then the function will be evaluated eagerly, and then the default value is thus the result of that function call. As a result the default value is not calculated when constructing a new object, and hence eventually will be different; and
the representation of a DateField. Now the model layer does not specify a representation, it only specifies how to store values in the database, and defines functions on a model.
We can solve the first problem by passing a reference to the today function, like:
from datetime import date
class A(models.Model):
date = models.DateField(default=date.today) # no ()
As for the representation, you should specify the format in the template, for example with the date template filter [Django-doc], like:
<!-- template.html -->
{{ some_a.date|date:'d-m-Y' }}
Or in a form with:
# app/forms.py
class AForm(ModelForm):
date = DateField(input_formats=['%d-%m-%Y'])
class Meta:
model = A
You can use the DATE_INPUT_FORMATS setting in your Django project settings, this will allow you to make date.today().strftime('%d-%m-%Y') be accepted by your model field; however, the DateField is stored in your database as the native column of the same type and not as a string with a specific format. There is a difference between storing the data and representing it in your forms, templates or DRF serializers. I really recommend keeping the default format for the database and present the data in the format you want by using the DATE_FORMAT setting to d-m-Y that will take care of presenting your dates in that format as long as the USE_L10N setting is False.
if you want to use the same format for display and input, you have to specify input_formats and format(in widget) respectively. for example
class OrderForm(forms.ModelForm):
deadline = forms.DateTimeField(
input_formats=['%d/%m/%Y %I:%M %p', ], # input format
widget=forms.DateTimeInput(format="%d/%m/%Y %I:%M %p"), # initial display format
)
I am trying to iterate over a model's attributes, getting both the verbose name and value for each attribute. I have no problem for character/numerical values, but I am struggling with DateTime values. Of course I can do this manually, but some of my models have dozens of attributes (only a few of which are DateTimes), so it would be nice if I could figure out how to do this programatically.
My code currently (with the 'History' Model class):
def get_fields(self):
return [(field.verbose_name, field.value_to_string(self)) for field in History._meta.fields]
In the case of a DateTime, of course this outputs a string, such as: 2011-06-16T04:00:00+00:00
Suggestions on pulling out DateTime values? Apologies if this is a very basic question -- I have been using Django for about a year, but am more recently trying to tackle area's I am unfamiliar with. Thank you!
You can use strftime() on datetime objects to specify how the string representation should be formatted, but you probably have to override the value_to_string() method in the datetimefield if you want to iterate over all fields in a uniform way.
See python doc of datetime.strftime() here:
https://docs.python.org/2/library/datetime.html
I have a model that contains datefield. I'm trying to get query set of that model that contains current week (starts on Monday).
So since Django datefield contains simple datetime.date model I assumed to filter by using .isocalendar(). Logically it's exactly what I want without no extra comparisons and calculations by current week day.
So what I want to do essentially is force .filter statement to behave in this logic:
if model.date.isocalendar()[2] == datetime.date.today().isocalendar()[2]
...
Yet how to write it inside filter statement?
.filter(model__date__isocalendar=datetime.date.today().isocalendar()) will give wrong results (same as comparing to today not this week).
As digging true http://docs.python.org/library/datetime.html I have not noticed any other week day options...
Note from documentation:
date.isocalendar() Return a 3-tuple, (ISO year, ISO week number, ISO
weekday).
Update:
Although I disliked the solution of using ranges yet it's the best option.
However in my case I made a variable that marks the beginning of the week and just look greater or equal value because if I'm looking for a matches for current week. In case of giving the number of the week It would require both ends.
today = datetime.date.today()
monday = today - datetime.timedelta(days=today.weekday())
... \
.filter(date__gte=monday)
You're not going to be able to do this. Remember it's not just an issue of what Python supports, Django has to communicate the filter to the database, and the database doesn't support such complex date calculations. You can use __range, though, with a start date and end date.
Even simpler than using Extract function that Amit mentioned in his answer is using __week field lookup added in Django 1.11, so you can simply do:
.filter(model__date__week=datetime.date.today().isocalendar()[1])
ExtractWeek has been introduced in Django 1.11 for filtering based on isoweek number.
For Django 1.10 and lower versions, following solution works for filtering by iso number week on postgres database:
from django.db.models.functions import Extract
from django.db import models
#models.DateTimeField.register_lookup
class ExtractWeek(Extract):
lookup_name = 'week'
Now do query as follows
queryset.annotate(week=ExtractWeek('date'))\
.filter(week=week_number)
(This answer should only work for postgres, but might work for other databases.)
A quick and elegant solution for this problem would be to define these two custom transformers:
from django.db import models
from django.db.models.lookups import DateTransform
#models.DateTimeField.register_lookup
class WeekTransform(DateTransform):
lookup_name = 'week'
#models.DateTimeField.register_lookup
class ISOYearTransform(DateTransform):
lookup_name = 'isoyear'
Now you can query by week like this:
from django.utils.timezone import now
year, week, _ = now().isocalendar()
MyModel.objects.filter(created__isoyear=year, created__week=week)
Behinds the scenes, the Django DateTransform object uses the postgres EXTRACT function, which supports week and isoyear.