Django 中的列名'id'无效



因此,我以不同的方式使用Django模型,我在MS SQL Server中有现有表,我想访问它们以供我的应用程序。我一直在遵循Pluralsights的一些教程,还https://docs.djangoproject.com/en/1.11/howto/legacy-databases/。我相应地遵循这些步骤,并准备好了我的模型,当我使用"迁移"命令时,我得到了此错误

"断言:一个模型不能超过一个自动场。"

所以我抬头看,并得到了Django的另一个文档

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

id = models.autofield(primary_key = true)

这是一个自动收入的主键。

如果您想指定自定义主键,只需指定 primary_key = true在您的一个字段上。如果Django看到您已经 显式设置字段。primary_key,它不会添加自动ID 列。

每个模型都需要一个字段才能具有primary_key = true(要么 明确声明或自动添加)。

因此,通过他的解决方案,我在没有主钥匙并跳过的表中添加了" ID"列。我的"迁移"命令工作平稳。

但是,当我试图测试是否可以从中获得值时,它显示了无效的列'id'

现在,我一直在思考自己,如果django隐式创建它们,或者当我在模型中明确创建它(然后使用makemigrations and Migrate命令),是否应该为其创建列?

另一种情况:有一些已经建立的主键的表,我尝试了查询,并且奏效了。

这只是让我想,如果我错过了所有这些之间的一步,

这是我的lib文件

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')

迁移。createModel函数为belows

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',
            },
        )

目前尚不清楚为什么要出现初始断言错误。我认为您错误地诊断出来并采取了错误的措施。现在我们无法分辨到真正发生了什么,很难进一步帮助您。

我建议您备份应用程序的migrations文件夹。让我们将您的应用程序称为" msapp",以便在适当的情况下替换。

首先,回滚迁移:

python manage.py migrate msapp zero

现在删除所有迁移文件:

rm msapp/migrations/0*.py

然后清除模型。Py:

rm msapp/models.py && touch msapp/models.py

使用通缉表列表运行InspectDB:

python manage.py inspectdb table1 table2 ... >> msapp/models.py

运行makemigrations:

python manage.py makemigrations msapp

运行迁移:

python manage.py migrate

现在显示您遇到的问题,如果再次遇到断言错误,则完整的追溯

更新

因此,问题在于,如果没有主键,即使模型被标记为未管理的,Django将在模型中添加自动创建的字段。共识似乎是,即使不是一个,也可以简单地选择一个字段并将其标记为主键。这将阻止自动插入的ID字段,该字段是在django.db.models.options中的Meta类中完成的:

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

基本上要获得旧数据库/表/视图,您至少需要一个在整个表/视图中唯一的字段。

您只需要放置正确的字段类型(例如Charfield,Integerfield-在我的示例中,我使用了Charfield),并将其放入Meta选项。

class YourLegacyModel(models.Model):
    id = models.CharField(db_column='unique column', primary_key=True)
    class Meta:
        db_table = 'your_table'
        managed = False

最新更新