Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

300
Vistas
Migración condicional de Django basada en un campo solo presente en la nueva versión

Mi aplicación que actualmente depende de Postgres y Django's Postgres-only JSONField . El campo funciona bien y no tengo ningún interés en otro proyecto, pero tengo usuarios potenciales que quieren usar mi aplicación, pero no pueden mientras dependa de Postgres.

Django 3.1 tiene una versión multiplataforma de este campo —que funcionará para mis necesidades— pero no quiero obligar a todo el mundo a usar Django 3.1; Me gustaría ofrecer a la gente la posibilidad de elegir entre Postgres o Django 3.1+. Sobre el papel, esto es bastante simple con una importación condicional...

 try: from django.db.models import JSONField except ImportError: from django.contrib.postgres.fields import JSONField

Y si instalé Django 3.1 y generé una migración, podría llevarme de django.contrib.postgres.fields.JSONField a django.db.models.JSONField . Pero...

  • Los nuevos usuarios seguirán ejecutando la migración inicial. Todavía tendré una dependencia en Postgres.
  • Los usuarios de Sub-Django 3.1 no podrán ejecutar la nueva migración. Ahora tengo una dependencia de Django 3.1.

Esto es peor que cuando empecé. ¿Cómo hago este tipo de migración de campo de una manera que funcione para todos?

over 4 years ago · Santiago Trujillo
4 Respuestas
Responde la pregunta

0

Las migraciones son solo código. El hecho de que se generen automáticamente no significa que no deba cambiarlos. Lo alentamos a que, al menos, verifique que se generen correctamente, pero tampoco hay nada de malo en escribirlos usted mismo.

Esto funciona para mí:

Modelo:

 from django.db import models try: from django.db.models import JSONField except ImportError: from django.contrib.postgres.fields import JSONField class MyModel(models.Model): stuff = JSONField()

Migración:

 from django.db import migrations, models try: from django.db.models import JSONField except ImportError: from django.contrib.postgres.fields import JSONField class Migration(migrations.Migration): dependencies = [('testapp', '0001_initial')] operations = [ migrations.CreateModel( name='MyModel', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('stuff', JSONField()), ], ), ]

Tenga en cuenta que si necesita cambiar este campo en el futuro, deberá realizar este proceso nuevamente.

over 4 years ago · Santiago Trujillo Denunciar

0

Tengo esto del código fuente de Django

 from django.db.models import JSONField as BuiltinJSONField class JSONField(BuiltinJSONField): system_check_deprecated_details = { 'msg': ( 'django.contrib.postgres.fields.JSONField is deprecated. Support ' 'for it (except in historical migrations) will be removed in ' 'Django 4.0.' ), 'hint': 'Use django.db.models.JSONField instead.', 'id': 'fields.W904', }

Esto indica que django.contrib.postgres.fields.JSONField quedará en desuso. Además, Django usa django.db.models.JSONField como JSONField especial de postgres.

Aparte de eso, generé el comando SQL usando el comando sqlmigrate y fue como,

 BEGIN; -- -- Create model MyModel -- CREATE TABLE "myapp_mymodel" ("id" serial NOT NULL PRIMARY KEY, "stuff" jsonb NOT NULL); COMMIT;

Sorprendentemente, tengo el mismo comando SQL usando Django==3.0 y Django==3.1 y en la base de datos, el campo es de tipo jsonb

Esta información concluye que no tiene que preocuparse por esta nueva actualización de JSONField.

¿Qué cambios hay que hacer?

No necesita generar un nuevo archivo de migración , pero edite los archivos de migración existentes que tienen una referencia django.contrib.postgres.fields.JSONField con el bloque try...except .

¡¡¡Eso es todo!!!

over 4 years ago · Santiago Trujillo Denunciar

0

Le di un punto a Tom Carrick por su respuesta, pero creo que también debería incluir el uso deMeta.required_db_vendor = 'postgres' en Django <3.1

 # models.py from django.db import models try: from django.db.models import JSONField postgres_only = False except ImportError: from django.contrib.postgres.fields import JSONField postgres_only = True class MyModel(models.Model): stuff = JSONField() class Meta: if postgres_only: required_db_vendor = 'postgres'
 # migrations/0001_initial.py from django.db import migrations, models try: from django.db.models import JSONField postgres_only = False except ImportError: from django.contrib.postgres.fields import JSONField postgres_only = True class Migration(migrations.Migration): dependencies = [('testapp', '0001_initial')] operations = [ migrations.CreateModel( name='MyModel', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('stuff', JSONField()), ], options={'required_db_vendor': 'postgres'} if postgres_only else None, ), ]

Esto asegurará que los usuarios de su aplicación reutilizable no puedan usarla en una base de datos diferente a PostgreSQL en Django < 3.1 y habilitará sin problemas el soporte en 3.1 sin requerir una migración en los usuarios de PostgreSQL que usen su biblioteca y actualicen a Django 3.1.

over 4 years ago · Santiago Trujillo Denunciar

0

Todas las nuevas migraciones se corregirán automáticamente si se utiliza esta solución con un método deconstruct() .

Puede crear un JSONField personalizado compatible que encapsule ambas variantes.

Cree un pequeño archivo fields.py en su aplicación:

 try: from django.db.models import JSONField as OrigJSONField except ImportError: from django.contrib.postgres.fields import JSONField as OrigJSONField class JSONField(OrigJSONField): def deconstruct(self): # the original path was 'django.db.models.JSONField' or 'django.contrib.postgres.fields....' name, path, args, kwargs = super().deconstruct() # Substitute 'my_app' by your application name everywhere. path = 'my_app.fields.JSONField' return name, path, args, kwargs

Cambie una línea en su models.py :

 from my_app.fields import JSONField

Edite todas las migraciones existentes que usan un JSONField:

 import my_app.fields ... ('stuff', my_app.fields.JSONField()),

(o equivalente)

 from my_app.fields import JSONField ... ('stuff', JSONField()).

No se crea ninguna migración después de eso porque makemigrations no encuentra ninguna diferencia.

Todas las futuras makemigrations después de un modelo modificado se crearán automáticamente con my_app.fields.JSONField() . La compatibilidad es un beneficio de esta solución.


Reflexión sobre Django Release Notes 3.1 y futuras:

Describen una actualización simple que requiere crear una nueva migración que solo actualice la ruta de importación, pero no genera SQL, por ejemplo, mediante sqlmigrate . Es más fácil que editar migraciones antiguas.

Tal vez usted también actualice en dos años a Django >= 3.1 solamente y tendrá dos alternativas:

A) Solo se editará la importación en models.py y creará una nueva migración formal casi vacía de manera similar a las notas de la versión. No podrá eliminar la ruta de importación my_app.fields.JSONField porque debe poder importarse de migraciones antiguas de manera similar que Django nunca puede eliminar la ruta django.contrib.postgres.fields.JSONField . El archivo my_app/fields.py podría simplificarse a una línea from django.db.models import JSONField as JSONField después de una actualización incondicional de requisitos.

B) Es posible volver a editar las migraciones antiguas solo al nuevo JSONField, pero no es razonable.

(Es responsabilidad de cada usuario que una edición en un archivo de migraciones no requiera un estado de base de datos modificado y todas las migraciones permanezcan consistentes entre sí. Es por eso que no se puede encontrar mucho al respecto, excepto casos claros).

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda