Ticket #7270: django_select_related_onetoone_r10448.patch

File django_select_related_onetoone_r10448.patch, 6.9 KB (added by aiev, 6 years ago)

adaptation to the r10448

  • db/models/sql/query.py

     
    13911391            self.fill_related_selections(f.rel.to._meta, alias, cur_depth + 1,
    13921392                    used, next, restricted, new_nullable, dupe_set, avoid)
    13931393
     1394        # Do reverse columns, but only the ones in the requested list.
     1395        if restricted:
     1396            related_fields = [(x.field, x.model) for x in opts.get_all_related_objects() if x.field.unique]
     1397            for f, model in related_fields:
     1398                if f.rel.parent_link or f.related_query_name() not in requested:
     1399                    continue
     1400                table = model._meta.db_table
     1401                if nullable or f.null:
     1402                    promote = True
     1403                else:
     1404                    promote = False
     1405                alias = self.join((root_alias, table, f.rel.get_related_field().column,
     1406                        f.column), exclusions=used,
     1407                        promote=promote, reuse=used)
     1408                used.add(alias)
     1409 
     1410                self.related_select_cols.extend([(alias, f2.column)
     1411                        for f2 in model._meta.fields])
     1412                self.related_select_fields.extend(model._meta.fields)
     1413 
     1414                next = requested.get(f.related_query_name(), {})
     1415                #if nullable is not None:
     1416                #    new_nullable = nullable
     1417                #else:
     1418                #    new_nullable = f.null
     1419                if f.null is not None:
     1420                    new_nullable = f.null
     1421                else:
     1422                    new_nullable = None
     1423                self.fill_related_selections(model._meta, table, cur_depth + 1,
     1424                        used, next, restricted, new_nullable)
     1425
    13941426    def add_aggregate(self, aggregate, model, alias, is_summary):
    13951427        """
    13961428        Adds a single aggregate expression to the Query
  • db/models/options.py

     
    4747        self.proxy_for_model = None
    4848        self.parents = SortedDict()
    4949        self.duplicate_targets = {}
     50        self.reverse_field_cache = {}
    5051
    5152        # To handle various inheritance situations, we need to track where
    5253        # managers came from (concrete or abstract base classes).
  • db/models/fields/related.py

     
     1import types
    12from django.db import connection, transaction
    23from django.db.backends import util
    34from django.db.models import signals, get_model
     
    178179    # SingleRelatedObjectDescriptor instance.
    179180    def __init__(self, related):
    180181        self.related = related
    181         self.cache_name = '_%s_cache' % related.get_accessor_name()
     182        #self.cache_name = '_%s_cache' % related.get_accessor_name()
     183        cache_name = '_%s_cache' % related.field.related_query_name()
     184        # Contribute to the parent model for later lookup.
     185        related.parent_model._meta.reverse_field_cache[related.field.related_query_name()] = cache_name
     186        self.cache_name = cache_name
    182187
    183188    def __get__(self, instance, instance_type=None):
    184189        if instance is None:
     
    291296    # attribute is a ForeignRelatedObjectsDescriptor instance.
    292297    def __init__(self, related):
    293298        self.related = related   # RelatedObject instance
     299        if related.field.unique:
     300            cache_name = '_%s_cache' % related.field.related_query_name()
     301            # Contribute to the parent model for later lookup.
     302            related.parent_model._meta.reverse_field_cache[related.field.related_query_name()] = cache_name
     303            self.cache_name = cache_name
    294304
    295305    def __get__(self, instance, instance_type=None):
    296306        if instance is None:
     
    309319        if self.related.field.null:
    310320            manager.clear()
    311321        manager.add(*value)
     322        # Cache the value specially if from a unique set.
     323        if self.related.field.unique:
     324            self.cache_name = value
    312325
    313326    def delete_manager(self, instance):
    314327        """
     
    325338        """
    326339        rel_field = self.related.field
    327340        rel_model = self.related.model
     341        if rel_field.unique:
     342            cache_name = self.cache_name
    328343
    329344        class RelatedManager(superclass):
    330345            def get_query_set(self):
     
    369384                        obj.save()
    370385                clear.alters_data = True
    371386
     387            if rel_field.unique:
     388                def all(self):
     389                    try:
     390                        result = getattr(instance, cache_name)
     391                        if isinstance(result, (types.TupleType, types.ListType)):
     392                            return result
     393                        else:
     394                            return [result]
     395                    except AttributeError, ae:
     396                        return superclass.get_query_set(self)
     397
    372398        manager = RelatedManager()
    373399        attname = rel_field.rel.get_related_field().name
    374400        manager.core_filters = {'%s__%s' % (rel_field.name, attname):
  • db/models/query.py

     
    937937            obj = klass(*fields)
    938938
    939939    index_end = index_start + field_count + offset
     940
    940941    for f in klass._meta.fields:
    941942        if not select_related_descend(f, restricted, requested):
    942943            continue
     
    950951            rel_obj, index_end = cached_row
    951952            if obj is not None:
    952953                setattr(obj, f.get_cache_name(), rel_obj)
     954
     955            # Do the reverse cache if the field is a unique relation.
     956            if f.unique:
     957                cache_var_name = rel_obj._meta.reverse_field_cache[f.related_query_name()]
     958                setattr(rel_obj, cache_var_name, obj)
     959
     960    if restricted:
     961        related_fields = [(x.field, x.model) for x in klass._meta.get_all_related_objects() if x.field.unique]
     962        for f, model in related_fields:
     963            if f.related_query_name() not in requested:
     964                continue
     965
     966            next = requested.get(f.related_query_name(), {})
     967            cached_row = get_cached_row(model, row, index_end, max_depth,
     968                    cur_depth+1, next)
     969            if cached_row:
     970                rel_obj, index_end = cached_row
     971                if rel_obj is not None:
     972                    setattr(rel_obj, f.get_cache_name(), obj)
     973
     974                # Now do the reverse cache.
     975                cache_var_name = obj._meta.reverse_field_cache[f.related_query_name()]
     976                setattr(obj, cache_var_name, rel_obj)
     977
    953978    return obj, index_end
    954979
    955980def delete_objects(seen_objs):
Back to Top