2011-11-08 18 views
7

Tengo un modelo respaldado por una vista de base de datos.Django - Cómo evitar la creación de restricciones de la clave externa de la base de datos

class OrgCode(models.Model): 
    org_code    = models.CharField(db_column=u'code',max_length=15) 
    org_description   = models.CharField(max_length=250) 
    org_level_num   = models.IntegerField() 

    class Meta: 
     db_table = u'view_FSS_ORG_PROFILE' 

Necesito hacer referencia a esto en otro modelo

class AssessmentLocation(models.Model): 
    name    = models.CharField(max_length=150) 
    org     = models.ForeignKey(OrgCode) 

no puedo correr syncdb debido a restricciones de clave externa no se pueden crear referencia a una vista.

u"Foreign key 'FK__main_asse__org__1D114BD1' 
references object 'view_FSS_ORG_PROFILE' 
which is not a user table.", None, 0, -214 
7217900), None) 
Command: 
CREATE TABLE [main_assessmentlocation] (
    [id] int IDENTITY (1, 1) NOT NULL PRIMARY KEY, 
    [name] nvarchar(150) NOT NULL, 
    [org] int NOT NULL REFERENCES [view_FSS_ORG_PROFILE] ([id]), 
) 

La solución consiste en sacar la Meta: db_table que apunta a la vista y dejar db sincronización crear la tabla del OrgCode, a continuación, poner el Meta: DB_Table de nuevo después de syncdb.

¿Hay alguna manera de evitar la creación de restricciones de clave externa para ciertos modelos o campos?

Actualización: I añadió un método estático para el modelo relacionado que indica que es una vista

class OrgCode(models.Model): 
    org_code    = models.CharField(max_length=15) 
    org_description   = models.CharField(max_length=250) 

    @staticmethod 
    def is_backend_view(): 
     return True 

Entonces hicieron caso omiso DatabaseCreation.sql_for_inline_foreign_key_references en creation.py django_mssql:

def sql_for_inline_foreign_key_references(self, field, known_models, style): 
    try: 
     field.rel.to.is_backend_view() 
     return "", False 
    except: 
     return super(DatabaseCreation,self).sql_for_inline_foreign_key_references(field, known_models, style)  

el SQL generado a partir de syncdb deja fuera la restricción:

CREATE TABLE [main_assessmentlocation] (
    [id] int IDENTITY (1, 1) NOT NULL PRIMARY KEY, 
    [name] nvarchar(150) NOT NULL, 
    [org] int, -- NO FK CONSTRAINT ANYMORE -- 
); 

Esta consiste en cortar django_mssql así que voy a seguir intentando, quizás enganchar en la señal django.db.backends.signals.connection_created va a funcionar ...

Respuesta

10

django versión de desarrollo tiene db_constraint campo para ForeignKey modelo campo - docs.

+0

¡Gracias! Eso es lo que necesitaba, ahora solo tendré que esperar a que aterrice en un lanzamiento y puedo eliminar mi truco. –

+1

'db_constraint' se puede usar de forma segura desde la versión 1.6 –

4

Si establece managed=False (Django docs) en su modelo de Meta clase, Django no creará la tabla cuando ejecute syncdb.

class AssessmentLocation(models.Model): 
    name = models.CharField(max_length=150) 
    org = models.ForeignKey(OrgCode) 

    class Meta: 
     managed = False 

Django tiene un gancho para provide initial sql data. Podemos (¿ab?) Usar esto para que Django cree la tabla inmediatamente después de ejecutar syncdb.

Crear un archivo myapp/sql/assessmentlocation.sql, que contiene la instrucción create table:

CREATE TABLE [main_assessmentlocation] (
    [id] int IDENTITY (1, 1) NOT NULL PRIMARY KEY, 
    [name] nvarchar(150) NOT NULL, 
    [org] int, -- NO FK CONSTRAINT ANYMORE -- 
); 

Si tiene otros modelos con claves externas al modelo AssessmentLocation, es posible que tenga problemas si Django trata de aplicar la restricción de clave externa antes de ejecutar el sql personalizado para crear la tabla. De lo contrario, creo que este enfoque funcionará.

+0

Gracias! Miré esto y funciona. El modelo de objeto relacionado basado en vista es parte de un marco que estoy construyendo para ser utilizado por otros desarrolladores. Intento no desviarme de la creación del modelo syncdb y los documentos estándar de django. –

Cuestiones relacionadas