Marco Mei
Marco Mei

Reputation: 137

failed to query database with filter in django 2.0

I'm developing a blog app with django2.0.

in the models layer, I defined a class Post, and defined a attribute created_time with DateTimeField, then I tried to query the posts based on the created_time with two arguments year and month, but finally it turns out there is no object got from the query.

What seems to be the problem?

1.blog/models.py

class Post(models.Model):
    ...
    created_time = models.DateTimeField()
    ...

2.blog/views.py

def archives(request, year, month):
    post_list = Post.objects.filter(created_time__year=year,
                                    created_time__month=month).
                                     order_by('-created_time')
    print('Year:{0}.\nMonth:{1}'.format(year,month))

    count = 0
    for a in post_list:
        count += 1
    print("I've found {} post here!".format(str(count)))

    return render(request, 
                  'blog/index.html', 
                   context={'post_list': post_list})

3.blog/urls.py

urlpatterns = [
...
url(r'^archives/(?P<year>[0-9]{4})/(?P<month>[0-9]{1,2})/$',views.archives,name='archives'),

]

  1. templates/blog.index.html

<li><a href="{% url 'blog:archives' date.year date.month %}">{{date.year}}年{{date.month}}月</a></li>

In the database I've added lots of post, but finally the console output is like: enter image description here

**Why******?

Note that, if I remove one argument created_time__month=month in view archives() as below, it can get the correct query results.

def archives(request, year, month):
    post_list = Post.objects.filter(created_time__year=year).order_by('-created_time')

enter image description here

And below is the database info:

enter image description here

Upvotes: 0

Views: 223

Answers (1)

Antwane
Antwane

Reputation: 22678

First, you may convert year and month url argument to int, to ensure the filtering is done correctly. By default, you receive these values as str.

def archives(request, year, month):
    year, month = int(year), int(month)
    post_list = Post.objects.filter(created_time__year=year,
                                    created_time__month=month).
                                     order_by('-created_time')
    # [...]

Then, don't use a loop to count number of results of a queryset. Use count():

print("I've found {} post here!".format(post_list.count()))

In addition, if you need to understand why this particular queryset returns nothing when this other returns some results, you could check the underlying SQL query generated by Django. This should help to determine where the problem comes from:

print(post_list.query)

In addition, as stated in the documentation, Django may convert your date values into current timezone (depending on settings.USE_TZ) before executing the SQL request. That could explain this kind of error sometimes.

Upvotes: 1

Related Questions