python - Django 模型尝试自动创建主键字段,即使它已经指定

标签 python mysql django rdbms

Django 文档中指出,每个模型都需要一个主键。在我的 MySQL 模式中,指定表的主键由多个列组成。使用inspectdb自动生成模型会创建unique_together元信息。

class Connections(models.Model):
    router = models.ForeignKey('Routers', models.CASCADE)
    src_mac = models.CharField(db_column='src_MAC', max_length=17)  # Field name made lowercase.
    src_ip = models.CharField(max_length=45, blank=True, null=True)
    src_port = models.CharField(max_length=45)
    dest_mac = models.CharField(db_column='dest_MAC', max_length=17, blank=True, null=True)  # Field name made lowercase.
    dest_ip = models.CharField(max_length=45)
    dest_port = models.CharField(max_length=45)
    first_activity = models.DateTimeField(blank=True, null=True)
    last_activity = models.DateTimeField(blank=True, null=True)
    hits_counter = models.IntegerField(blank=True, null=True)

def __unicode__(self):
    return self.src_ip

class Meta:
      db_table = 'Connections'
      unique_together = (('router', 'src_mac', 'src_port', 'dest_ip', 'dest_port'),)

当我运行的时候

> python manage.py shell

>>> Connections.objects.all()

它给了我操作错误:(1054,“'字段列表'中的未知列'Connections.id'”)据我了解,这意味着Django正在尝试自动创建连接的主键列。 我该如何解决这个问题?

最佳答案

tl;dr:重新创建表或手动将“id”字段添加到数据库。

我不认为可以在所有数据库中创建主键。 例如,当使用 SQLite 时,如果我创建表的简化版本,更改它以添加 PK 会返回错误:

> CREATE TABLE connections(src_MAC CHAR(17) NOT NULL, first_activity DATETIME NULL);
> INSERT INTO connections VALUES ('abcd1234',date('now'));
> ALTER TABLE connections add column id integer NOT NULL PRIMARY KEY AUTOINCREMENT;
Error: Cannot add a PRIMARY KEY column

同样,运行 Django 迁移以使用 SQLite 创建字段也无法以静默方式添加字段(可能是 Django 问题)。

如果您不幸使用的数据库支持添加主键(如果您不确定,请通过运行ALTER命令进行检查),最好的选择是转储表数据,删除表,使用主键创建一个新表,最后重新加载表数据。这似乎也是最安全的方法。

另一方面,如果您确实使用支持添加主键的数据库,则可以尝试进行迁移或手动更改数据库。

在 Postgres 中手动创建 id 字段非常简单:

ALTER TABLE connections ADD COLUMN id SERIAL PRIMARY KEY;

这足以使模型在 Django 中可用。现在来说说困难的方法。


似乎 makemigrations 假设 ID 字段已经存在,因此如果您选择使用迁移,则初始迁移将需要修复(删除 id 字段)。您可以手动创建 CreateField 迁移:

migrations/0002_connections_id.py

# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-07-08 08:56
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

    dependencies = [
        ('testapp', '0001_initial'),
    ]

    operations = [
        migrations.AddField(
            model_name='connections',
            name='id',
            field=models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
        ),
    ]

不幸的是,这似乎仍然不够,因为创建的列不会自动递增(可能是另一个 Django 问题)。现在的解决方案是更改创建的字段,如下所示:

> ALTER TABLE connections ALTER id SET default nextval('connections_id_seq');

最后,这些值对 Django 有意义,您现在可以像往常一样查询和创建“Connections”实例。

以防万一以后有人需要这个,我已将用于测试它的代码推送到 this GitHub repo .

关于python - Django 模型尝试自动创建主键字段,即使它已经指定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38232364/

相关文章:

django - 如何在自定义模板标签上使用模板过滤器?

python - 使用 argparse 保持参数不变

python - 如何使用 scikit-learn 中的信息增益度量选择 Dataframe 中的最佳特征

python - 这是你分页的方式,还是有更好的算法?

mysql - 在mysql中一起更改唯一键

django - 如何在 Django 模板中引用选择列表?

python - 如何在我自己的模板中使用内置的密码重置/更改 View

python - python 中连续脚本运行之间的 vars() 字典

mysql - 购物 list 项目数据类型

php - Laravel中两点之间的Haversine距离计算