Esempio n. 1
0
 def _fill_related_objects_cache(self):
     cache = SortedDict()
     parent_list = self.get_parent_list()
     for parent in self.parents:
         for obj, model in parent._meta.get_all_related_objects_with_model(
         ):
             if (obj.field.creation_counter < 0 or obj.field.rel.parent_link
                 ) and obj.model not in parent_list:
                 continue
             if not model:
                 cache[obj] = parent
             else:
                 cache[obj] = model
     for klass in get_models(include_auto_created=True):
         for f in klass._meta.local_fields:
             if f.rel and not isinstance(f.rel.to,
                                         str) and self == f.rel.to._meta:
                 cache[RelatedObject(f.rel.to, klass, f)] = None
     self._related_objects_cache = cache
Esempio n. 2
0
 def _fill_related_many_to_many_cache(self):
     cache = SortedDict()
     parent_list = self.get_parent_list()
     for parent in self.parents:
         for obj, model in parent._meta.get_all_related_m2m_objects_with_model(
         ):
             if obj.field.creation_counter < 0 and obj.model not in parent_list:
                 continue
             if not model:
                 cache[obj] = parent
             else:
                 cache[obj] = model
     for klass in get_models(only_installed=False):
         for f in klass._meta.local_many_to_many:
             if f.rel and not isinstance(
                     f.rel.to, basestring) and self == f.rel.to._meta:
                 cache[RelatedObject(f.rel.to, klass, f)] = None
     if app_cache_ready():
         self._related_many_to_many_cache = cache
     return cache
Esempio n. 3
0
 def _fill_related_many_to_many_cache(self):
     from django.db.models.loading import get_models, app_cache_ready
     from django.db.models.related import RelatedObject
     from django.utils.datastructures import SortedDict
     cache = SortedDict()
     parent_list = self.get_parent_list()
     for parent in self.parents:
         for obj, model in parent._meta.get_all_related_m2m_objects_with_model():
             if obj.field.creation_counter < 0 and obj.model not in parent_list:
                 continue
             if not model:
                 cache[obj] = parent
             else:
                 cache[obj] = model
     for klass in get_models():
         for f in klass._meta.local_many_to_many:
             if f.rel and not isinstance(f.rel.to, str) and self == f.rel.to._meta:
                 cache[RelatedObject(f.rel.to, klass, f)] = None
     if app_cache_ready():
         self._related_many_to_many_cache = cache
     return cache
Esempio n. 4
0
 def do_related_class(self, other, cls):
     self.set_attributes_from_rel()
     self.related = RelatedObject(other, cls, self)
     if not cls._meta.abstract:
         self.contribute_to_related_class(other, self.related)
Esempio n. 5
0
    def introspect_class(self, cls):
        bits = self.field.split(".")

        if len(bits) < 2:
            raise ValueError("Illegal path to foreign field")

        foreign_field = None

        related_models_chain = [cls]
        related_names_chain = []

        for bit in bits[:-1]:
            meta = related_models_chain[-1]._meta

            try:
                foreign_field = meta.get_field(bit)
            except models.FieldDoesNotExist:
                raise ValueError("Field '%s' does not exist" % bit)

            if isinstance(foreign_field, models.ForeignKey):
                if isinstance(foreign_field.rel.to, basestring):
                    raise ValueError(
                        "Model with name '%s' must be class instance not string"
                        % foreign_field.rel.to)

                related_name = foreign_field.rel.related_name
                if not related_name:
                    related_name = RelatedObject(
                        foreign_field.rel.to, related_models_chain[-1],
                        foreign_field).get_accessor_name()

                related_models_chain.append(foreign_field.rel.to)
                related_names_chain.append(related_name)
            else:
                raise ValueError("Foreign fields in path must be ForeignField"
                                 "instances except last. Got %s" %
                                 foreign_field.__name__)

        native = self.native
        if not native:
            field_name = bits[-1]
            try:
                native = deepcopy(
                    related_models_chain[-1]._meta.get_field(field_name))
                native.creation_counter = models.Field.creation_counter
                models.Field.creation_counter += 1
            except models.FieldDoesNotExist:
                raise ValueError("Leaf field '%s' does not exist" % field_name)

        def get_root_instances(instance, chain):
            attr = getattr(instance, chain.pop()).all()

            if chain:
                for obj in attr:
                    for inst in get_root_instances(obj, chain):
                        yield inst
            else:
                for obj in attr:
                    yield obj

        def get_leaf_instance(instance, chain):
            for bit in chain:
                instance = getattr(instance, bit)

            return instance

        self.internal_init(
            native=native,
            trigger=[
                dict(on=(models.signals.post_save, models.signals.post_delete),
                     sender_model=related_models_chain[-1],
                     do=lambda holder, foreign, signal: getattr(
                         foreign, bits[-1]),
                     field_holder_getter=lambda foreign: get_root_instances(
                         foreign, related_names_chain[:])),
                dict(
                    on=models.signals.pre_save,
                    sender_model=related_models_chain[0],
                    do=lambda holder, _, signal: get_leaf_instance(
                        holder, bits[:]),
                    commit=False,  # to prevent recursion `save` method call
                )
            ],
            update_method=dict(queryset=lambda holder: get_leaf_instance(
                holder, bits[:-1])  #FIXME: rename queryset
                               ))
Esempio n. 6
0
 def do_related_class(self, other, cls):
     self.set_attributes_from_rel()
     related = RelatedObject(other, cls, self)
     self.contribute_to_related_class(other, related)
Esempio n. 7
0
 def post_through_setup(self, cls):
     self.rel.to = self.through._meta.get_field("tag").rel.to
     self.related = RelatedObject(self.through, cls, self)