Python 无效的列名';id';在Django

Python 无效的列名';id';在Django,python,sql-server,django,django-models,Python,Sql Server,Django,Django Models,因此,我以不同的方式使用Django模型,我在MS SQL server中有现有的表,我想为我的应用程序访问它们。我一直在学习pluralsights的一些教程 . 我按照相应的步骤操作并准备好了模型,当我使用“migrate”命令时,出现了这个错误 “AssertionError:模型不能有多个自动字段。” 所以我查了一下,得到了Django的另一份文档 默认情况下,Django为每个模型提供以下字段: id=models.AutoField(主键=True) 这是一个自动递增的主键 如果要指

因此,我以不同的方式使用Django模型,我在MS SQL server中有现有的表,我想为我的应用程序访问它们。我一直在学习pluralsights的一些教程 . 我按照相应的步骤操作并准备好了模型,当我使用“migrate”命令时,出现了这个错误

“AssertionError:模型不能有多个自动字段。”

所以我查了一下,得到了Django的另一份文档

默认情况下,Django为每个模型提供以下字段:

id=models.AutoField(主键=True)

这是一个自动递增的主键

如果要指定自定义主键,只需指定 primary_key=在一个字段上为True。如果Django看到你 显式设置Field.primary_键,它不会添加自动id 专栏

每个模型只需要一个字段就可以使primary_key=True(或 显式声明或自动添加)

因此,根据他的解决方案,我在没有主键的表中添加了“id”列,并跳过了有主键的表。 我的“迁移”命令运行顺利

但当我尝试测试是否可以从中获取值时,它显示无效列“ID”

现在,我一直在想,如果Django隐式地创建它们,或者当我在模型中显式地创建它们时(然后使用makemigrations和migrate命令),它不应该为它创建列吗

另一种情况: 有些表已经建立了主键,我尝试过对它们进行查询,结果成功了

这让我想如果我错过了这一切之间的一步

这是我的库文件

certifi==2016.2.28
Django==1.11.3
django-mssql==1.8
django-pyodbc-azure==1.11.0.0
mysqlclient==1.3.12
PyMySQL==0.7.9
pyodbc==4.0.17
pytz==2017.2
wincertstore==0.2
很抱歉格式错误,但如果我错过了与旧系统连接的任何步骤,请提供帮助。请询问是否需要任何额外信息。谢谢

编辑:如所问,这是我的查询工作的模型

class DjangoSession(models.Model):
    session_key = models.CharField(primary_key=True, max_length=40)
    session_data = models.TextField()
    expire_date = models.DateTimeField()

    class Meta:
        managed = False
        db_table = 'django_session'
这里有一个(许多)不起作用

class table1(models.Model):
    id=models.AutoField(primary_key=True)
    col2 = models.CharField(db_column='col2', max_length=255, blank=True, null=True)  # Field name made lowercase. Field renamed to remove unsuitable characters.
    col3 = models.IntegerField(db_column='col3', blank=True, null=True)  # Field name made lowercase.
    col4 = models.CharField(max_length=250, blank=True, null=True)
    col5 = models.DateTimeField(db_column='col5')  # Field name made lowercase.

    class Meta:
        managed = True
        db_table = 'table1'
session_key变量已经在表中,因此我不需要为该表创建主键。 然而,由于阅读了各种文档,我添加了
id=models.AutoField(primary_key=True)
,我也尝试了创建id的“隐式添加”方法,但它给出了相同的结果

导致此错误的sql shell查询:

from app.models import table1
table1.objects.filter(column_name='col3')
migration.createModel函数如下所示

migrations.CreateModel(
            name='VikalpFtrFeatureCr',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('col2', models.CharField(blank=True, db_column='col2', max_length=255, null=True)),
                ('col3', models.IntegerField(blank=True, db_column='col3', null=True)),
                ('col4', models.CharField(blank=True, max_length=250, null=True)),
                ('col5', models.DateTimeField(db_column='UPDATE_DTTM')),
            ],
            options={
                'managed': False,
                'db_table': 'VIKALP_FTR_Feature_CR',
            },
        )

基本上,要使遗留数据库/表/视图正常工作,至少需要一个在整个表/视图中唯一的字段

您只需输入正确的字段类型(例如CharField、IntegerField-在我的示例中,我使用了CharField)并在元选项中输入表名,然后将managed设置为False

class YourLegacyModel(models.Model):

    id = models.CharField(db_column='unique column', primary_key=True)

    class Meta:
        db_table = 'your_table'
        managed = False

不清楚为什么会出现初始断言错误。我认为你诊断错了,采取了错误的行动。现在我们不知道到底发生了什么,很难进一步帮助你

我建议您备份应用程序的
迁移
文件夹。接下来,我们将您的应用程序称为“msapp”,并在适当的情况下替换它

首先,回滚迁移:

python manage.py migrate msapp zero
python manage.py makemigrations msapp
现在删除所有迁移文件:

rm msapp/migrations/0*.py
然后清除models.py:

rm msapp/models.py && touch msapp/models.py
使用所需表列表运行inspectdb:

python manage.py inspectdb table1 table2 ... >> msapp/models.py
运行makemigrations:

python manage.py migrate msapp zero
python manage.py makemigrations msapp
运行迁移:

python manage.py migrate
现在显示您遇到了什么问题,如果再次遇到断言错误,则显示完全回溯

更新 因此,问题是当没有主键时,Django将向模型添加一个自动创建的字段,,即使模型被标记为非托管。 问题似乎是,人们可以简单地选择一个字段并将其标记为主键,即使它不是主键。这将阻止自动插入ID字段,该字段是在
django.db.models.options
中的元类中完成的:

def _prepare():
    # ...
    if self.pk is None:
        if self.parents:
            # Promote the first parent link in lieu of adding yet another
            # field.
            field = next(six.itervalues(self.parents))
            # Look for a local field with the same name as the
            # first parent link. If a local field has already been
            # created, use it instead of promoting the parent
            already_created = [fld for fld in self.local_fields if fld.name == field.name]
            if already_created:
                field = already_created[0]
            field.primary_key = True
            self.setup_pk(field)
            if not field.remote_field.parent_link:
                warnings.warn(
                    'Add parent_link=True to %s as an implicit link is '
                    'deprecated.' % field, RemovedInDjango20Warning
                )
        else:
            auto = AutoField(verbose_name='ID', primary_key=True, auto_created=True)
            model.add_to_class('id', auto)
另一个选项是在处理这些模型时始终使用,这样就永远不会从数据库中查询“id”字段。您可以通过执行以下操作,在当前设置中测试这一点:

table1.objects.filter(column_name='col3').defer('id')
您可以在管理器中进一步抽象:

class NoPkModelManager(models.Manager):
    def get_queryset(self):
        return super(NoPkModelManager, self).get_queryset().defer('id')

class Table1(models.Model):
    objects = NoPkModelManager()
    # .. other fields and methods

在添加
自动字段
之前,您是否可以发布一个模型,以及在您将其更改为“我已将'id'列添加到没有主键的表中”之后发布的模型。在您的问题中添加
models.py
,我将与模型一起编辑问题,谢谢。看到了
托管的
元类属性中的差异吗?1.它不应该是真的,这样django就可以将id列添加到表中吗?2.在面向问题的表格上尝试了managed=False,仍然没有进展我已相应地编辑了问题。我已经创建了整个表中唯一的主键列。我之所以将managed=True,是因为我想对它执行CRUD操作。不是这样的。让managed为false,您也可以执行crud操作。
默认情况下,inspectdb创建非托管模型。也就是说,模型的元类中的managed=False告诉Django不要管理每个表的创建、修改和删除:
这是我所指的文档。但是您不想创建新表。我以为你在访问旧数据库?!是的,我正在访问遗留数据库,我现在知道Django指的是表的CRUD,而不是数据的CRUD,我将测试它并返回这里,谢谢!您好,感谢您提供了清晰的步骤,我已经按照您提供的方法进行了尝试,这是我的回溯
回溯(最近一次调用):文件“C:\Anaconda3\envs\django\lib\site packages\django\db\backends\utils.py”,第65行,在execute return self.cursor.execute(sql,params)文件中“C:\Anaconda3\envs\django\lib\site packages\sql\pyodbc\base.py”,第545行,在执行返回self.cursor.execute(sql,params)pyodbc.ProgrammingError:('42S22',“[42S22][Microsoft][ODBC sql server驱动程序][sql server]无效的列名'id'(207 SQLExecDirectW)”)
如果需要,我可以提供更多的信息,因为我是Django的新手,我很高兴