Как использовать Django's DurationField с Postgres, если ранее он был определен с помощью sqlite?
Недавно я перенес все свои данные из sqlite
в postgres
. Все поля работают нормально, за исключением поля duration
. Оно отображается как целое число в панели администратора и не позволяет мне редактировать или сохранять.
Он прекрасно работает с sqlite. Однако после перехода на Postgres я получаю следующие ошибки (при сохранении или обновлении):
ProgrammingError at /admin/content/movie/add/
колонка "duration" имеет тип bigint, но выражение имеет тип interval
СОВЕТ: Вам потребуется переписать или привести выражение.
class Movie(models.Model):
"""
Stores movie related information.
"""
unique_id = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
name = models.CharField(verbose_name='name', max_length=100, blank=False, unique=True)
slug = models.SlugField(verbose_name='slug', null=True, blank=True)
description = models.TextField(verbose_name='description', blank=True)
poster = models.ImageField(verbose_name='poster',upload_to='posters/movies', default='defaults/video.webp', validators=[validate_image])
# Field of interest
duration = models.DurationField(verbose_name='duration')
created_at = models.DateTimeField(verbose_name='created_at', auto_now_add=True)
Я также использовал следующий length
метод для успешного преобразования поля в человекочитаемую форму (при использовании sqlite), но он не работает после перехода на postgres. Там говорится:
duration (int) не имеет атрибута 'days'
def length(self):
"""
Converts timedelta into hours and minutes.
"""
days, seconds = self.duration.days, self.duration.seconds
hours = days * 24 + seconds // 3600
minutes = (seconds % 3600) // 60
seconds = (seconds % 60)
if hours == 0:
length = f'{minutes} min'
else:
if minutes == 0:
length = f'{hours} h'
else:
length = f'{hours} h {minutes} min'
return length
Примечание: я использовал
pgloader
для загрузки данных sqlite. https://pgloader.readthedocs.io/en/latest/quickstart.html#migrating-from-sqlite
Отсюда DurationField:
Поле для хранения периодов времени - в Python моделируется timedelta. При использовании в PostgreSQL используется тип данных - интервал, а в Oracle - INTERVAL DAY(9) TO SECOND(6). В противном случае используется bigint микросекунд.
Так что вам нужно либо сделать поле в модели IntegerField
, чтобы соответствовать данным, либо изменить данные на Postgres interval
. Так как в SQLite данные хранятся в виде микросекунд, то что-то вроде:
select (1000000::text || ' microseconds')::interval;
interval
----------
00:00:01