首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >是否有Django 1.7+替代South的add_introspection_rules()?

是否有Django 1.7+替代South的add_introspection_rules()?
EN

Stack Overflow用户
提问于 2015-04-10 00:30:36
回答 1查看 2.8K关注 0票数 25

回到南方迁移时代,如果您想要创建一个扩展Django字段功能的自定义模型字段,您可以告诉South使用父类的内省规则,如下所示:

代码语言:javascript
复制
from south.modelsinspector import add_introspection_rules
add_introspection_rules([], ["^myapp\.stuff\.fields\.SomeNewField"])

现在迁移到Django,是否有一个非南方的等价物?是否还需要一种类似的工具,或者新的迁移工具是否足够聪明,可以自己解决呢?

EN

回答 1

Stack Overflow用户

发布于 2015-07-01 12:12:09

正如菲利普在评论中提到的,deconstruct()是django迁移中的official way to handle custom fields

继续完成澄清请求..。似乎已经有几个代码示例是用来处理这两种代码的。例如,这段摘录(用于处理on参数用于ExclusiveBooleanField)取自django-exclusivebooleanfield

代码语言:javascript
复制
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
票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29551367

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档