Ответы пользователя по тегу Django
  • Django - как посчитать количество часов, минут, секунд (TimeField)?

    aruseni
    @aruseni
    Если нужно универсальное решение для сравнения любых двух полей, содержащих время — тогда, вероятно, template tag будет вполне адекватным решением. Если же вам нужно сравнивать только два конкретных поля этой модели, вам будет намного проще добавить в модель соответствующие методы, и обращаться из шаблона к ним ({{ blablabla_obj.hours }}, {{ blablabla_obj.minutes }}, {{ blablabla_obj.seconds }}).

    Впрочем, ваш вопрос составлен неточно. Вам нужно именно узнавать разницу между этими двумя значениями? В виде HH:MM:SS?

    Update 1

    Автор указал, что минуты и секунды вообще не указываются, и при этом end_t всегда больше, чем start_t. Таким образом, достаточно сравнить start_t.hour и end_t.hour.

    Сделать это можно, добавив в модель соответствующий метод:

    class Blablabla(models.Model):
        start_t = models.TimeField(u"From", blank=True, null=True)
        end_t  = models.TimeField(u"To", blank=True, null=True)
    
        def period_duration(self):
            """
            Returns the length of the period between
            start_t and end_t, in hours.
    
            This is precise as long as both values
            have 0 as minute/second.
            """
            return self.end_t.hour - self.start_t.hour

    Далее, соответственно, если blablabla_obj — это объект модели Blablabla, то получить разницу между start_t и end_t можно с помощью blablabla_obj.period_duration() в коде или {{ blablabla_obj.period_duration }} в шаблоне.

    Тест:

    class BlablablaTestCase(TestCase):
        def setUp(self):
            start_t = datetime.time(14)
            end_t = datetime.time(18)
            self.blablabla_obj = Blablabla.objects.create(
                start_t=start_t,
                end_t=end_t
            )
    
        def test_period_calculation(self):
            """
            Tests that the period_duration method of the Blablabla
            model correctly compares start_t and end_t.
            """
            self.assertEqual(self.blablabla_obj.period_duration(), 4)
    
        def tearDown(self):
            self.blablabla_obj.delete()

    Update 2

    Если нужно считать и часы, и минуты, и секунды, то метод period_duration можно переписать вот так:

    def period_duration(self):
        """
        Returns the length of the period between
        start_t and end_t, in the following format:
    
        HH:MM:SS
        """
        total_seconds = (
            (
                self.end_t.hour*3600
                +
                self.end_t.minute*60
                +
                self.end_t.second
            ) - (
                self.start_t.hour*3600
                +
                self.start_t.minute*60
                +
                self.start_t.second
            )
        )
        hour, total_seconds = divmod(total_seconds, 3600)
        minute, total_seconds = divmod(total_seconds, 60)
        second = total_seconds
        return "%02d:%02d:%02d" % (hour, minute, second)
    Ответ написан
    6 комментариев
  • Как в django добавить в админку возможность изменения одного поля из другого класса?

    aruseni
    @aruseni
    Просто отобразить можно запросто:

    class OrdersAdmin(admin.ModelAdmin):
    
        fields = [
            'customer',
            'customer_address',
            'date',
            'amount_bottle',
            'price',
            'statusOrder'
        ]
        readonly_fields = ['customer_address',]
        list_filter = ['date']
        date_hierarchy = 'date'
    
        def customer_address(self, obj):
            return obj.customer.address
    
        customer_address.short_description = "Customer’s address"

    А вот с редактированием всё сложнее. Представьте себе, например, такую ситуацию — допустим, вы добавили в эту форму поле, которое сохраняется в поле address связанного объекта модели Customer. Но вот какое дело: пользователь в процессе редактирования поля поменял значение поля Customer, и поэтому объект Order связан уже с другим клиентом. Если всё равно сохранить адрес, то получится, что вы перезапишете значение уже для другого объекта, и это, возможно, будет неуместно. Если не сохранить — опять же, это может не быть ожидаемым поведением (может быть, пользователь хотел сохранить именно такой адрес для нового клиента).

    Тут я вижу такие варианты решения: или запрещать редактирование клиента, или прятать поле с адресом, если клиент изенён, или вообще динамически (с помощью JS) подгружать новый адрес при изменении клиента (и блокировать сохранение заказа, пока адрес не подгрузился).

    Если один из таких вариантов вам подходит, то вам нужно отредактировать используемую для страницы редактирования заказа форму, и дополнить обработку этой формы таким образом, чтобы значение поля с адресом сохранялось в поле address связанного объекта Customer.

    Удачи!

    P.S. Замечание по стилю: лучше не OrdersAdmin, а OrderAdmin (тем более, что Customer у вас напиано в единственном числе).
    Ответ написан
    Комментировать