也许我已经筋疲力尽而且看不到简单的东西,但是在Django 1.9.7中,在进行迁移时我发现了一些奇怪的东西, 我正在寻找解释。
在Run apps
中获取模型类(它是(django.db.migrations.state.StateApps
)在RunPython操作中,对于存在的字段,我有AttributeError
。
我的模特:
class Weight(models.Model):
INF = 2**31-1
minimum = models.PositiveIntegerField()
maximum = models.PositiveIntegerField()
carrier = models.ForeignKey(Carrier)
class Meta:
ordering = ['carrier__name', 'minimum']
在从RunPython
运行的迁移方法中,我有:
Weight = apps.get_model('calc.Weight')
然后有异常,但只适用于某些领域。
来自调试(由RunPython运行的内部方法):
>>> Weight.maximum
Traceback (most recent call last):
File "<pudb command line>", line 1, in <module>
AttributeError: type object 'Weight' has no attribute 'maximum'
>>> Weight.minimum
Traceback (most recent call last):
File "<pudb command line>", line 1, in <module>
AttributeError: type object 'Weight' has no attribute 'minimum'
>>> Weight.INF
Traceback (most recent call last):
File "<pudb command line>", line 1, in <module>
AttributeError: type object 'Weight' has no attribute 'INF'
但:
>>> Weight.carrier
<django.db.models.fields.related_descriptors.ForwardManyToOneDescriptor object at 0x7f8dcca692d0>
>>> Weight._meta.fields
(<django.db.models.fields.AutoField: id>, <django.db.models.fields.PositiveIntegerField: minimum>,
<django.db.models.fields.PositiveIntegerField: maximum>, <django.db.models.fields.related.ForeignKey: carrier>)
type(Weight)
<class 'django.db.models.base.ModelBase'>
所以某种方式只有载体字段可用,为什么?
更新: 我的迁移文件是:
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
def add_weights(app, *args):
Carrier = app.get_model('calc.Carrier')
Weight = app.get_model('calc.Weight')
# import pudb;pu.db
carrier_obj = Carrier.objects.get(name='MainCarrier')
Weight.objects.create(carrier=carrier_obj, minimum=1, maximum=400) # OK, yes it works within `create`
Weight.objects.create(carrier=carrier_obj, minimum=401, maximum=800) # OK
Weight.objects.create(carrier=carrier_obj, minimum=800, maximum=Weight.INF) # here is AttributeError
class Migration(migrations.Migration):
dependencies = [
('calc', '0012_auto_20170622_1310'),
]
operations = [
migrations.CreateModel(
name='Weight',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('minimum', models.PositiveIntegerField()),
('maximum', models.PositiveIntegerField()),
('carrier', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='calc.Carrier')),
],
options={
'ordering': ['carrier__name', 'minimum'],
},
),
migrations.RunPython(add_weights)
]
顺便说一句:毕竟我可以将INF放在课堂外面,并有解决方法,但知识发生的事情对我来说更重要。
答案 0 :(得分:1)
void QIODevice::readyRead()
来电将返回app.get_model(...)
个实例,而非django.db.models.base.ModelBase
模型,这就是您无法看到Weight
的原因。
使用替代名称导入它(因此它不会遮挡您的INF
变量),您将能够使用它:
Weight
答案 1 :(得分:0)
我认为此错误的原因是数据库更改和状态更改具有不同的方面。文档说
一种高度专业化的操作,可让您混合和匹配数据库(更改模式)和状态(自动检测器供电)方面的操作。
它接受两个操作列表,当要求应用状态时将使用状态列表,而当要求将更改应用于数据库时将使用数据库列表。除非您非常确定自己知道自己在做什么,否则请不要使用此操作。
https://docs.djangoproject.com/en/1.9/ref/migration-operations/#separatedatabaseandstate
以下情况的适当更新;
operations = [
migrations.SeparateDatabaseAndState(
[
migrations.CreateModel(
name='Weight',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('minimum', models.PositiveIntegerField()),
('maximum', models.PositiveIntegerField()),
('carrier', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='calc.Carrier')),
],
options={
'ordering': ['carrier__name', 'minimum'],
},
)
],
[
migrations.RunPython(add_weights)
]
)
]
但是,我会在单独的文件中进行这2次迁移,因为它们的用途不同,而且在将来进行还原可能会很麻烦。
答案 2 :(得分:0)
仅供参考, 我通过放置非模型字段和自定义方法解决了我的问题 进入新类的定义
一般:
class MyModelInterface(object): ..
class MyModel(models.Model, MyModelInterface): ..
其中 MyModelInterface
是模型的 mixin,但如果需要,我可以单独使用它。
我发现它是 Django 模型的一个好习惯, 所以在迁移等特殊需求时,我可以直接评估接口类。 此外,避免使用具有许多自定义方法、属性、...
的非常长的模型主体也很有帮助