Prasanna
Prasanna

Reputation: 4636

filtering DateField on the basis of substring in django

So I am using a DateField for displaying the date. Which when passed to a template using contexts, renders in the format Nov. 4, 2018

Now there are multiple entries of such dates in the database. And I want to filter on the basis of string of the date actually shown. i.e when I type in Nov 4, or nov 4 or NOV 4 in my search input field, it should show the matched result. More like a substring match.

Now the only problem is that i do not know how to convert my_model.date field in to Nov. 4, 2018.

str(my_model.date) returns 2016-11-04 and I do not want to parse this with month_number-to-month_name map

I think, any of the two solutions should work.

1) Django filters that allow me to do so.

2) converting my_model.date into Nov. 4, 2018 string

Help please, been stuck on this forever now

Upvotes: 1

Views: 280

Answers (1)

souldeux
souldeux

Reputation: 3755

Because you specifically mention rendering the date in a template, I'm not sure if the search operation you're referring to is a front-end, user-facing thing or a backend database query.

If you want to convert my_model.date to a prettier string before sending it to the template before display, you can process it in your view with strptime - this will give you the control that you're missing with the str wrapper: https://docs.python.org/3/library/datetime.html#strftime-strptime-behavior While there are template tags that can do this for you as well, doing it in your view is faster and better.

If this is a DB query, then remember that you can filter date objects by their attributes. For example, to get all instances created on November 11th, 2011:

MyModel.objects.filter(
    date__day = 11, 
    date__month = 11,
    date__year = 2018
)

Note the double underscores.


Responding to your comment, now that I better understand your goal:

Date fields do not store their more "verbose" date information in a queryable spot. If you want to be able to query for things like "Nov" instead of 11 then you'll need to add another attribute (or attributes) to your model to propagate that computed data into queryable containers.

If it were me, I would do this within my_model:

from datetime import date

...

rawDate = models.DateField(...) #your current date field
formatted_month = models.CharField(...)
formatted_day = models.IntegerField(...)
formatted_year = models.IntegerField(...)

...

def save(self):
    self.formatted_month = date.strftime(self.rawDate, '%b')
    self.formatted_day = date.strftime(self.rawDate, '%d')
    self.formatted_year = date.strftime(self.rawDate, '%Y')
    super().save()

Now you can perform your NOV/nov/Nov lookup like so:

MyModel.objects.filter(
    formatted_month__iexact = 'Nov'
)

This still requires you to split the month and day in your search term before hitting the database. If you wanted to squash these down a bit, you could instead store all of the formatted date info in a single field:

formatted_date = models.CharField(...)
...
def save(self):
    self.formatted_date = date.strftime(self.rawDate, '%b %d %Y')

Then if your query looks like "NOV 4", you could do:

MyModel.objects.filter(formatted_date__icontains='NOV 4')

Upvotes: 1

Related Questions