Ticket #5415: db_signal_r6702.2.patch
File db_signal_r6702.2.patch, 8.7 KB (added by , 17 years ago) |
---|
-
django/db/__init__.py
1 1 import os 2 2 from django.conf import settings 3 from django.core import signals 3 from django.core import signals as core_signals 4 4 from django.core.exceptions import ImproperlyConfigured 5 5 from django.dispatch import dispatcher 6 6 from django.utils.functional import curry … … 54 54 55 55 # Register an event that closes the database connection 56 56 # when a Django request is finished. 57 dispatcher.connect(connection.close, signal= signals.request_finished)57 dispatcher.connect(connection.close, signal=core_signals.request_finished) 58 58 59 # Register an event that resets connection.queries60 # when a Django request is started.61 def reset_queries():62 connection.queries = []63 dispatcher.connect(reset_queries, signal=signals.request_started)64 65 59 # Register an event that rolls back the connection 66 60 # when a Django request has an exception. 67 61 def _rollback_on_exception(): 68 62 from django.db import transaction 69 63 transaction.rollback_unless_managed() 70 dispatcher.connect(_rollback_on_exception, signal= signals.got_request_exception)64 dispatcher.connect(_rollback_on_exception, signal=core_signals.got_request_exception) -
django/db/signals.py
1 query_execute = object() -
django/db/backends/util.py
1 1 import datetime 2 from django.db import signals 3 from django.dispatch import dispatcher 2 4 import md5 3 5 from time import time 4 6 … … 7 9 except ImportError: 8 10 from django.utils import _decimal as decimal # for Python 2.3 9 11 10 class Cursor DebugWrapper(object):12 class CursorSignalWrapper(object): 11 13 def __init__(self, cursor, db): 12 14 self.cursor = cursor 13 15 self.db = db # Instance of a BaseDatabaseWrapper subclass … … 18 20 return self.cursor.execute(sql, params) 19 21 finally: 20 22 stop = time() 21 sql = self.db.ops.last_executed_query(self.cursor, sql, params) 22 self.db.queries.append({ 23 'sql': sql, 24 'time': "%.3f" % (stop - start), 25 }) 23 dispatcher.send(signal=signals.query_execute, sender=self, sql=sql, params=params, time=stop-start) 26 24 27 25 def executemany(self, sql, param_list): 28 26 start = time() … … 30 28 return self.cursor.executemany(sql, param_list) 31 29 finally: 32 30 stop = time() 33 self.db.queries.append({ 34 'sql': '%s times: %s' % (len(param_list), sql), 35 'time': "%.3f" % (stop - start), 36 }) 31 # XXX: Should this be a special signal that only gets called once for efficiency? 32 for params in param_list: 33 dispatcher.send(signal=signals.query_execute, sender=self, sql=sql, params=params, time=stop-start) 37 34 38 35 def __getattr__(self, attr): 39 36 if attr in self.__dict__: … … 41 38 else: 42 39 return getattr(self.cursor, attr) 43 40 41 44 42 ############################################### 45 43 # Converters from database (string) to Python # 46 44 ############################################### -
django/db/backends/__init__.py
12 12 ops = None 13 13 def __init__(self, **kwargs): 14 14 self.connection = None 15 self.queries = []16 15 self.options = kwargs 17 16 18 17 def _commit(self): … … 31 30 def cursor(self): 32 31 from django.conf import settings 33 32 cursor = self._cursor(settings) 34 if settings.DEBUG:35 return self.make_debug_cursor(cursor)33 from django.db.backends import util 34 cursor = util.CursorSignalWrapper(cursor, self) 36 35 return cursor 37 36 38 def make_debug_cursor(self, cursor):39 from django.db.backends import util40 return util.CursorDebugWrapper(cursor, self)41 42 37 class BaseDatabaseFeatures(object): 43 38 allows_group_by_ordinal = True 44 39 allows_unique_and_pk = True -
django/core/context_processors.py
33 33 context_extras = {} 34 34 if settings.DEBUG and request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS: 35 35 context_extras['debug'] = True 36 from django.db import connection37 context_extras['sql_queries'] = connection.queries38 36 return context_extras 39 37 40 38 def i18n(request): -
tests/modeltests/select_related/models.py
7 7 the select-related behavior will traverse. 8 8 """ 9 9 10 from django.db import models 10 from django.db import models, signals 11 from django.dispatch import dispatcher 11 12 12 13 # Who remembers high school biology? 13 14 … … 75 76 obj.save() 76 77 parent = obj 77 78 79 class QueryCounter(object): 80 counter = 0 81 82 @staticmethod 83 def add(): 84 QueryCounter.counter += 1 85 86 @staticmethod 87 def clear(): 88 QueryCounter.counter = 0 89 90 91 def track_query(sender, *args, **kwargs): 92 QueryCounter.add() 93 dispatcher.connect(track_query, signal=signals.query_execute, weak=False) 94 78 95 __test__ = {'API_TESTS':""" 79 96 80 # Set up.81 # The test runner sets settings.DEBUG to False, but we want to gather queries82 # so we'll set it to True here and reset it at the end of the test suite.83 >>> from django.conf import settings84 >>> settings.DEBUG = True85 86 97 >>> create_tree("Eukaryota Animalia Anthropoda Insecta Diptera Drosophilidae Drosophila melanogaster") 87 98 >>> create_tree("Eukaryota Animalia Chordata Mammalia Primates Hominidae Homo sapiens") 88 99 >>> create_tree("Eukaryota Plantae Magnoliophyta Magnoliopsida Fabales Fabaceae Pisum sativum") … … 91 102 >>> from django import db 92 103 93 104 # Normally, accessing FKs doesn't fill in related objects: 94 >>> db.reset_queries()105 >>> QueryCounter.clear() 95 106 >>> fly = Species.objects.get(name="melanogaster") 96 107 >>> fly.genus.family.order.klass.phylum.kingdom.domain 97 108 <Domain: Eukaryota> 98 >>> len(db.connection.queries)109 >>> QueryCounter.counter 99 110 8 100 111 101 112 # However, a select_related() call will fill in those related objects without any extra queries: 102 >>> db.reset_queries()113 >>> QueryCounter.clear() 103 114 >>> person = Species.objects.select_related().get(name="sapiens") 104 115 >>> person.genus.family.order.klass.phylum.kingdom.domain 105 116 <Domain: Eukaryota> 106 >>> len(db.connection.queries)117 >>> QueryCounter.counter 107 118 1 108 119 109 120 # select_related() also of course applies to entire lists, not just items. 110 121 # Without select_related() 111 >>> db.reset_queries()122 >>> QueryCounter.clear() 112 123 >>> world = Species.objects.all() 113 124 >>> [o.genus.family for o in world] 114 125 [<Family: Drosophilidae>, <Family: Hominidae>, <Family: Fabaceae>, <Family: Amanitacae>] 115 >>> len(db.connection.queries)126 >>> QueryCounter.counter 116 127 9 117 128 118 129 # With select_related(): 119 >>> db.reset_queries()130 >>> QueryCounter.clear() 120 131 >>> world = Species.objects.all().select_related() 121 132 >>> [o.genus.family for o in world] 122 133 [<Family: Drosophilidae>, <Family: Hominidae>, <Family: Fabaceae>, <Family: Amanitacae>] 123 >>> len(db.connection.queries)134 >>> QueryCounter.counter 124 135 1 125 136 126 137 # The "depth" argument to select_related() will stop the descent at a particular level: 127 >>> db.reset_queries()138 >>> QueryCounter.clear() 128 139 >>> pea = Species.objects.select_related(depth=1).get(name="sativum") 129 140 >>> pea.genus.family.order.klass.phylum.kingdom.domain 130 141 <Domain: Eukaryota> 131 142 132 143 # Notice: one few query than above because of depth=1 133 >>> len(db.connection.queries)144 >>> QueryCounter.counter 134 145 7 135 146 136 >>> db.reset_queries()147 >>> QueryCounter.clear() 137 148 >>> pea = Species.objects.select_related(depth=5).get(name="sativum") 138 149 >>> pea.genus.family.order.klass.phylum.kingdom.domain 139 150 <Domain: Eukaryota> 140 >>> len(db.connection.queries)151 >>> QueryCounter.counter 141 152 3 142 153 143 >>> db.reset_queries()154 >>> QueryCounter.clear() 144 155 >>> world = Species.objects.all().select_related(depth=2) 145 156 >>> [o.genus.family.order for o in world] 146 157 [<Order: Diptera>, <Order: Primates>, <Order: Fabales>, <Order: Agaricales>] 147 >>> len(db.connection.queries)158 >>> QueryCounter.counter 148 159 5 149 150 # Reset DEBUG to where we found it.151 >>> settings.DEBUG = False152 160 """}