Changes between Initial Version and Version 1 of Ticket #29738


Ignore:
Timestamp:
Sep 6, 2018, 8:38:15 AM (6 years ago)
Author:
Nick Pope
Comment:

Presumably you are using default=DateTimeTZRange(lower=None, upper=None, bounds='[)')? Could you provide a simple example project?

The problem is that psycopg2.extras.DateTimeTZRange cannot be serialized into a migrations, see documentation.

So there are a few options:

  1. Can you get away with using default=None, null=True?
  2. Does default=(None, None) work instead? (I believe this will be limited to the default bounds: [))
  3. You need to make DateTimeTZRange deconstructible which will allow for other bounds to be defined.

We should be able to get away with making these range objects deconstructible as we only expect them to take simple arguments that are already supported by the serializer.

Here is an example:

from psycopg2.extras import DateTimeTZRange

from django.contrib.postgres.fields import DateTimeRangeField
from django.utils.deconstruct import deconstructible


DateTimeTZRange = deconstructible(DateTimeTZRange, path='psycopg2.extras.DateTimeTZRange')


class RangeTestModel(models.Model):
    a = DateTimeRangeField(
        default=None,
        null=True,
    )
    b = DateTimeRangeField(
        default=(None, None),
        null=False,
    )
    c = DateTimeRangeField(
        default=DateTimeTZRange(None, None, '[]'),
        null=False,
    )

I managed to produce the following migration:

import django.contrib.postgres.fields.ranges
from django.db import migrations, models
import psycopg2.extras


class Migration(migrations.Migration):

    dependencies = [
    ]

    operations = [
        migrations.CreateModel(
            name='RangeTestModel',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('a', django.contrib.postgres.fields.ranges.DateTimeRangeField(default=None, null=True)),
                ('b', django.contrib.postgres.fields.ranges.DateTimeRangeField(default=(None, None))),
                ('c', django.contrib.postgres.fields.ranges.DateTimeRangeField(default=psycopg2.extras.DateTimeTZRange(None, None, '[]'))),
            ],
        ),
    ]

(Disclaimer: I have only attempted to produce migrations and not actually called RangeTestModel.objects.create()...)

So in summary, I think that we only need to add some documentation to explain how to handle defaults for range fields and tests to ensure that it continues to work.

Legend:

Unmodified
Added
Removed
Modified
  • Ticket #29738

    • Property Component Migrationscontrib.postgres
    • Property Easy pickings set
    • Property Keywords rangefield postgresql psycopg2 migrations added
    • Property Needs documentation set
    • Property Needs tests set
    • Property Triage Stage UnreviewedAccepted
  • Ticket #29738 – Description

    initial v1  
    1 Tried to use DateTimeTZRange(lower=None, upper=None, bounds='[)') as a default for a model field and get the following error when running 'python manage.py makemigrations':
     1Tried to use {{{DateTimeTZRange(lower=None, upper=None, bounds='[)')}}} as a default for a model field and get the following error when running {{{python manage.py makemigrations}}}:
     2
     3{{{
    24 Traceback (most recent call last):
    35  File "manage.py", line 12, in <module>
     
    3032    "topics/migrations/#migration-serializing" % (value, get_docs_version())
    3133ValueError: Cannot serialize: DateTimeTZRange(None, None, '[)')
     34}}}
Back to Top