[英]How to filter queryset against time in django with custom timezone?
I know the question seems stupid, but for some reason I am not able to understand why my django app does not return the correct filtering results when I change my TIME_ZONE = 'UTC'
to 'TIME_ZONE = 'Asia/Kolkata''. 我知道这个问题看起来很愚蠢,但是由于某种原因,当我将
TIME_ZONE = 'UTC'
更改为'TIME_ZONE ='Asia / Kolkata'时,为什么我的django应用程序无法返回正确的过滤结果。 Everything else is working just fine, but when I change the timezone to my local timezone, it does not give any error, but the function in views.py also gives 0 matching results. 其他所有工作都很好,但是当我将时区更改为本地时区时,它没有给出任何错误,但是views.py中的函数也给出了0个匹配结果。
This question is also related to this question . 这个问题也与此问题有关 。
This is my function in views.py importing the data in the Itembatch model: 这是我在views.py中导入Itembatch模型中的数据的功能:
@login_required
def upload_batch(request):
template_name = 'classroom/teachers/upload.html'
prompt = {'order':'Order of csv should be first_name, last_name, email, ip_address, message'}
if request.method == "GET":
return render(request,template_name,prompt)
csv_file = request.FILES['file']
data_set = csv_file.read().decode('UTF-8')
io_string = io.StringIO(data_set)
next(io_string)
uploaded_by = request.user
for column in csv.reader(io_string,delimiter=',',quotechar='|'):
_, created = ItemBatch.objects.update_or_create(
name = column[0],
pid = column[1],
quantity = column[2],
length = column[3],
width = column[4],
height = column[5],
volume = column[6],
weight = column[7],
truck_type = column[8],
origin = column[9],
destination = column[10],
uploaded_by = uploaded_by
)
context = {}
return render(request,template_name,context)
This is my function in views.py to render the objects : 这是我在views.py中渲染对象的功能:
@method_decorator([login_required, teacher_required], name='dispatch')
class UploadedItems(ListView):
model = ItemBatch
ordering = ('name',)
context_object_name = 'quizzes'
template_name = 'classroom/teachers/item_list.html'
def get_queryset (self):
latest_item = ItemBatch.objects.latest('time')
return ItemBatch.objects.filter(time__date=latest_item.time.date(),
time__hour=latest_item.time.hour, time__minute=latest_item.time.minute)
And this is the model: 这是模型:
# item upload
class ItemBatch(models.Model):
# uploaded_by = models.ForeignKey(Teacher, on_delete=models.CASCADE, related_name='uploaded_by')
ttypes =(('Open','Open'),('Container','Container'),('Trailer','Trailer'),('All','All'))
uploaded_by = models.ForeignKey(User, on_delete=models.CASCADE, related_name='uploaded_by')
name = models.CharField(max_length=30)
pid = models.CharField(max_length=30)
quantity = models.CharField(max_length=30)
length = models.CharField(max_length=100, blank=True)
width = models.CharField(max_length=100, blank=True)
height = models.CharField(max_length=100, blank=True)
volume = models.CharField(max_length=100, blank=True)
weight = models.CharField(max_length=100, blank=True)
truck_type = models.CharField(max_length=255,default=0, choices=ttypes)
origin = models.CharField(max_length=100, blank=True)
destination = models.CharField(max_length=100, blank=True)
time = models.DateTimeField(max_length=100, blank=True,default=now)
def __str__ (self):
return self.name
This is my models database: 这是我的模型数据库:
A fellow SO user suggested I should try something like this, but it did not work either. 一位SO用户建议我应该尝试类似的方法,但是它也不起作用。
latest_item = ItemBatch.objects.latest('time')
from django.conf import settings
settings.USE_TZ = False
latest_items = ItemBatch.objects.filter(time__date=latest_item.time.date(), time__hour=latest_item.time.hour, time__minute=latest_item.time.minute)
settings.USE_TZ = True
The problem is that __date
, __hour
and __minute
are using the current timezone (whatever you defined as settings.TIME_ZONE
). 问题是
__date
, __hour
和__minute
使用的是当前时区(无论您定义为settings.TIME_ZONE
)。 Whereas the python datetime
object retrieved from the database with latest
is always in UTC. 而从数据库中获取的
latest
的python datetime
对象始终是UTC。
The thing to remember when being timezone aware is: All datetime
objects passed around by Django are in UTC. 时区感知时要记住的事情是:Django传递的所有
datetime
对象都位于UTC中。 The timezone is in general only used when displaying these datetimes in templates (rendering to the user) or receiving input values from forms (input from the user). 通常仅在在模板中显示这些日期时间(呈现给用户)或从表单接收输入值(来自用户的输入)时才使用时区。
The exception here are the Trunc
and Extract
database functions, for which __date
, __hour
and __minute
are shortcuts. Trunc
和Extract
数据库函数是这里的例外, __date
, __hour
和__minute
是其快捷方式。 They use the settings.TIME_ZONE
unless you explicitly set tzinfo
to None
or UTC
. 他们使用
settings.TIME_ZONE
除非您将tzinfo
显式设置为None
或UTC
。
So you need to be in the same timezone context for both queries. 因此,两个查询都需要处于相同的时区上下文中。 The easiest is to do the whole thing at the database level:
最简单的方法是在数据库级别完成整个操作:
from django.db.models.functions import Trunc
from django.db.models import DateTimeField, Subquery
latest = ItemBatch.objects.order_by('-time').annotate(truncated_time=Trunc(
'time', 'minute', output_field=DateTimeField())
qs = ItemBatch.objects.annotate(truncated_time=Trunc(
'time', 'minute', output_field=DateTimeField()))\
.filter(truncated_time=Subquery(latest.values('truncated_time')[:1]))
Note: Make sure your queryset doesn't include any rows where the field is NULL
(not possible in your case, since time
cannot be NULL
), that will raise an exception when calling Trunc
on it. 注意:确保您的查询集不包含字段为
NULL
任何行(在您的情况下,这是不可能的,因为time
不能为NULL
),这将在对其调用Trunc
时引发异常。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.