#29738: Django can't serialize DateTimeTZRange(lower=None, upper=None, 
bounds='[)')
-------------------------------------+-------------------------------------
     Reporter:  grahammayer          |                    Owner:  nobody
         Type:  Bug                  |                   Status:  new
    Component:  contrib.postgres     |                  Version:  2.0
     Severity:  Normal               |               Resolution:
     Keywords:  rangefield,          |             Triage Stage:  Accepted
  postgresql, psycopg2, migrations   |
    Has patch:  0                    |      Needs documentation:  1
  Needs tests:  1                    |  Patch needs improvement:  0
Easy pickings:  1                    |                    UI/UX:  0
-------------------------------------+-------------------------------------
Changes (by Nick Pope):

 * component:  Migrations => contrib.postgres
 * needs_tests:  0 => 1
 * easy:  0 => 1
 * keywords:   => rangefield, postgresql, psycopg2, migrations
 * needs_docs:  0 => 1
 * stage:  Unreviewed => Accepted


Old description:

> 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':
>  Traceback (most recent call last):
>   File "manage.py", line 12, in <module>
>     execute_from_command_line(sys.argv)
>   File "/home/grahammayer/logimeter/logimeter/lib/python3.6/site-
> packages/django/core/management/__init__.py", line 371, in
> execute_from_command_line
>     utility.execute()
>   File "/home/grahammayer/logimeter/logimeter/lib/python3.6/site-
> packages/django/core/management/__init__.py", line 365, in execute
>     self.fetch_command(subcommand).run_from_argv(self.argv)
>   File "/home/grahammayer/logimeter/logimeter/lib/python3.6/site-
> packages/django/core/management/base.py", line 288, in run_from_argv
>     self.execute(*args, **cmd_options)
>   File "/home/grahammayer/logimeter/logimeter/lib/python3.6/site-
> packages/django/core/management/base.py", line 335, in execute
>     output = self.handle(*args, **options)
>   File "/home/grahammayer/logimeter/logimeter/lib/python3.6/site-
> packages/django/core/management/commands/makemigrations.py", line 172, in
> handle
>     self.write_migration_files(changes)
>   File "/home/grahammayer/logimeter/logimeter/lib/python3.6/site-
> packages/django/core/management/commands/makemigrations.py", line 210, in
> write_migration_files
>     migration_string = writer.as_string()
>   File "/home/grahammayer/logimeter/logimeter/lib/python3.6/site-
> packages/django/db/migrations/writer.py", line 151, in as_string
>     operation_string, operation_imports =
> OperationWriter(operation).serialize()
>   File "/home/grahammayer/logimeter/logimeter/lib/python3.6/site-
> packages/django/db/migrations/writer.py", line 110, in serialize
>     _write(arg_name, arg_value)
>   File "/home/grahammayer/logimeter/logimeter/lib/python3.6/site-
> packages/django/db/migrations/writer.py", line 74, in _write
>     arg_string, arg_imports = MigrationWriter.serialize(_arg_value)
>   File "/home/grahammayer/logimeter/logimeter/lib/python3.6/site-
> packages/django/db/migrations/writer.py", line 279, in serialize
>     return serializer_factory(value).serialize()
>   File "/home/grahammayer/logimeter/logimeter/lib/python3.6/site-
> packages/django/db/migrations/serializer.py", line 203, in serialize
>     return self.serialize_deconstructed(path, args, kwargs)
>   File "/home/grahammayer/logimeter/logimeter/lib/python3.6/site-
> packages/django/db/migrations/serializer.py", line 90, in
> serialize_deconstructed
>     arg_string, arg_imports = serializer_factory(arg).serialize()
>   File "/home/grahammayer/logimeter/logimeter/lib/python3.6/site-
> packages/django/db/migrations/serializer.py", line 370, in
> serializer_factory
>     "topics/migrations/#migration-serializing" % (value,
> get_docs_version())
> ValueError: Cannot serialize: DateTimeTZRange(None, None, '[)')

New description:

 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}}}:

 {{{
  Traceback (most recent call last):
   File "manage.py", line 12, in <module>
     execute_from_command_line(sys.argv)
   File "/home/grahammayer/logimeter/logimeter/lib/python3.6/site-
 packages/django/core/management/__init__.py", line 371, in
 execute_from_command_line
     utility.execute()
   File "/home/grahammayer/logimeter/logimeter/lib/python3.6/site-
 packages/django/core/management/__init__.py", line 365, in execute
     self.fetch_command(subcommand).run_from_argv(self.argv)
   File "/home/grahammayer/logimeter/logimeter/lib/python3.6/site-
 packages/django/core/management/base.py", line 288, in run_from_argv
     self.execute(*args, **cmd_options)
   File "/home/grahammayer/logimeter/logimeter/lib/python3.6/site-
 packages/django/core/management/base.py", line 335, in execute
     output = self.handle(*args, **options)
   File "/home/grahammayer/logimeter/logimeter/lib/python3.6/site-
 packages/django/core/management/commands/makemigrations.py", line 172, in
 handle
     self.write_migration_files(changes)
   File "/home/grahammayer/logimeter/logimeter/lib/python3.6/site-
 packages/django/core/management/commands/makemigrations.py", line 210, in
 write_migration_files
     migration_string = writer.as_string()
   File "/home/grahammayer/logimeter/logimeter/lib/python3.6/site-
 packages/django/db/migrations/writer.py", line 151, in as_string
     operation_string, operation_imports =
 OperationWriter(operation).serialize()
   File "/home/grahammayer/logimeter/logimeter/lib/python3.6/site-
 packages/django/db/migrations/writer.py", line 110, in serialize
     _write(arg_name, arg_value)
   File "/home/grahammayer/logimeter/logimeter/lib/python3.6/site-
 packages/django/db/migrations/writer.py", line 74, in _write
     arg_string, arg_imports = MigrationWriter.serialize(_arg_value)
   File "/home/grahammayer/logimeter/logimeter/lib/python3.6/site-
 packages/django/db/migrations/writer.py", line 279, in serialize
     return serializer_factory(value).serialize()
   File "/home/grahammayer/logimeter/logimeter/lib/python3.6/site-
 packages/django/db/migrations/serializer.py", line 203, in serialize
     return self.serialize_deconstructed(path, args, kwargs)
   File "/home/grahammayer/logimeter/logimeter/lib/python3.6/site-
 packages/django/db/migrations/serializer.py", line 90, in
 serialize_deconstructed
     arg_string, arg_imports = serializer_factory(arg).serialize()
   File "/home/grahammayer/logimeter/logimeter/lib/python3.6/site-
 packages/django/db/migrations/serializer.py", line 370, in
 serializer_factory
     "topics/migrations/#migration-serializing" % (value,
 get_docs_version())
 ValueError: Cannot serialize: DateTimeTZRange(None, None, '[)')
 }}}

--

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
 [https://docs.djangoproject.com/en/2.1/topics/migrations/#serializing-
 values documentation].

 So there are a few options:

 a. Can you get away with using {{{default=None, null=True}}}?
 b. Does {{{default=(None, None)}}} work instead? (I believe this will be
 limited to the
 [http://initd.org/psycopg/docs/extras.html#psycopg2.extras.Range default
 bounds]: `[)`)
 c. 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:
 {{{#!python
 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:

 {{{#!python
 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.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/29738#comment:1>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-updates+unsubscr...@googlegroups.com.
To post to this group, send email to django-updates@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/069.84ef1660e9354733da1d8889263a516a%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to