Как получить вторую последнюю запись в Django / Python с метками времени? - PullRequest
0 голосов
/ 06 ноября 2019

У меня есть форма из модели, которая отслеживает время входа / выхода. Я пытаюсь добавить ограничения, чтобы сделать данные более точными. В настоящее время, когда кто-то «входит», он создает запись, сохраняет время в DateTimeField «time_in», а затем перенаправляет. Если человек затем пытается войти снова, он создает новую запись с новой отметкой времени.

Что я пытаюсь добавить сейчас, так это то, что если у человека есть предыдущая запись без отметки времени выхода (time_out), то эта запись (которая будет второй последней записью) будет помечена. изменяя поле time_exceptions на «N».

В настоящее время все поля заменяются на «N», независимо от того, есть ли выход или нет, как показано ниже.

ПРИМЕЧАНИЕ Я уменьшил количество кода в form_valid, следовательно, часть области выхода не существует. Это была просто большая фильтрация, основанная на других полях, и она не выглядела слишком уместной.

views.py

class EnterExitArea(CreateView):
    model = EmployeeWorkAreaLog
    template_name = "operations/enter_exit_area.html"
    form_class = WarehouseForm

    def form_valid(self, form):
        emp_num = form.cleaned_data['employee_number']
        area = form.cleaned_data['work_area']
        station = form.cleaned_data['station_number']

        if 'enter_area' in self.request.POST:
            form.save()
            EmployeeWorkAreaLog.objects.filter((Q(employee_number=emp_num) & Q(work_area=area) & Q(time_out__isnull=True) & Q(time_in__isnull=True)) & (Q(station_number=station) | Q(station_number__isnull=True))).update(time_in=datetime.now())

            if EmployeeWorkAreaLog.objects.filter(Q(employee_number=emp_num)).count() > 1:
                EmployeeWorkAreaLog.objects.filter((Q(employee_number=emp_num) & Q(work_area=area) & Q(time_out__isnull=True)) & (Q(station_number=station) | Q(station_number__isnull=True))).update(time_exceptions='N')

            return HttpResponseRedirect(self.request.path_info)

Я попробовал следующее, ноЯ получаю expected string or bytes-like object и, хотя он все еще создает новую запись перед сбоем, он не обновляет time_exceptions секунды до самой последней до N.

        if 'enter_area' in self.request.POST:
            form.save()
            EmployeeWorkAreaLog.objects.filter((Q(employee_number=emp_num) & Q(work_area=area) & Q(time_out__isnull=True) & Q(time_in__isnull=True)) & (Q(station_number=station) | Q(station_number__isnull=True))).update(time_in=datetime.now())

            if EmployeeWorkAreaLog.objects.filter(Q(employee_number=emp_num) & Q(time_out__isnull=True) & Q(time_exceptions="")).count() > 1:
                recent = EmployeeWorkAreaLog.objects.filter(employee_number=emp_num, work_area=area, station_number=station, time_out__isnull=True).order_by('-time_in')[1]

                EmployeeWorkAreaLog.objects.filter((Q(employee_number=emp_num) & Q(work_area=area) & Q(time_in=recent) & Q(time_out__isnull=True)) & (Q(station_number=station) | Q(station_number__isnull=True))).update(time_exceptions='N')

            return HttpResponseRedirect(self.request.path_info)

models.py

class EmployeeWorkAreaLog(TimeStampedModel, SoftDeleteModel, models.Model):
    employee_number = models.ForeignKey(Salesman, on_delete=models.SET_NULL, help_text="Employee #", null=True, blank=False)
    work_area = models.ForeignKey(WorkArea, on_delete=models.SET_NULL, null=True, blank=False, help_text="Work Area", related_name="work_area")
    station_number = models.ForeignKey(StationNumber, on_delete=models.SET_NULL, 
    time_exceptions = models.CharField(max_length=2, blank=True)
    time_in = models.DateTimeField(help_text="Time in", null=True, blank=True)
    time_out = models.DateTimeField(blank=True, help_text="Time out", null=True)

    def __str__(self):
        return self.employee_number

traceback:

Internal Server Error: /operations/enter-exit-area/
Traceback (most recent call last):
  File "C:\Users\mkusneco\appsve\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
    response = get_response(request)
  File "C:\Users\mkusneco\appsve\lib\site-packages\django\core\handlers\base.py", line 126, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "C:\Users\mkusneco\appsve\lib\site-packages\django\core\handlers\base.py", line 124, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\mkusneco\appsve\lib\site-packages\django\views\generic\base.py", line 68, in view
    return self.dispatch(request, *args, **kwargs)
  File "C:\Users\mkusneco\appsve\lib\site-packages\django\views\generic\base.py", line 88, in dispatch
    return handler(request, *args, **kwargs)
  File "C:\Users\mkusneco\appsve\lib\site-packages\django\views\generic\edit.py", line 172, in post
    return super().post(request, *args, **kwargs)
  File "C:\Users\mkusneco\appsve\lib\site-packages\django\views\generic\edit.py", line 142, in post
    return self.form_valid(form)
  File "C:\Users\mkusneco\apps.rsrgroup.com\apps\operations\views.py", line 45, in form_valid
    Q(station_number=station) | Q(station_number__isnull=True))).update(time_exceptions='N')
  File "C:\Users\mkusneco\appsve\lib\site-packages\django\db\models\manager.py", line 82, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "C:\Users\mkusneco\appsve\lib\site-packages\django\db\models\query.py", line 844, in filter
    return self._filter_or_exclude(False, *args, **kwargs)
  File "C:\Users\mkusneco\appsve\lib\site-packages\django\db\models\query.py", line 862, in _filter_or_exclude
    clone.query.add_q(Q(*args, **kwargs))
  File "C:\Users\mkusneco\appsve\lib\site-packages\django\db\models\sql\query.py", line 1263, in add_q
    clause, _ = self._add_q(q_object, self.used_aliases)
  File "C:\Users\mkusneco\appsve\lib\site-packages\django\db\models\sql\query.py", line 1281, in _add_q
    current_negated, allow_joins, split_subq)
  File "C:\Users\mkusneco\appsve\lib\site-packages\django\db\models\sql\query.py", line 1287, in _add_q
    split_subq=split_subq,
  File "C:\Users\mkusneco\appsve\lib\site-packages\django\db\models\sql\query.py", line 1225, in build_filter
    condition = self.build_lookup(lookups, col, value)
  File "C:\Users\mkusneco\appsve\lib\site-packages\django\db\models\sql\query.py", line 1096, in build_lookup
    lookup = lookup_class(lhs, rhs)
  File "C:\Users\mkusneco\appsve\lib\site-packages\django\db\models\lookups.py", line 20, in __init__
    self.rhs = self.get_prep_lookup()
  File "C:\Users\mkusneco\appsve\lib\site-packages\django\db\models\lookups.py", line 70, in get_prep_lookup
    return self.lhs.output_field.get_prep_value(self.rhs)
  File "C:\Users\mkusneco\appsve\lib\site-packages\django\db\models\fields\__init__.py", line 1408, in get_prep_value
    value = super().get_prep_value(value)
  File "C:\Users\mkusneco\appsve\lib\site-packages\django\db\models\fields\__init__.py", line 1268, in get_prep_value
    return self.to_python(value)
  File "C:\Users\mkusneco\appsve\lib\site-packages\django\db\models\fields\__init__.py", line 1369, in to_python
    parsed = parse_datetime(value)
  File "C:\Users\mkusneco\appsve\lib\site-packages\django\utils\dateparse.py", line 106, in parse_datetime
    match = datetime_re.match(value)
TypeError: expected string or bytes-like object

1 Ответ

1 голос
/ 06 ноября 2019

Вы присваиваете EmployeeWorkAreaLog экземпляр recent, однако вы используете его в условии как Q(time_in=recent), что явно неверно, поскольку условие должно содержать простое значение / datetime / string, а не объект.

Таким образом, вы могли бы исправить это с помощью Q(time_in=recent.time_in), но это не очень надежно, если у пользователя были какие-то дубликаты записей. Было бы лучше использовать экземпляр pk, поэтому вместо условия time_in вы бы использовали Q(pk=recent.pk). Но это все еще не лучшее решение - что, если существует более одной такой записи? Зачем обновлять только второе, а не третье и т. Д.?

Поэтому я думаю, что вместо выбора второй записи (с использованием [1]) следует выбрать first one и исключитьэто из обновленного набора запросов, например:

first = EmployeeWorkAreaLog.objects.filter(employee_number=emp_num, work_area=area, station_number=station, time_out__isnull=True).order_by('-time_in').first()
EmployeeWorkAreaLog.objects.filter((Q(employee_number=emp_num) & Q(work_area=area) & Q(time_out__isnull=True)) & (Q(station_number=station) | Q(station_number__isnull=True))).exclude(pk=first.pk).update(time_exceptions='N')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...