Как использовать 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

Вернуться на верх