Tro*_*roy 25 django django-south
回到South迁移的时代,如果你想创建一个扩展Django字段功能的自定义模型字段,你可以告诉South使用父类的内省规则,如下所示:
from south.modelsinspector import add_introspection_rules
add_introspection_rules([], ["^myapp\.stuff\.fields\.SomeNewField"])
Run Code Online (Sandbox Code Playgroud)
既然迁移已经转移到Django,那么上面的非南方是否相同?是不是还需要一个等价物,或者新的迁移内容是否足够巧妙,可以自行解决?
正如Phillip在评论中提到的那样,deconstruct() 是在django迁移中处理自定义字段的官方方式.
继续完成澄清请求......似乎已经有几个代码示例用于处理两者.例如,此摘录(用于处理on参数ExclusiveBooleanField)取自django-exclusivebooleanfield:
from django.db import models, transaction
from django.db.models import Q
from six import string_types
from six.moves import reduce
try:
transaction_context = transaction.atomic
except AttributeError:
transaction_context = transaction.commit_on_success
class ExclusiveBooleanField(models.BooleanField):
"""
Usage:
class MyModel(models.Model):
the_one = ExclusiveBooleanField()
class MyModel(models.Model):
field_1 = ForeignKey()
field_2 = CharField()
the_one = ExclusiveBooleanField(on=('field_1', 'field_2'))
# `on` is a bit like a unique constraint, value of field
# is only exclusive for rows with same value of the on fields
"""
def __init__(self, on=None, *args, **kwargs):
if isinstance(on, string_types):
on = (on, )
self._on_fields = on or ()
super(ExclusiveBooleanField, self).__init__(*args, **kwargs)
def contribute_to_class(self, cls, name):
super(ExclusiveBooleanField, self).contribute_to_class(cls, name)
models.signals.class_prepared.connect(self._replace_save, sender=cls)
def deconstruct(self):
"""
to support Django 1.7 migrations, see also the add_introspection_rules
section at bottom of this file for South + earlier Django versions
"""
name, path, args, kwargs = super(
ExclusiveBooleanField, self).deconstruct()
if self._on_fields:
kwargs['on'] = self._on_fields
return name, path, args, kwargs
def _replace_save(self, sender, **kwargs):
old_save = sender.save
field_name = self.name
on_fields = self._on_fields
def new_save(self, *args, **kwargs):
def reducer(left, right):
return left & Q(**{right: getattr(self, right)})
with transaction_context():
if getattr(self, field_name) is True:
f_args = reduce(reducer, on_fields, Q())
u_args = {field_name: False}
sender._default_manager.filter(f_args).update(**u_args)
old_save(self, *args, **kwargs)
new_save.alters_data = True
sender.save = new_save
try:
from south.modelsinspector import add_introspection_rules
add_introspection_rules(
rules=[
(
(ExclusiveBooleanField,),
[],
{"on": ["_on_fields", {"default": tuple()}]},
)
],
patterns=[
'exclusivebooleanfield\.fields\.ExclusiveBooleanField',
]
)
except ImportError:
pass
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2268 次 |
| 最近记录: |