Django - Метод пользовательской модели - Как указать тип данных, чтобы Admin правильно его форматировал? - PullRequest
1 голос
/ 11 апреля 2011

Пример:

class MyModel(models.Model):
    field1=models.CharField(..)
    field2=models.DateTimeField()
    def today(self):
        return self.field2

Когда я смотрю на это на сайте администратора, поле field2 форматируется иначе, чем поле сегодня.это лечит field2?То есть, скажите админу Django, что «сегодня» - это модель.

Ответы [ 4 ]

2 голосов
/ 11 апреля 2011

Для получения DateTime объекта необходимо вызвать datetime.datetime.now() вместо datetime.datetime.today()

EDIT:

Или используйте models.DateField() для field2 вместо models.DateTimeField(): -)

EDIT2:

Вот решение:

def today(self):
    from django.utils import formats
    return formats.localize(self.field2)
1 голос
/ 12 апреля 2011

Если вы решили предоставить элемент «list_display» через свою собственную функцию, и вам не нравятся выходные данные по умолчанию, вам нужно будет отформатировать его самостоятельно.В этом случае, если вы хотите, чтобы форматирование идентично тому, что заканчивается в поле базы данных DateTime:

from django.utils import formats
def today(self):
        return formats.localize(self.field2)

Фон:

templates/admin/change_list.html

использует тег шаблона

django.contrib.admin.templatetags.admin_list.result_list

, который, в свою очередь, вызовет

django.contrib.admin.templatetags.admin_list.items_for_result()

для визуализации значений отдельных столбцов для каждой строки.

Вы увидите, что оба ваших значения начинаются с экземпляра DateTime, либос помощью поиска в базе данных или вызова вашей функции см.

django.contrib.admin.util.lookup_field()

, но возвращаемое значение «f» будет только полем, если поле базы данных было.Вы предоставили функцию, поэтому lookup_field () предоставит только значение, а "f" будет None.

Таким образом, в items_for_result () ваше значение будет проходить через блок "если f равен None" и пропущено

result_repr = display_for_field(value, f)

Другими словами,

django.contrib.admin.util.display_for_field()

будет вызываться только из значения базы данных для форматирования в соответствии с типом поля, так что это процедура, в которой отсутствует значение вашей функции:

elif isinstance(field, models.DateField) or isinstance(field, models.TimeField):
    return formats.localize(value)

, и вам нужно будет выполнить эту последнюю строку самостоятельно, как показано выше.

РЕДАКТИРОВАТЬ: Относительно вашего вопроса

Как я могу сказать администратору сайта обрабатывать сегодня, как он обрабатывает field2?То есть, скажите администратору Django, что «сегодня» - это модели. DateTimeField?

Это не модели. DateTimeField, это значение функции.Если бы это был models.DateTimeField, он бы описывал вашу модель.Посмотрите на все, что влечет за собой: http://docs.djangoproject.com/en/dev/ref/models/fields/ В вашем примере вы действительно можете просто использовать field2.По-видимому, вы хотите что-то сделать с его значением, вычислить его и т. Д. - тогда что же такое сегодня.по умолчанию, так как это то, что документация по локализации кажется многообещающей.Кстати, я бы лучше определил форматированное значение в ModelAdmin, чем в самой модели.Я обычно называю это чем-то вроде «formatted_today» (чтобы сохранить значение datetime оригинала today ()), просто, если Admin - единственное место, где нужно отформатированное значение, imho, именно здесь оно должно быть определено.

1 голос
/ 11 апреля 2011

Это действительно очень странное поведение.В общей сложности думаю , это может иметь какое-то отношение к настройкам django;в частности настройки DATETIME_FORMAT (и связанные с ними).Фреймворк, вероятно, выполняет самоанализ полей, и если они имеют тип DateTime, они отображаются в соответствии с вышеупомянутыми настройками.

В большинстве случаев самоанализ методов не имеет смысла, поэтому я мог понять это поведениеесли это так.

Попробуйте изменить параметры соответствующим образом (укажите разные форматы даты и времени) и посмотрите, не изменились ли поля и не изменился ли метод.

Редактировать:

Глядя на django.contrib.databrowse.datastructures, есть раздел кода, который выполняет что-то вроде:

if isinstance(self.field, models.DateTimeField):
    objs = capfirst(formats.date_format(self.raw_value, 'DATETIME_FORMAT'))

Я мог бы представить, что подобное происходит в приложении администратора, хотя я не могу найтиточная ссылка на данный момент.

Чтобы достичь желаемого, вам нужно соответствующим образом отформатировать дату и время:

def today(self):
    from django.conf import settings
    return self.field2.strftime(settings.DATETIME_FORMAT)

Или, используя комментарий @ cata:

def today(self):
    from django.utils.formats import localize
    return localize(self.field2)
0 голосов
/ 26 мая 2013

Все предыдущие ответы предоставляют решения, которые будут некорректно обрабатывать информацию о часовых поясах в новых версиях Django.

field2 и today обычно показывают другое время, если settings.USE_TZ==True.

Я нашел этот вопрос сегодня и потратил некоторое время, чтобы выяснить правильный путь:

from django.db import models
from django.contrib import admin
from django.utils.timezone import template_localtime
from django.utils.formats import localize


class MyModel(models.Model):
    # ...
    field2=models.DateTimeField()

class MyModelAdmin(admin.ModelAdmin):
    # ...
    def today(self, obj):
        return localize(template_localtime(obj.field2))

admin.site.register(MyModel, MyModelAdmin)
...