当我尝试使用以下命令为我的Django应用程序生成初始迁移时:
python manage.py makemigrations myapp
我得到了一个跟踪:
File "/myproject/.env/local/lib/python2.7/site-packages/localflavor/us/models.py", line 21, in deconstruct
name, path, args, kwargs = super(USStateField, self).deconstruct()
File "/myproject/.env/local/lib/python2.7/site-packages/localflavor/us/models.py", line 21, in deconstruct
name, path, args, kwargs = super(USStateField, self).deconstruct()
File "/myproject/.env/local/lib/python2.7/site-packages/localflavor/us/models.py", line 21, in deconstruct
name, path, args, kwargs = super(USStateField, self).deconstruct()
File "/myproject/.env/local/lib/python2.7/site-packages/localflavor/us/models.py", line 21, in deconstruct
name, path, args, kwargs = super(USStateField, self).deconstruct()
RuntimeError: maximum recursion depth exceeded while calling a Python object
我做的唯一奇怪的事情可能是因为我试图从localflavor包中对USStateField进行monkeypatch。具体来说,我需要从字段的状态列表中设置自定义状态选项,所以我正在做:
from localflavor.us import models as us_models
_USStateField = us_models.USStateField
class USStateField(_USStateField):
description = _("U.S. state (two uppercase letters)")
def __init__(self, *args, **kwargs):
kwargs['choices'] = MY_STATE_CHOICES
kwargs['max_length'] = 2
super(_USStateField, self).__init__(*args, **kwargs)
us_models.USStateField = USStateField
这在Django 1.7中完美运行,但现在在Django 1.10中给出了这个错误。有更好的方法吗?
答案 0 :(得分:1)
我发现了关于“猴子修补django模型和迁移”on github主题的一些信息 - 但它看起来并不是很有希望。
我担心django迁移的行为会使模型与猴子修补方法不兼容。当你需要处理它们时,你会在不同的地方遇到几个副作用(How to add custom migrations to external Django apps)。
如果你直接依赖localflavor
- 什么阻止你使用继承而不是猴子修补外来依赖?对于localflavor.us
中的自定义字段,您可以将fields.py
添加到自定义应用或项目中,然后使用您的代码:
from localflavor.us import models as us_models
class USStateField(us_models.USStateField):
description = _("U.S. state (two uppercase letters)")
def __init__(self, *args, **kwargs):
kwargs['choices'] = MY_STATE_CHOICES
kwargs['max_length'] = 2
super(USStateField, self).__init__(*args, **kwargs)
之后,您只需在模型中使用该模型from yourapp.fields import USStateField
。
如果您有其他依赖localfavor.us
的第三方应用程序,这使得这种方法非常复杂,因为您需要为这个小补丁重写一堆模型,我目前看到两种方式:
localflavor
并在需求中将其作为直接git URL或通过本地pypi存储库提供。localflavor
本身做出贡献,并且可以在那里传递选项 - 这避免了针对这种特定情况的猴子修补。最重要的是,在django邮件列表上开始讨论有关猴子修补和迁移的讨论可能是值得的 - 但过去有关该主题的意见是not that positive。
更新:无需仔细查看localflavor,但在这种情况下,使用它时可能只需将choices=MY_STATE_CHOICES
传递给字段 - 如果您直接依赖于该字段。尽管如此,上面提到了猴子修补和django迁移。
UPDATE2 :我今天和一位同事谈过,他告诉我apps.py
可能是猴子修补工作的地方。那里的代码在其他任何事情发生之前执行 - 也许你可以在那里拯救猴子补丁。知道它是否有效会很有趣。
UPDATE3 :我最近有一些时间,因为我很好奇,我自己尝试了apps.py
方法。我的同事是完全正确的。当您将猴子修补代码移到apps.py
迁移中时,运行而不会您要解决的错误。
这就是我apps.py
的样子:
from django.apps import AppConfig
from localflavor.us import models as us_models
_USStateField = us_models.USStateField
MY_STATE_CHOICES = [('foo', 'BAR',)]
class USStateField(_USStateField):
description = "U.S. state (two uppercase letters)"
def __init__(self, *args, **kwargs):
kwargs['choices'] = MY_STATE_CHOICES
kwargs['max_length'] = 2
super(_USStateField, self).__init__(*args, **kwargs)
us_models.USStateField = USStateField
class FoobarConfig(AppConfig):
name = 'foobar'