Как отфильтровать набор запросов по времени в Django с пользовательским часовым поясом? - PullRequest
0 голосов
/ 30 апреля 2019

Я знаю, что вопрос кажется глупым, но по какой-то причине я не могу понять, почему мое приложение django не возвращает правильные результаты фильтрации, когда я изменяю TIME_ZONE = 'UTC' на 'TIME_ZONE =' Asia / Kolkata ''.Все остальное работает просто отлично, но когда я меняю часовой пояс на свой местный часовой пояс, он не выдает никакой ошибки, но функция в views.py также выдает 0 подходящих результатов.

Этот вопрос также связан с этот вопрос .

Это моя функция в 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)

Это моя функция в 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) 

А это модель:

# 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

Это база данных моих моделей:

1

То, что я пытался

Другой пользователь 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

1 Ответ

1 голос
/ 01 мая 2019

Проблема в том, что __date, __hour и __minute используют текущий часовой пояс (независимо от того, что вы определили как settings.TIME_ZONE).Принимая во внимание, что объект python datetime, извлеченный из базы данных с latest, всегда находится в UTC.

При обращении к часовому поясу следует помнить: все объекты datetime, переданные Django, находятся в UTC.Часовой пояс обычно используется только при отображении этих дат в шаблонах (визуализация для пользователя) или при получении входных значений из форм (ввод от пользователя).

Исключением являются Trunc и Extractфункции базы данных, для которых __date, __hour и __minute являются ярлыками.Они используют settings.TIME_ZONE, если вы явно не установите tzinfo на None или UTC.

Таким образом, вы должны находиться в одном и том же контексте часового пояса для обоих запросов.Проще всего сделать все это на уровне базы данных:

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]))

Примечание. Убедитесь, что в вашем наборе запросов нет строк с полем NULL (в вашем случае это невозможно, так как time не может быть NULL), что вызовет исключение при вызове Trunc для него.

...