def _add_to_load_related(self, field, *related_fields): rf = unique_tuple((v for v in related_fields)) # we need to copy the related dictionary including its values if self.select_related: d = dict(((k, tuple(v)) for k, v in self.select_related.items())) else: d = {} self.data['select_related'] = d if field.name in d: d[field.name] = unique_tuple(d[field.name], rf) else: d[field.name] = rf return self
def load_only(self, *fields): '''This is provides a :ref:`performance boost <increase-performance>` in cases when you need to load a subset of fields of your model. The boost achieved is less than the one obtained when using :meth:`Query.load_related`, since it does not reduce the number of requests to the database. However, it can save you lots of bandwidth when excluding data intensive fields you don't need. ''' q = self._clone() new_fields = [] for field in fields: if JSPLITTER in field: bits = field.split(JSPLITTER) related = self._get_related_field(bits[0]) if related: q._add_to_load_related(related, JSPLITTER.join(bits[1:])) continue new_fields.append(field) if fields and not new_fields: # if we added a field to the load_related list and not fields are # are left we add the primary key so that other firls are not # loaded. new_fields.append(self._meta.pkname()) fs = unique_tuple(q.fields, new_fields) q.data['fields'] = fs if fs else None return q
def __init__( self, model, fields, app_label=None, modelkey=None, name=None, register=True, pkname=None, ordering=None, attributes=None, abstract=False, **kwargs ): self.model = model self.abstract = abstract self.attributes = unique_tuple(attributes or ()) self.dfields = {} self.fields = [] self.scalarfields = [] self.indices = [] self.multifields = [] self.related = {} self.manytomany = [] self.model._meta = self self.app_label = make_app_label(model, app_label) self.name = (name or model.__name__).lower() if not modelkey: if self.app_label: modelkey = "{0}.{1}".format(self.app_label, self.name) else: modelkey = self.name self.modelkey = modelkey if not self.abstract and register: hashmodel(model) # # Check if PK field exists pk = None pkname = pkname or "id" for name in fields: field = fields[name] if field.primary_key: if pk is not None: raise FieldError("Primary key already available %s." % name) pk = field pkname = name if pk is None and not self.abstract: # ID field not available, create one pk = AutoIdField(primary_key=True) fields.pop(pkname, None) for name, field in fields.items(): field.register_with_model(name, model) if pk is not None: pk.register_with_model(pkname, model) self.ordering = None if ordering: self.ordering = self.get_sorting(ordering, ImproperlyConfigured)
def dont_load(self, *fields): '''Works like :meth:`load_only` to provides a :ref:`performance boost <increase-performance>` in cases when you need to load all fields except a subset specified by *fields*. ''' q = self._clone() fs = unique_tuple(q.exclude_fields, fields) q.exclude_fields = fs if fs else None return q
def __init__(self, model, fields, app_label=None, modelkey=None, name=None, register=True, pkname=None, ordering=None, attributes=None, abstract=False, **kwargs): self.model = model self.abstract = abstract self.attributes = unique_tuple(attributes or ()) self.dfields = {} self.fields = [] self.scalarfields = [] self.indices = [] self.multifields = [] self.related = {} self.manytomany = [] self.model._meta = self self.app_label = make_app_label(model, app_label) self.name = (name or model.__name__).lower() if not modelkey: if self.app_label: modelkey = '{0}.{1}'.format(self.app_label, self.name) else: modelkey = self.name self.modelkey = modelkey if not self.abstract and register: hashmodel(model) # # Check if PK field exists pk = None pkname = pkname or 'id' for name in fields: field = fields[name] if field.primary_key: if pk is not None: raise FieldError("Primary key already available %s." % name) pk = field pkname = name if pk is None and not self.abstract: # ID field not available, create one pk = AutoIdField(primary_key=True) fields.pop(pkname, None) for name, field in fields.items(): field.register_with_model(name, model) if pk is not None: pk.register_with_model(pkname, model) self.ordering = None if ordering: self.ordering = self.get_sorting(ordering, ImproperlyConfigured)
def _items(self, slic): meta = self.meta get = self.queryelem._get_field fields_attributes = None pkname_tuple = (meta.pk.name,) if get: raise QuerySetError('Not implemented') else: fields = self.queryelem.fields or None if fields: fields = unique_tuple(fields, self.queryelem.select_related or ()) if fields == pkname_tuple: fields_attributes = fields elif fields: fields, fields_attributes = meta.backend_fields(fields) query = self.find(fields=fields_attributes) data = self.backend.build(query, meta, fields, fields_attributes) return self.backend.objects_from_db(meta, data)
def _items(self, slic): # Unwind the database query by creating a list of arguments for # the load_query lua script backend = self.backend meta = self.meta name = '' order = () start, stop = self.get_redis_slice(slic) if self.queryelem.ordering: order = self.order(self.queryelem.ordering) elif meta.ordering: name = 'DESC' if meta.ordering.desc else 'ASC' elif start or stop is not None: order = self.order(meta.get_sorting(meta.pkname())) # Wen using the sort algorithm redis requires the number of element # not the stop index if order: name = 'explicit' N = self.execute_query() if stop is None: stop = N elif stop < 0: stop += N if start < 0: start += N stop -= start elif stop is None: stop = -1 get = self.queryelem._get_field fields_attributes = None pkname_tuple = (meta.pk.name, ) # if the get_field is available, we only load that field if get: if slic: raise QuerySetError('Cannot slice a queryset in conjunction ' 'with get_field. Use load_only instead.') if get == meta.pk.name: fields_attributes = fields = pkname_tuple else: fields, fields_attributes = meta.backend_fields((get, )) else: fields = self.queryelem.fields or None if fields: fields = unique_tuple(fields, self.queryelem.select_related or ()) if fields == pkname_tuple: fields_attributes = fields elif fields: fields, fields_attributes = meta.backend_fields(fields) else: fields_attributes = () options = { 'ordering': name, 'order': order, 'start': start, 'stop': stop, 'fields': fields_attributes, 'related': dict(self.related_lua_args()), 'get': get } joptions = json.dumps(options) options.update({ 'fields': fields, 'fields_attributes': fields_attributes }) return backend.odmrun(backend.client, 'load', meta, (self.query_key, ), self.meta_info, joptions, **options)
def _items(self, slic): # Unwind the database query by creating a list of arguments for # the load_query lua script backend = self.backend meta = self.meta name = '' order = () start, stop = self.get_redis_slice(slic) if self.queryelem.ordering: order = self.order(self.queryelem.ordering) elif meta.ordering: name = 'DESC' if meta.ordering.desc else 'ASC' elif start or stop is not None: order = self.order(meta.get_sorting(meta.pkname())) # Wen using the sort algorithm redis requires the number of element # not the stop index if order: name = 'explicit' N = self.execute_query() if stop is None: stop = N elif stop < 0: stop += N if start < 0: start += N stop -= start elif stop is None: stop = -1 get = self.queryelem._get_field fields_attributes = None pkname_tuple = (meta.pk.name,) # if the get_field is available, we only load that field if get: if slic: raise QuerySetError('Cannot slice a queryset in conjunction ' 'with get_field. Use load_only instead.') if get == meta.pk.name: fields_attributes = fields = pkname_tuple else: fields, fields_attributes = meta.backend_fields((get,)) else: fields = self.queryelem.fields or None if fields: fields = unique_tuple(fields, self.queryelem.select_related or ()) if fields == pkname_tuple: fields_attributes = fields elif fields: fields, fields_attributes = meta.backend_fields(fields) else: fields_attributes = () options = {'ordering': name, 'order': order, 'start': start, 'stop': stop, 'fields': fields_attributes, 'related': dict(self.related_lua_args()), 'get': get} joptions = json.dumps(options) options.update({'fields': fields, 'fields_attributes': fields_attributes}) return backend.odmrun(backend.client, 'load', meta, (self.query_key,), self.meta_info, joptions, **options)