django.db.utils.DatabaseError: ORA-00904: неверный идентификатор - PullRequest
0 голосов
/ 05 февраля 2019

Я запускаю приложение на django 1.11 и как движок базы данных Oracle Database 11G XE.У меня есть 3 таблицы producto, catalogo и catalogo_producto.Таблица catalogo_producto - это промежуточная таблица между producto и catalogo.При переносе таблиц проблем не возникает, но при создании объекта возникает следующая ошибка django.db.utils.DatabaseError: ORA-00904: "CATALOGO_PRODUCTO". "ID": invalid identifier.

Я знаю, что эта ошибка относится к тому факту, что я не назначил первичный ключ вмодели, но в соответствии с документацией django Дополнительные поля для отношений «многие ко многим» для этих случаев первичный ключ не назначается конкретному полю.Я также понимаю, что django в этих случаях создает PK ID, который не отображается в моделях.Так что я не знаю, является ли правильным решением просто создать поле id в таблице catalogo_producto или есть какое-то другое решение?

models.py

class Producto(models.Model):
    codigo = models.IntegerField(primary_key=True)
    precio = models.IntegerField()
    nombre = models.CharField(max_length=100)
    tipo = models.CharField(max_length=25)
    cantidad = models.IntegerField()

    class Meta:
        db_table = 'producto'

    def __str__(self):
        return str(self.codigo)

class Catalogo(models.Model):
    codigo = models.AutoField(primary_key=True)
    descripcion = models.CharField(max_length=250)
    fecha = models.DateField()
    productos = models.ManyToManyField(Producto, through='CatalogoProducto')

    class Meta:
        db_table = 'catalogo'

    def __str__(self):
        return str(self.codigo)

class CatalogoProducto(models.Model):
    catalogo_codigo = models.ForeignKey(Catalogo, models.DO_NOTHING, db_column='catalogo_codigo')
    producto_codigo = models.ForeignKey(Producto, models.DO_NOTHING, db_column='producto_codigo')
    posicion = models.IntegerField()
    precio = models.IntegerField()
    imagen_producto = models.ImageField(upload_to="images/", default='')

    class Meta:
        db_table = 'catalogo_producto'
        unique_together = (('catalogo_codigo', 'producto_codigo'),)

DDL Oracle

CREATE TABLE producto (
codigo     NUMBER(6) NOT NULL,
precio     NUMBER(8) NOT NULL,
nombre     VARCHAR2(100) NOT NULL,
tipo       VARCHAR2(25) NOT NULL,
cantidad   NUMBER(6) NOT NULL
);

ALTER TABLE producto ADD CONSTRAINT producto_pk PRIMARY KEY ( codigo );

CREATE TABLE catalogo (
codigo        NUMBER(6) NOT NULL,
descripcion   VARCHAR2(250) NOT NULL,
fecha         DATE NOT NULL);

ALTER TABLE catalogo ADD CONSTRAINT catalogo_pk PRIMARY KEY ( codigo );

CREATE TABLE catalogo_producto (
catalogo_id       NUMBER(6) NOT NULL,
producto_id       NUMBER(6) NOT NULL,
posicion          NUMBER(4) NOT NULL,
precio            NUMBER(8) NOT NULL,
imagen_producto   VARCHAR2(250) NOT NULL
);

ALTER TABLE catalogo_producto ADD CONSTRAINT catálogo_producto_pk PRIMARY KEY(catalogo_id, producto_id);

ALTER TABLE catalogo_producto
ADD CONSTRAINT cat_prod_catalogo_fk FOREIGN KEY ( catalogo_id )
    REFERENCES catalogo ( codigo );

ALTER TABLE catalogo_producto
ADD CONSTRAINT cat_prod_producto_fk FOREIGN KEY ( producto_id )
REFERENCES producto ( codigo );

Ответы [ 3 ]

0 голосов
/ 05 февраля 2019

Кажется, вы создаете первичные ключи и внешние ключи вручную.

ALTER TABLE producto ADD CONSTRAINT producto_pk PRIMARY KEY ( codigo );
ALTER TABLE catalogo ADD CONSTRAINT catalogo_pk PRIMARY KEY ( codigo );
ALTER TABLE catalogo_producto
ADD CONSTRAINT cat_prod_catalogo_fk FOREIGN KEY ( catalogo_id )
    REFERENCES catalogo ( codigo );

ALTER TABLE catalogo_producto
ADD CONSTRAINT cat_prod_producto_fk FOREIGN KEY ( producto_id )
REFERENCES producto ( codigo );

Вы указываете внешние ключи на несуществующие первичные ключи.Это даже создается Oracle?(Или, может быть, я неправильно читаю это.)

Возможно, вы создаете их в своих собственных скриптах SQL или они уже созданы.

Обычно в Django вы не пишете скрипты SQLдля создания таблиц самостоятельно, но вы пишете модели и затем запускаете:

./manage.py makemigrations # creates the files that create the DB structure
./manage.py migrate. # actually accesses the DB and creates the tables

Django создаст столбцы первичного ключа, назвав их ID.В общем, эти столбцы нужны для объединений (вы не сможете присоединиться к Oracle с вашими текущими ограничениями, это должно дать вам ошибку, очень похожую на ту, что вы получаете от Django).

Django также установитForeignKey ограничивается с помощью makemigrations и migrate, присваивая им соответствующие имена, используя имена полей в ваших моделях.

Если вам разрешено создавать свои собственные таблицы, удалите все параметры db_* из вашегокод и запустить makemigrations, потому что вам не придется проверять дубликаты имен таблиц.Позвольте Django выполнять работу везде, где только можно.

Миграции Django помогут вам отслеживать изменения, которые вы вносите в свои модели с течением времени и которые должны быть отражены в структуре вашей БД.Одна из причин использования Django заключается именно в том, что вы не хотите поддерживать это вручную.Смотри https://docs.djangoproject.com/en/2.1/topics/migrations/.

0 голосов
/ 05 февраля 2019

Похоже, вы создаете DDL вручную или что-то еще, потому что, если вы покопаетесь в файлах миграции, вы увидите, что django хочет создать поле id:

    migrations.CreateModel(
        name='CatalogoProducto',
        fields=[
            ('id', models.AutoField(auto_created=True,                 #<---- here!!!
                                    primary_key=True, serialize=False, 
                                    verbose_name='ID')),
            ('posicion', models.IntegerField()),
            ('precio', models.IntegerField()),
            ('catalogo_codigo', models.ForeignKey(db_c...

Проверьте дваждысоздаем таблицы из миграций:

python manage.py makemigrations
python manage.py migrate   #<-------- this one creates the tables.
0 голосов
/ 05 февраля 2019

Я нашел эту проблему в проекте django, на которую можно было бы ответить:

Здесь нет ошибки.По умолчанию Django хочет, чтобы имена столбцов таблицы соединения между моделями Foo и Bar были foo_id и bar_id.Столбцы промежуточной таблицы не называются так, поэтому возникает ошибка при попытке выполнить SQL для промежуточной таблицы (объединения).Чтобы решить эту проблему, создайте промежуточную таблицу вручную, указав имена столбцов db, и используйте новый сквозной параметр ManyToManyField для указания промежуточной модели.

Итак, я думаю, вам нужно изменить столбецимена в промежуточной модели:

https://code.djangoproject.com/ticket/8339

...