我正在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文档Extra fields on many-to-many relationships之后,对于这些情况,没有将主键分配给特定字段。我也了解django在这种情况下会创建一个未在模型中显示的PK“ ID”。因此,我不知道正确的解决方案是只是在catalogo_producto表中创建一个id字段,还是有其他解决方案?
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 );
答案 0 :(得分:0)
我在django项目上发现了这个问题,这可能是答案:
这里没有错误。默认情况下,Django希望模型Foo和Bar之间的联接表的列名称为foo_id和bar_id。中间表的列没有被调用,因此在尝试对中间(联接)表执行SQL时会引发错误。 要解决此问题,请手动构造中间表,指定db列的名称,然后在ManyToManyField上使用new through参数指定中间模型。
所以,我认为您必须更改中间模型中的列名:
答案 1 :(得分:0)
您似乎正在手动创建主键和外键。
with concurrent.futures.ProcessPoolExecutor(big_number) as executor:
par_results = executor.map(fnc, (param1, param2, counter))
您正在将外键指向不存在的主键。这甚至是由Oracle创建的吗? (或者也许我误读了此内容。)
也许您是在自己的SQL脚本中创建它们,或者已经创建了它们。
通常,在Django中,您无需编写用于创建表的SQL脚本,而是编写模型然后运行:
Django将创建主键列,并将其命名为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,它会给您一个与Django非常相似的错误)。
Django还将通过./manage.py makemigrations # creates the files that create the DB structure
./manage.py migrate. # actually accesses the DB and creates the tables
和ID
设置ForeignKey约束,并使用模型中的字段名称对其进行适当命名。
如果允许您创建自己的表,请从代码中删除所有makemigrations
参数并运行migrate
,因为您不必费心检查重复的表名。让Django尽你所能。
Django迁移将帮助您随时跟踪对模型所做的更改,这些更改需要反映在数据库结构中。使用Django的原因之一就是因为您不想手动维护它。参见https://docs.djangoproject.com/en/2.1/topics/migrations/。
答案 2 :(得分:0)
您似乎正在手动创建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.