Estoy tratando de restringir GFK para que solo apunte a objetos de algunos modelos, y pensé que CheckConstraint sería una excelente manera de hacerlo, sin embargo, recibo este error
class ManualAdjustment(Model): content_type = models.ForeignKey(ContentType, null=True, on_delete=models.CASCADE) object_id = models.PositiveIntegerField(null=True) booking_obj = GenericForeignKey('content_type', 'object_id') # should point to a app1.Booking1 or app2.Booking2 or app3.Booking3 only - trying to enforce this via CheckConstraint class Meta: constraints = [ models.CheckConstraint( check= Q(content_type__app_label='app1', content_type__model='booking1') | Q(content_type__app_label='app2', content_type__model='booking2') | Q(content_type__app_label='app3', content_type__model='booking3'), name='myconstraint_only_certain_models'), ] execute_from_command_line(sys.argv) File "/Users/myuser/.virtualenvs/xenia371/lib/python3.7/site-packages/django/core/management/__init__.py", line 381, in execute_from_command_line utility.execute() File "/Users/myuser/.virtualenvs/xenia371/lib/python3.7/site-packages/django/core/management/__init__.py", line 375, in execute self.fetch_command(subcommand).run_from_argv(self.argv) File "/Users/myuser/.virtualenvs/xenia371/lib/python3.7/site-packages/django/core/management/base.py", line 323, in run_from_argv self.execute(*args, **cmd_options) File "/Users/myuser/.virtualenvs/xenia371/lib/python3.7/site-packages/django/core/management/commands/sqlmigrate.py", line 30, in execute return super().execute(*args, **options) File "/Users/myuser/.virtualenvs/xenia371/lib/python3.7/site-packages/django/core/management/base.py", line 364, in execute output = self.handle(*args, **options) File "/Users/myuser/.virtualenvs/xenia371/lib/python3.7/site-packages/django/core/management/commands/sqlmigrate.py", line 64, in handle sql_statements = executor.collect_sql(plan) File "/Users/myuser/.virtualenvs/xenia371/lib/python3.7/site-packages/django/db/migrations/executor.py", line 225, in collect_sql state = migration.apply(state, schema_editor, collect_sql=True) File "/Users/myuser/.virtualenvs/xenia371/lib/python3.7/site-packages/django/db/migrations/migration.py", line 124, in apply operation.database_forwards(self.app_label, schema_editor, old_state, project_state) File "/Users/myuser/.virtualenvs/xenia371/lib/python3.7/site-packages/django/db/migrations/operations/models.py", line 827, in database_forwards schema_editor.add_constraint(model, self.constraint) File "/Users/myuser/.virtualenvs/xenia371/lib/python3.7/site-packages/django/db/backends/base/schema.py", line 343, in add_constraint sql = constraint.create_sql(model, self) File "/Users/myuser/.virtualenvs/xenia371/lib/python3.7/site-packages/django/db/models/constraints.py", line 47, in create_sql check = self._get_check_sql(model, schema_editor) File "/Users/myuser/.virtualenvs/xenia371/lib/python3.7/site-packages/django/db/models/constraints.py", line 37, in _get_check_sql where = query.build_where(self.check) File "/Users/myuser/.virtualenvs/xenia371/lib/python3.7/site-packages/django/db/models/sql/query.py", line 1296, in build_where return self._add_q(q_object, used_aliases=set(), allow_joins=False, simple_col=True)[0] File "/Users/myuser/.virtualenvs/xenia371/lib/python3.7/site-packages/django/db/models/sql/query.py", line 1312, in _add_q current_negated, allow_joins, split_subq, simple_col) File "/Users/myuser/.virtualenvs/xenia371/lib/python3.7/site-packages/django/db/models/sql/query.py", line 1318, in _add_q split_subq=split_subq, simple_col=simple_col, File "/Users/myuser/.virtualenvs/xenia371/lib/python3.7/site-packages/django/db/models/sql/query.py", line 1199, in build_filter raise FieldError("Joined field references are not permitted in this query") django.core.exceptions.FieldError: Joined field references are not permitted in this query¿Alguna pista sobre cómo resolver esto? He usado GFK antes, pero con la nueva restricción de verificación, ahora puede ser una forma muy segura de errores, si pudiera hacer que esto migre
Gracias
No es posible lograr esto usando la funcionalidad CheckConstraint . Django traduce todos los comandos ORM a los comandos específicos de la base de datos de bajo nivel, y dicha creación de restricciones no es posible ni siquiera en el nivel de la base de datos. De hecho, podemos aplicar CheckConstraint a una sola fila que se agrega/actualiza solamente.
La nota en la documentación de PostgreSQL dice:
PostgreSQL no admite restricciones CHECK que hagan referencia a datos de tablas que no sean la fila nueva o actualizada que se está comprobando. Si bien una restricción CHECK que viola esta regla puede parecer que funciona en pruebas simples, no puede garantizar que la base de datos no alcance un estado en el que la condición de la restricción sea falsa (debido a cambios posteriores de las otras filas involucradas). Esto provocaría un error en el volcado y la recarga de la base de datos. La recarga podría fallar incluso cuando el estado completo de la base de datos es consistente con la restricción, debido a que las filas no se cargan en un orden que satisfaga la restricción. Si es posible, use restricciones UNIQUE, EXCLUDE o FOREIGN KEY para expresar restricciones entre filas y entre tablas.
Si lo que desea es una verificación única contra otras filas en la inserción de la fila, en lugar de una garantía de coherencia mantenida continuamente, se puede usar un disparador personalizado para implementar eso. (Este enfoque evita el problema de volcado/recarga porque pg_dump no reinstala los activadores hasta después de recargar los datos, por lo que la verificación no se aplicará durante un volcado/recarga).
Por lo tanto, la única forma de introducir las restricciones deseadas es mediante activadores de base de datos. Puede crear una migración vacía y agregarle un activador de base de datos.