Django

Code

Changeset 7498

Show
Ignore:
Timestamp:
04/28/08 09:08:46 (2 months ago)
Author:
jbronn
Message:

gis: Merged revisions 7485-7491,7493-7497 via svnmerge from trunk.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/branches/gis

    • Property svnmerge-integrated changed from /django/trunk:1-7481 to /django/trunk:1-7497
  • django/branches/gis/django/contrib/admin/views/main.py

    r7482 r7498  
    717717                        break 
    718718 
    719         # Calculate lookup_order_field. 
    720         # If the order-by field is a field with a relationship, order by the 
    721         # value in the related table. 
    722         lookup_order_field = self.order_field 
    723         try: 
    724             f = self.lookup_opts.get_field(self.order_field, many_to_many=False) 
    725         except models.FieldDoesNotExist: 
    726             pass 
    727         else: 
    728             if isinstance(f.rel, models.OneToOneRel): 
    729                 # For OneToOneFields, don't try to order by the related object's ordering criteria. 
    730                 pass 
    731             elif isinstance(f.rel, models.ManyToOneRel): 
    732                 rel_ordering = f.rel.to._meta.ordering and f.rel.to._meta.ordering[0] or f.rel.to._meta.pk.column 
    733                 lookup_order_field = '%s.%s' % (f.rel.to._meta.db_table, rel_ordering) 
    734  
    735719        # Set ordering. 
    736         qs = qs.order_by((self.order_type == 'desc' and '-' or '') + lookup_order_field) 
     720        if self.order_field: 
     721            qs = qs.order_by('%s%s' % ((self.order_type == 'desc' and '-' or ''), self.order_field)) 
    737722 
    738723        # Apply keyword searches. 
  • django/branches/gis/django/db/backends/__init__.py

    r7482 r7498  
    5252    uses_custom_query_class = False 
    5353    empty_fetchmany_value = [] 
     54    update_can_self_select = True 
    5455 
    5556class BaseDatabaseOperations(object): 
  • django/branches/gis/django/db/backends/mysql/base.py

    r7482 r7498  
    6464    inline_fk_references = False 
    6565    empty_fetchmany_value = () 
     66    update_can_self_select = False 
    6667 
    6768class DatabaseOperations(BaseDatabaseOperations): 
  • django/branches/gis/django/db/backends/mysql_old/base.py

    r7482 r7498  
    6868    inline_fk_references = False 
    6969    empty_fetchmany_value = () 
     70    update_can_self_select = False 
    7071 
    7172class DatabaseOperations(BaseDatabaseOperations): 
  • django/branches/gis/django/db/models/fields/__init__.py

    r7482 r7498  
    1010from django.db import get_creation_module 
    1111from django.db.models import signals 
     12from django.db.models.query_utils import QueryWrapper 
    1213from django.dispatch import dispatcher 
    1314from django.conf import settings 
     
    227228    def get_db_prep_lookup(self, lookup_type, value): 
    228229        "Returns field's value prepared for database lookup." 
     230        if hasattr(value, 'as_sql'): 
     231            sql, params = value.as_sql() 
     232            return QueryWrapper(('(%s)' % sql), params) 
    229233        if lookup_type in ('exact', 'regex', 'iregex', 'gt', 'gte', 'lt', 'lte', 'month', 'day', 'search'): 
    230234            return [value] 
  • django/branches/gis/django/db/models/query.py

    r7482 r7498  
    285285        query.add_update_values(kwargs) 
    286286        query.execute_sql(None) 
     287        transaction.commit_unless_managed() 
    287288        self._result_cache = None 
    288289    update.alters_data = True 
     
    496497        # QuerySet.clone() will also set up the _fields attribute with the 
    497498        # names of the model fields to select. 
    498  
    499     def __iter__(self): 
    500         return self.iterator() 
    501499 
    502500    def iterator(self): 
  • django/branches/gis/django/db/models/sql/constants.py

    r7482 r7498  
    2929SINGLE = 'single' 
    3030 
    31 ORDER_PATTERN = re.compile(r'\?|[-+]?\w+$') 
     31ORDER_PATTERN = re.compile(r'\?|[-+]?[.\w]+$') 
    3232ORDER_DIR = { 
    3333    'ASC': ('ASC', 'DESC'), 
  • django/branches/gis/django/db/models/sql/query.py

    r7482 r7498  
    896896        (filter_string, value). E.g. ('name__contains', 'fred') 
    897897 
    898         If 'negate' is True, this is an exclude() filter. If 'trim' is True, we 
    899         automatically trim the final join group (used internally when 
    900         constructing nested queries). 
     898        If 'negate' is True, this is an exclude() filter. It's important to 
     899        note that this method does not negate anything in the where-clause 
     900        object when inserting the filter constraints. This is because negated 
     901        filters often require multiple calls to add_filter() and the negation 
     902        should only happen once. So the caller is responsible for this (the 
     903        caller will normally be add_q(), so that as an example). 
     904 
     905        If 'trim' is True, we automatically trim the final join group (used 
     906        internally when constructing nested queries). 
    901907 
    902908        If 'can_reuse' is a set, we are processing a component of a 
     
    10021008        self.where.add((alias, col, field, lookup_type, value), connector) 
    10031009        if negate: 
    1004             self.where.negate() 
    10051010            for alias in join_list: 
    10061011                self.promote_alias(alias) 
     
    10401045                self.add_q(child, used_aliases) 
    10411046                self.where.end_subtree() 
    1042                 if q_object.negated: 
    1043                     self.where.children[-1].negate() 
    10441047            else: 
    10451048                self.add_filter(child, connector, q_object.negated, 
    10461049                        can_reuse=used_aliases) 
    10471050            connector = q_object.connector 
     1051        if q_object.negated: 
     1052            self.where.negate() 
    10481053        if subtree: 
    10491054            self.where.end_subtree() 
  • django/branches/gis/django/db/models/sql/subqueries.py

    r7482 r7498  
    9696    def _setup_query(self): 
    9797        """ 
    98         Runs on initialisation and after cloning. Any attributes that would 
     98        Runs on initialization and after cloning. Any attributes that would 
    9999        normally be set in __init__ should go in here, instead, so that they 
    100100        are also set up after a clone() call. 
     
    160160        query = self.clone(klass=Query) 
    161161        query.bump_prefix() 
    162         query.select = [] 
    163162        query.extra_select = {} 
    164         query.add_fields([query.model._meta.pk.name]) 
     163        first_table = query.tables[0] 
     164        if query.alias_refcount[first_table] == 1: 
     165            # We can remove one table from the inner query. 
     166            query.unref_alias(first_table) 
     167            for i in xrange(1, len(query.tables)): 
     168                table = query.tables[i] 
     169                if query.alias_refcount[table]: 
     170                    break 
     171            join_info = query.alias_map[table] 
     172            query.select = [(join_info[RHS_ALIAS], join_info[RHS_JOIN_COL])] 
     173            must_pre_select = False 
     174        else: 
     175            query.select = [] 
     176            query.add_fields([query.model._meta.pk.name]) 
     177            must_pre_select = not self.connection.features.update_can_self_select 
    165178 
    166179        # Now we adjust the current query: reset the where clause and get rid 
    167180        # of all the tables we don't need (since they're in the sub-select). 
    168181        self.where = self.where_class() 
    169         if self.related_updates: 
     182        if self.related_updates or must_pre_select: 
     183            # Either we're using the idents in multiple update queries (so 
     184            # don't want them to change), or the db backend doesn't support 
     185            # selecting from the updating table (e.g. MySQL). 
    170186            idents = [] 
    171187            for rows in query.execute_sql(MULTI): 
     
    174190            self.related_ids = idents 
    175191        else: 
     192            # The fast path. Filters and updates in one query. 
    176193            self.add_filter(('pk__in', query)) 
    177194        for alias in self.tables[1:]: 
     
    350367        self.select = [select] 
    351368        self.select_fields = [None] 
     369        self.select_related = False # See #7097. 
    352370        self.distinct = True 
    353371        self.order_by = order == 'ASC' and [1] or [-1] 
  • django/branches/gis/docs/db-api.txt

    r7482 r7498  
    528528 
    529529**New in Django development version:** The syntax for ordering across related 
    530 models has changed. See the `Django 0.96 documentation`_ for the old behaviour. 
     530models has changed. See the `Django 0.96 documentation`_ for the old behavior. 
    531531 
    532532.. _Django 0.96 documentation: http://www.djangoproject.com/documentation/0.96/model-api/#floatfield 
     
    541541**New in Django development version** 
    542542 
    543 If you want to reverse the order in which a queryset's elements are returned, 
    544 you can use the ``reverse()`` method. Calling ``reverse()`` a second tim
    545 restores the ordering back to the normal direction. 
     543Use the ``reverse()`` method to reverse the order in which a queryset's 
     544elements are returned. Calling ``reverse()`` a second time restores th
     545ordering back to the normal direction. 
    546546 
    547547To retrieve the ''last'' five items in a queryset, you could do this:: 
     
    553553penultimate item and so on. If we had a Python sequence and looked at 
    554554``seq[:-5]``, we would see the fifth-last item first. Django doesn't support 
    555 that mode of access (slicing from the end), since it is not possible to do it 
     555that mode of access (slicing from the end), because it's not possible to do it 
    556556efficiently in SQL. 
    557557 
     
    16611661filter statement, not the ``Entry`` items. 
    16621662 
    1663 All of this behaviour also applies to ``exclude()``: all the conditions in a 
     1663All of this behavior also applies to ``exclude()``: all the conditions in a 
    16641664single ``exclude()`` statement apply to a single instance (if those conditions 
    16651665are talking about the same multi-valued relation). Conditions in subsequent 
     
    21022102 
    21032103Sometimes you want to set a field to a particular value for all the objects in 
    2104 a queryset. You can do this with the ``update()`` method. For example:: 
    2105  
    2106     # Update all the headlines to the same value
    2107     Entry.objects.all().update(headline='Everything is the same') 
     2104a ``QuerySet``. You can do this with the ``update()`` method. For example:: 
     2105 
     2106    # Update all the headlines with pub_date in 2007
     2107    Entry.objects.filter(pub_date__year=2007).update(headline='Everything is the same') 
    21082108 
    21092109You can only set non-relation fields and ``ForeignKey`` fields using this 
    2110 method and the value you set the field to must be a normal Python value (you 
    2111 can't set a field to be equal to some other field at the moment). 
     2110method, and the value you set the field to must be a hard-coded Python value 
     2111(i.e., you can't set a field to be equal to some other field at the moment). 
    21122112 
    21132113To update ``ForeignKey`` fields, set the new value to be the new model 
     
    21152115 
    21162116    b = Blog.objects.get(pk=1) 
    2117     # Make all entries belong to this blog. 
     2117    # Change every Entry so that it belongs to this Blog. 
    21182118    Entry.objects.all().update(blog=b) 
    21192119 
    21202120The ``update()`` method is applied instantly and doesn't return anything 
    2121 (similar to ``delete()``). The only restriction on the queryset that is 
     2121(similar to ``delete()``). The only restriction on the ``QuerySet`` that is 
    21222122updated is that it can only access one database table, the model's main 
    21232123table. So don't try to filter based on related fields or anything like that; 
  • django/branches/gis/tests/modeltests/many_to_one/models.py

    r7482 r7498  
    247247[<Reporter: John Smith>] 
    248248 
    249 # Check that implied __exact also works 
     249# Check that implied __exact also works. 
    250250>>> Reporter.objects.filter(article__reporter=r).distinct() 
    251251[<Reporter: John Smith>] 
     
    267267[<Reporter: John Smith>] 
    268268 
    269 # Deletes using a join in the query 
     269# You can delete using a JOIN in the query. 
    270270>>> Reporter.objects.filter(article__headline__startswith='This').delete() 
    271271>>> Reporter.objects.all() 
     
    274274[] 
    275275 
     276# Check that Article.objects.select_related().dates() works properly when 
     277# there are multiple Articles with the same date but different foreign-key 
     278# objects (Reporters). 
     279>>> r1 = Reporter.objects.create(first_name='Mike', last_name='Royko', email='royko@suntimes.com') 
     280>>> r2 = Reporter.objects.create(first_name='John', last_name='Kass', email='jkass@tribune.com') 
     281>>> a1 = Article.objects.create(headline='First', pub_date=datetime(1980, 4, 23), reporter=r1) 
     282>>> a2 = Article.objects.create(headline='Second', pub_date=datetime(1980, 4, 23), reporter=r2) 
     283>>> Article.objects.select_related().dates('pub_date', 'day') 
     284[datetime.datetime(1980, 4, 23, 0, 0)] 
     285>>> Article.objects.select_related().dates('pub_date', 'month') 
     286[datetime.datetime(1980, 4, 1, 0, 0)] 
     287>>> Article.objects.select_related().dates('pub_date', 'year') 
     288[datetime.datetime(1980, 1, 1, 0, 0)] 
    276289"""} 
  • django/branches/gis/tests/regressiontests/queries/models.py

    r7482 r7498  
    117117    class Meta: 
    118118        ordering = ['z'] 
     119 
     120# A model and custom default manager combination. 
     121class CustomManager(models.Manager): 
     122    def get_query_set(self): 
     123        return super(CustomManager, self).get_query_set().filter(public=True, 
     124                tag__name='t1') 
     125 
     126class ManagedModel(models.Model): 
     127    data = models.CharField(max_length=10) 
     128    tag = models.ForeignKey(Tag) 
     129    public = models.BooleanField(default=True) 
     130 
     131    objects = CustomManager() 
     132    normal_manager = models.Manager() 
     133 
     134    def __unicode__(self): 
     135        return self.data 
     136 
    119137 
    120138__test__ = {'API_TESTS':""" 
     
    655673>>> s = qs.query.as_sql()   # test passes if this doesn't raise an exception. 
    656674 
     675Bug #7098 -- Make sure semi-deprecated ordering by related models syntax still 
     676works. 
     677>>> Item.objects.values('note__note').order_by('queries_note.note', 'id') 
     678[{'note__note': u'n2'}, {'note__note': u'n3'}, {'note__note': u'n3'}, {'note__note': u'n3'}] 
     679 
     680Bug #7096 -- Make sure exclude() with multiple conditions continues to work. 
     681>>> Tag.objects.filter(parent=t1, name='t3').order_by('name') 
     682[<Tag: t3>] 
     683>>> Tag.objects.exclude(parent=t1, name='t3').order_by('name') 
     684[<Tag: t1>, <Tag: t2>, <Tag: t4>, <Tag: t5>] 
     685>>> Item.objects.exclude(tags__name='t1', name='one').order_by('name').distinct() 
     686[<Item: four>, <Item: three>, <Item: two>] 
     687>>> Item.objects.filter(name__in=['three', 'four']).exclude(tags__name='t1').order_by('name') 
     688[<Item: four>, <Item: three>] 
     689 
     690More twisted cases, involving nested negations. 
     691>>> Item.objects.exclude(~Q(tags__name='t1', name='one')) 
     692[<Item: one>] 
     693>>> Item.objects.filter(~Q(tags__name='t1', name='one'), name='two') 
     694[<Item: two>] 
     695>>> Item.objects.exclude(~Q(tags__name='t1', name='one'), name='two') 
     696[<Item: four>, <Item: one>, <Item: three>] 
     697 
     698Bug #7095 
     699Updates that are filtered on the model being updated are somewhat tricky to get 
     700in MySQL. This exercises that case. 
     701>>> mm = ManagedModel.objects.create(data='mm1', tag=t1, public=True) 
     702>>> ManagedModel.objects.update(data='mm') 
     703 
    657704"""} 
    658705