因此,我以不同的方式使用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