Django

Code

Ticket #4747: mdb.patch

File mdb.patch, 203.1 kB (added by ben <ben.fordnz@gmail.com>, 1 year ago)

Full Patch -r4189:5589

  • django/test/utils.py

    old new  
    11import sys, time 
    22from django.conf import settings 
    3 from django.db import connection, backend, get_creation_module 
     3from django.db import connection, transaction, backend, \ 
     4                connection_info, connections, get_creation_module 
    45from django.core import management, mail 
    56from django.core import management, mail 
    67from django.dispatch import dispatcher 
     
    1213TEST_DATABASE_PREFIX = 'test_' 
    1314 
    1415def instrumented_test_render(self, context): 
    15     """An instrumented Template render method, providing a signal  
    16     that can be intercepted by the test system Client 
    17      
    1816    """ 
     17    An instrumented Template render method, providing a signal that can be 
     18    intercepted by the test system Client. 
     19    """ 
    1920    dispatcher.send(signal=signals.template_rendered, sender=self, template=self, context=context) 
    2021    return self.nodelist.render(context) 
     22 
     23def instrumented_test_iter_render(self, context): 
     24    """ 
     25    An instrumented Template iter_render method, providing a signal that can be 
     26    intercepted by the test system Client. 
     27    """ 
     28    for chunk in self.nodelist.iter_render(context): 
     29        yield chunk 
     30    dispatcher.send(signal=signals.template_rendered, sender=self, template=self, context=context) 
    2131     
    2232class TestSMTPConnection(object): 
    2333    """A substitute SMTP connection for use during test sessions. 
     
    4555         
    4656    """ 
    4757    Template.original_render = Template.render 
     58    Template.original_iter_render = Template.iter_render 
    4859    Template.render = instrumented_test_render 
     60    Template.iter_render = instrumented_test_render 
    4961     
    5062    mail.original_SMTPConnection = mail.SMTPConnection 
    5163    mail.SMTPConnection = TestSMTPConnection 
     
    6072         
    6173    """ 
    6274    Template.render = Template.original_render 
    63     del Template.original_render 
     75    Template.iter_render = Template.original_iter_render 
     76    del Template.original_render, Template.original_iter_render 
    6477     
    6578    mail.SMTPConnection = mail.original_SMTPConnection 
    6679    del mail.original_SMTPConnection 
     
    7386        connection.connection.autocommit(True) 
    7487    elif hasattr(connection.connection, "set_isolation_level"): 
    7588        connection.connection.set_isolation_level(0) 
    76  
     89         
    7790def get_mysql_create_suffix(): 
    7891    suffix = [] 
    7992    if settings.TEST_DATABASE_CHARSET: 
     
    97110     
    98111    if verbosity >= 1: 
    99112        print "Creating test database..." 
     113         
    100114    # If we're using SQLite, it's more convenient to test against an 
    101115    # in-memory database. 
    102116    if settings.DATABASE_ENGINE == "sqlite3": 
    103         TEST_DATABASE_NAME = ":memory:" 
     117        TEST_DATABASE_NAME = "/home/ben/test.db" #":memory:" 
     118        if verbosity >= 2: 
     119            print "Using in-memory sqlite database for testing" 
    104120    else: 
    105121        suffix = { 
    106122            'postgresql': get_postgresql_create_suffix, 
     
    112128            TEST_DATABASE_NAME = settings.TEST_DATABASE_NAME 
    113129        else: 
    114130            TEST_DATABASE_NAME = TEST_DATABASE_PREFIX + settings.DATABASE_NAME 
    115          
     131 
     132        qn = backend.quote_name 
    116133        # Create the test database and connect to it. We need to autocommit 
    117134        # if the database supports it because PostgreSQL doesn't allow  
    118135        # CREATE/DROP DATABASE statements within transactions. 
    119136        cursor = connection.cursor() 
    120137        _set_autocommit(connection) 
    121138        try: 
    122             cursor.execute("CREATE DATABASE %s %s" % (backend.quote_name(TEST_DATABASE_NAME), suffix)) 
     139            cursor.execute("CREATE DATABASE %s %s" % (qn(TEST_DATABASE_NAME), suffix)) 
    123140        except Exception, e:             
    124141            sys.stderr.write("Got an error creating the test database: %s\n" % e) 
    125142            if not autoclobber: 
     
    128145                try: 
    129146                    if verbosity >= 1: 
    130147                        print "Destroying old test database..."                 
    131                     cursor.execute("DROP DATABASE %s" % backend.quote_name(TEST_DATABASE_NAME)) 
     148                    cursor.execute("DROP DATABASE %s" % qn(TEST_DATABASE_NAME)) 
    132149                    if verbosity >= 1: 
    133150                        print "Creating test database..." 
    134                     cursor.execute("CREATE DATABASE %s %s" % (backend.quote_name(TEST_DATABASE_NAME), suffix)) 
     151                    cursor.execute("CREATE DATABASE %s %s" % (qn(TEST_DATABASE_NAME), suffix)) 
    135152                except Exception, e: 
    136153                    sys.stderr.write("Got an error recreating the test database: %s\n" % e) 
    137154                    sys.exit(2) 
     
    148165    # the side effect of initializing the test database. 
    149166    cursor = connection.cursor() 
    150167 
    151 def destroy_test_db(old_database_name, verbosity=1): 
     168    # Fill OTHER_DATABASES with the TEST_DATABASES settings, 
     169    # and connect each named connection to the test database. 
     170    test_databases = {} 
     171    for db_name in settings.TEST_DATABASES: 
     172        db_st = {'DATABASE_NAME': TEST_DATABASE_NAME} 
     173        if db_name in settings.TEST_DATABASE_MODELS: 
     174            db_st['MODELS'] = settings.TEST_DATABASE_MODELS.get(db_name, []) 
     175        test_databases[db_name] = db_st 
     176    settings.OTHER_DATABASES = test_databases 
     177     
     178def destroy_test_db(old_database_name, old_databases, verbosity=1): 
    152179    # If the database wants to drop the test DB itself, let it 
    153180    creation_module = get_creation_module() 
    154181    if hasattr(creation_module, "destroy_test_db"): 
    155182        creation_module.destroy_test_db(settings, connection, backend, old_database_name, verbosity) 
    156183        return 
    157      
    158184    # Unless we're using SQLite, remove the test database to clean up after 
    159185    # ourselves. Connect to the previous database (not the test database) 
    160186    # to do so, because it's not allowed to delete a database while being 
    161187    # connected to it. 
    162188    if verbosity >= 1: 
    163189        print "Destroying test database..." 
     190 
    164191    connection.close() 
     192    for cnx in connections.keys(): 
     193        connections[cnx].close() 
     194    connections.reset() 
     195     
    165196    TEST_DATABASE_NAME = settings.DATABASE_NAME 
     197    if verbosity >= 2: 
     198        print "Closed connections to %s" % TEST_DATABASE_NAME 
    166199    settings.DATABASE_NAME = old_database_name 
    167  
     200     
    168201    if settings.DATABASE_ENGINE != "sqlite3": 
     202        settings.OTHER_DATABASES = old_databases 
     203        for cnx in connections.keys(): 
     204            try: 
     205                connections[cnx].connection.cursor() 
     206            except (KeyboardInterrupt, SystemExit): 
     207                raise 
     208            except: 
     209                pass 
    169210        cursor = connection.cursor() 
    170211        _set_autocommit(connection) 
    171212        time.sleep(1) # To avoid "database is being accessed by other users" errors. 
  • django/http/__init__.py

    old new  
    224224        content = ''.join(self._container) 
    225225        if isinstance(content, unicode): 
    226226            content = content.encode(self._charset) 
     227 
     228        # If self._container was an iterator, we have just exhausted it, so we 
     229        # need to save the results for anything else that needs access 
     230        if not self._is_string: 
     231            self._container = [content] 
     232            self._is_string = True 
    227233        return content 
    228234 
    229235    def _set_content(self, value): 
     
    233239    content = property(_get_content, _set_content) 
    234240 
    235241    def __iter__(self): 
    236         self._iterator = self._container.__iter__() 
    237         return self 
     242        for chunk in self._container: 
     243            if isinstance(chunk, unicode): 
     244                chunk = chunk.encode(self._charset) 
     245            yield chunk 
    238246 
    239     def next(self): 
    240         chunk = self._iterator.next() 
    241         if isinstance(chunk, unicode): 
    242             chunk = chunk.encode(self._charset) 
    243         return chunk 
    244  
    245247    def close(self): 
    246248        if hasattr(self._container, 'close'): 
    247249            self._container.close() 
  • django/oldforms/__init__.py

    old new  
    309309        return data 
    310310    html2python = staticmethod(html2python) 
    311311 
     312    def iter_render(self, data): 
     313        # this even needed? 
     314        return (self.render(data),) 
     315 
    312316    def render(self, data): 
    313317        raise NotImplementedError 
    314318 
  • django/db/models/base.py

    old new  
    66from django.db.models.fields.related import OneToOneRel, ManyToOneRel 
    77from django.db.models.query import delete_objects 
    88from django.db.models.options import Options, AdminOptions 
    9 from django.db import connection, backend, transaction 
     9from django.db import transaction 
    1010from django.db.models import signals 
    1111from django.db.models.loading import register_models, get_model 
    1212from django.dispatch import dispatcher 
     
    2222    "Metaclass for all models" 
    2323    def __new__(cls, name, bases, attrs): 
    2424        # If this isn't a subclass of Model, don't do anything special. 
     25        print "\n\n" + "*"*40 
     26        print "ModelBase Called with name: %s and attrs:" % name 
     27        print "\n".join(["%s => %s" % (k,v) for k, v in attrs.items()]) 
    2528        try: 
    2629            if not filter(lambda b: issubclass(b, Model), bases): 
    2730                return super(ModelBase, cls).__new__(cls, name, bases, attrs) 
     
    201204    def save(self): 
    202205        dispatcher.send(signal=signals.pre_save, sender=self.__class__, instance=self) 
    203206 
     207        db = self.__class__._default_manager.db 
     208        connection = db.connection 
     209        backend = db.backend 
     210        qn = backend.quote_name 
    204211        non_pks = [f for f in self._meta.fields if not f.primary_key] 
    205212        cursor = connection.cursor() 
    206213 
     
    211218        if pk_set: 
    212219            # Determine whether a record with the primary key already exists. 
    213220            cursor.execute("SELECT COUNT(*) FROM %s WHERE %s=%%s" % \ 
    214                 (backend.quote_name(self._meta.db_table), backend.quote_name(self._meta.pk.column)), 
     221                (qn(self._meta.db_table), qn(self._meta.pk.column)), 
    215222                self._meta.pk.get_db_prep_lookup('exact', pk_val)) 
    216223            # If it does already exist, do an UPDATE. 
    217224            if cursor.fetchone()[0] > 0: 
    218225                db_values = [f.get_db_prep_save(f.pre_save(self, False)) for f in non_pks] 
    219226                if db_values: 
    220227                    cursor.execute("UPDATE %s SET %s WHERE %s=%%s" % \ 
    221                         (backend.quote_name(self._meta.db_table), 
    222                         ','.join(['%s=%%s' % backend.quote_name(f.column) for f in non_pks]), 
    223                         backend.quote_name(self._meta.pk.column)), 
     228                        (qn(self._meta.db_table), 
     229                        ','.join(['%s=%%s' % qn(f.column) for f in non_pks]), 
     230                        qn(self._meta.pk.column)), 
    224231                        db_values + self._meta.pk.get_db_prep_lookup('exact', pk_val)) 
    225232            else: 
    226233                record_exists = False 
    227234        if not pk_set or not record_exists: 
    228             field_names = [backend.quote_name(f.column) for f in self._meta.fields if not isinstance(f, AutoField)] 
     235            field_names = [qn(f.column) for f in self._meta.fields if not isinstance(f, AutoField)] 
    229236            db_values = [f.get_db_prep_save(f.pre_save(self, True)) for f in self._meta.fields if not isinstance(f, AutoField)] 
    230237            # If the PK has been manually set, respect that. 
    231238            if pk_set: 
     
    233240                db_values += [f.get_db_prep_save(f.pre_save(self, True)) for f in self._meta.fields if isinstance(f, AutoField)] 
    234241            placeholders = ['%s'] * len(field_names) 
    235242            if self._meta.order_with_respect_to: 
    236                 field_names.append(backend.quote_name('_order')) 
     243                field_names.append(qn('_order')) 
    237244                # TODO: This assumes the database supports subqueries. 
    238245                placeholders.append('(SELECT COUNT(*) FROM %s WHERE %s = %%s)' % \ 
    239                     (backend.quote_name(self._meta.db_table), backend.quote_name(self._meta.order_with_respect_to.column))) 
     246                    (qn(self._meta.db_table), qn(self._meta.order_with_respect_to.column))) 
    240247                db_values.append(getattr(self, self._meta.order_with_respect_to.attname)) 
    241248            if db_values: 
    242249                cursor.execute("INSERT INTO %s (%s) VALUES (%s)" % \ 
    243                     (backend.quote_name(self._meta.db_table), ','.join(field_names), 
     250                    (qn(self._meta.db_table), ','.join(field_names), 
    244251                    ','.join(placeholders)), db_values) 
    245252            else: 
    246253                # Create a new record with defaults for everything. 
    247254                cursor.execute("INSERT INTO %s (%s) VALUES (%s)" % 
    248                     (backend.quote_name(self._meta.db_table), 
    249                      backend.quote_name(self._meta.pk.column), 
     255                    (qn(self._meta.db_table), 
     256                     qn(self._meta.pk.column), 
    250257                     backend.get_pk_default_value())) 
    251258            if self._meta.has_auto_field and not pk_set: 
    252259                setattr(self, self._meta.pk.attname, backend.get_last_insert_id(cursor, self._meta.db_table, self._meta.pk.column)) 
    253         transaction.commit_unless_managed(
     260        transaction.commit_unless_managed([connection]
    254261 
    255262        # Run any post-save hooks. 
    256263        dispatcher.send(signal=signals.post_save, sender=self.__class__, instance=self) 
     
    321328        return dict(field.choices).get(value, value) 
    322329 
    323330    def _get_next_or_previous_by_FIELD(self, field, is_next, **kwargs): 
     331        qn = self._default_manager.db.backend.quote_name 
    324332        op = is_next and '>' or '<' 
    325333        where = '(%s %s %%s OR (%s = %%s AND %s.%s %s %%s))' % \ 
    326             (backend.quote_name(field.column), op, backend.quote_name(field.column), 
    327             backend.quote_name(self._meta.db_table), backend.quote_name(self._meta.pk.column), op) 
     334            (qn(field.column), op, qn(field.column), 
     335            qn(self._meta.db_table), qn(self._meta.pk.column), op) 
    328336        param = str(getattr(self, field.attname)) 
    329337        q = self.__class__._default_manager.filter(**kwargs).order_by((not is_next and '-' or '') + field.name, (not is_next and '-' or '') + self._meta.pk.name) 
    330338        q._where.append(where) 
     
    335343            raise self.DoesNotExist, "%s matching query does not exist." % self.__class__._meta.object_name 
    336344 
    337345    def _get_next_or_previous_in_order(self, is_next): 
     346        qn = self._default_manager.db.backend.quote_name 
     347 
    338348        cachename = "__%s_order_cache" % is_next 
    339349        if not hasattr(self, cachename): 
    340350            op = is_next and '>' or '<' 
    341351            order_field = self._meta.order_with_respect_to 
    342352            where = ['%s %s (SELECT %s FROM %s WHERE %s=%%s)' % \ 
    343                 (backend.quote_name('_order'), op, backend.quote_name('_order'), 
    344                 backend.quote_name(self._meta.db_table), backend.quote_name(self._meta.pk.column)), 
    345                 '%s=%%s' % backend.quote_name(order_field.column)] 
     353                (qn('_order'), op, qn('_order'), 
     354                qn(self._meta.db_table), qn(self._meta.pk.column)), 
     355                '%s=%%s' % qn(order_field.column)] 
    346356            params = [self._get_pk_val(), getattr(self, order_field.attname)] 
    347357            obj = self._default_manager.order_by('_order').extra(where=where, params=params)[:1].get() 
    348358            setattr(self, cachename, obj) 
     
    424434# ORDERING METHODS ######################### 
    425435 
    426436def method_set_order(ordered_obj, self, id_list): 
     437    db = ordered_obj._default_manager.db 
     438    connection = db.connection 
     439    qn = db.backend.quote_name 
    427440    cursor = connection.cursor() 
    428441    # Example: "UPDATE poll_choices SET _order = %s WHERE poll_id = %s AND id = %s" 
    429442    sql = "UPDATE %s SET %s = %%s WHERE %s = %%s AND %s = %%s" % \ 
    430         (backend.quote_name(ordered_obj._meta.db_table), backend.quote_name('_order'), 
    431         backend.quote_name(ordered_obj._meta.order_with_respect_to.column), 
    432         backend.quote_name(ordered_obj._meta.pk.column)) 
     443        (qn(ordered_obj._meta.db_table), qn('_order'), 
     444        qn(ordered_obj._meta.order_with_respect_to.column), 
     445        qn(ordered_obj._meta.pk.column)) 
    433446    rel_val = getattr(self, ordered_obj._meta.order_with_respect_to.rel.field_name) 
    434447    cursor.executemany(sql, [(i, rel_val, j) for i, j in enumerate(id_list)]) 
    435     transaction.commit_unless_managed(
     448    transaction.commit_unless_managed([connection]
    436449 
    437450def method_get_order(ordered_obj, self): 
     451    db = ordered_obj._default_manager.db 
     452    connection = db.connection 
     453    qn = db.backend.quote_name 
    438454    cursor = connection.cursor() 
    439455    # Example: "SELECT id FROM poll_choices WHERE poll_id = %s ORDER BY _order" 
    440456    sql = "SELECT %s FROM %s WHERE %s = %%s ORDER BY %s" % \ 
    441         (backend.quote_name(ordered_obj._meta.pk.column), 
    442         backend.quote_name(ordered_obj._meta.db_table), 
    443         backend.quote_name(ordered_obj._meta.order_with_respect_to.column), 
    444         backend.quote_name('_order')) 
     457        (qn(ordered_obj._meta.pk.column), 
     458        qn(ordered_obj._meta.db_table), 
     459        qn(ordered_obj._meta.order_with_respect_to.column), 
     460        qn('_order')) 
    445461    rel_val = getattr(self, ordered_obj._meta.order_with_respect_to.rel.field_name) 
    446462    cursor.execute(sql, [rel_val]) 
    447463    return [r[0] for r in cursor.fetchall()] 
  • django/db/models/manager.py

    old new  
     1from django.db import ConnectionInfoDescriptor 
    12from django.db.models.query import QuerySet, EmptyQuerySet 
    23from django.dispatch import dispatcher 
    3 from django.db.models import signals 
     4from django.db.models import signals, get_apps, get_models 
    45from django.db.models.fields import FieldDoesNotExist 
    56 
     7try: 
     8    # Only exists in Python 2.4+ 
     9    from threading import local 
     10except ImportError: 
     11    # Import copy of _thread_local.py from Python 2.4 
     12    from django.utils._threading_local import local 
     13 
    614# Size of each "chunk" for get_iterator calls. 
    715# Larger values are slightly faster at the expense of more storage space. 
    816GET_ITERATOR_CHUNK_SIZE = 100 
     
    1725        except FieldDoesNotExist: 
    1826            pass 
    1927        cls.add_to_class('objects', Manager()) 
    20  
     28    elif cls._default_manager.model != cls: 
     29        # cls is an inherited model; don't want the parent manager 
     30        cls.add_to_class('objects', Manager()) 
    2131dispatcher.connect(ensure_default_manager, signal=signals.class_prepared) 
    2232 
     33 
     34 
    2335class Manager(object): 
    2436    # Tracks each time a Manager instance is created. Used to retain order. 
    2537    creation_counter = 0 
    26  
     38    db = ConnectionInfoDescriptor() 
     39     
    2740    def __init__(self): 
    2841        super(Manager, self).__init__() 
    2942        # Increase the creation counter, and save our local copy. 
     
    3548        # TODO: Use weakref because of possible memory leak / circular reference. 
    3649        self.model = model 
    3750        setattr(model, name, ManagerDescriptor(self)) 
    38         if not hasattr(model, '_default_manager') or self.creation_counter < model._default_manager.creation_counter: 
     51        if not hasattr(model, '_default_manager') \ 
     52            or self.creation_counter < model._default_manager.creation_counter \ 
     53            or model._default_manager.model != model: 
    3954            model._default_manager = self 
    40  
     55         
    4156    ####################### 
    4257    # PROXIES TO QUERYSET # 
    4358    ####################### 
     
    105120    def values(self, *args, **kwargs): 
    106121        return self.get_query_set().values(*args, **kwargs) 
    107122 
     123    ####################### 
     124    # SCHEMA MANIPULATION # 
     125    ####################### 
     126 
     127    def install(self, initial_data=False, pending=None): 
     128        """Install my model's table, indexes and (if requested) initial data. 
     129 
     130        Returns a dict of pending statements, keyed by the model that 
     131        needs to be created before the statements can be executed. 
     132        (Pending statements are those that could not yet be executed, 
     133        such as foreign key constraints for tables that don't exist at 
     134        install time.) 
     135        """ 
     136        if pending is None: 
     137            pending = {} 
     138        builder = self.db.get_creation_module().builder 
     139        run, pending = builder.get_create_table(self.model, pending=pending) 
     140        run += builder.get_create_indexes(self.model) 
     141        many_many = builder.get_create_many_to_many(self.model) 
     142 
     143        for statement in run: 
     144            statement.execute() 
     145        for klass, statements in many_many.items(): 
     146            if klass in builder.models_already_seen: 
     147                for statement in statements: 
     148                    statement.execute() 
     149            else: 
     150                pending.setdefault(klass, []).extend(statements) 
     151        if initial_data: 
     152            self.load_initial_data() 
     153        return pending 
     154 
     155    def get_pending(self, rel_class, f): 
     156        """Get list pending statement relating my model to rel_class via 
     157        field f 
     158        """ 
     159        builder = self.db.get_creation_module().builder 
     160        return builder.get_ref_sql(self.model, rel_class, f) 
     161 
     162    def load_initial_data(self): 
     163        """Install initial data for model in db, Returns statements executed. 
     164        """ 
     165        builder = self.db.get_creation_module().builder 
     166        statements = builder.get_initialdata(self.model) 
     167        for statement in statements: 
     168            statement.execute() 
     169        return statements 
     170         
     171    def get_installed_models(self, table_list): 
     172        """Get list of models installed, given a list of tables. 
     173        """ 
     174        all_models = [] 
     175        for app in get_apps(): 
     176            for model in get_models(app): 
     177                all_models.append(model) 
     178        return set([m for m in all_models 
     179                    if m._meta.db_table in table_list]) 
     180 
     181    def get_table_list(self): 
     182        """Get list of tables accessible via my model's connection. 
     183        """ 
     184        builder = self.db.get_creation_module().builder 
     185        return builder.get_table_list(self.db) 
     186     
    108187class ManagerDescriptor(object): 
    109188    # This class ensures managers aren't accessible via model instances. 
    110189    # For example, Poll.objects works, but poll_obj.objects raises AttributeError. 
     
    115194        if instance != None: 
    116195            raise AttributeError, "Manager isn't accessible via %s instances" % type.__name__ 
    117196        return self.manager 
     197 
  • django/db/models/options.py

    old new  
    11from django.conf import settings 
     2from django.db import connection_info, connections 
    23from django.db.models.related import RelatedObject 
    34from django.db.models.fields.related import ManyToManyRel 
    45from django.db.models.fields import AutoField, FieldDoesNotExist 
     
    78from django.db.models import Manager 
    89from bisect import bisect 
    910import re 
     11import weakref 
    1012 
    1113# Calculate the verbose_name by converting from InitialCaps to "lowercase with spaces". 
    1214get_verbose_name = lambda class_name: re.sub('(((?<=[a-z])[A-Z])|([A-Z](?![A-Z]|$)))', ' \\1', class_name).lower().strip() 
     
    7981            self.db_table = truncate_name(self.db_table, 
    8082                                          backend.get_max_name_length()) 
    8183 
     84        # Keep a weakref to my model, for access to managers and such 
     85        self._model = weakref.ref(model) 
     86 
    8287    def add_field(self, field): 
    8388        # Insert the given field in the order in which it was created, using 
    8489        # the "creation_counter" attribute of the field. 
     
    105110                return f 
    106111        raise FieldDoesNotExist, '%s has no field named %r' % (self.object_name, name) 
    107112 
     113    def get_default_manager(self): 
     114        model = self._model() 
     115        if model is None: 
     116            raise ReferenceError("Model no longer available in %s" % self) 
     117        return model._default_manager 
     118 
    108119    def get_order_sql(self, table_prefix=''): 
    109120        "Returns the full 'ORDER BY' clause for this object, according to self.ordering." 
    110121        if not self.ordering: return '' 
  • django/db/models/loading.py

    old new  
    1212_app_models = {} # Dictionary of models against app label 
    1313                 # Each value is a dictionary of model name: model class 
    1414                 # Applabel and Model entry exists in cache when individual model is loaded. 
     15_app_model_order = {} # Dictionary of models against app label 
     16                      # Each value is a list of model names, in the order in 
     17                      # which the models were created 
    1518_app_errors = {} # Dictionary of errors that were experienced when loading the INSTALLED_APPS 
    1619                 # Key is the app_name of the model, value is the exception that was raised 
    1720                 # during model loading. 
     
    6164    get_apps() # Run get_apps() to populate the _app_list cache. Slightly hackish. 
    6265    return _app_errors 
    6366 
    64 def get_models(app_mod=None): 
     67def get_models(app_mod=None, creation_order=False): 
    6568    """ 
    6669    Given a module containing models, returns a list of the models. Otherwise 
    6770    returns a list of all installed models. 
    6871    """ 
    6972    app_list = get_apps() # Run get_apps() to populate the _app_list cache. Slightly hackish. 
    7073    if app_mod: 
    71         return _app_models.get(app_mod.__name__.split('.')[-2], {}).values() 
     74        app_label = app_mod.__name__.split('.')[-2] 
     75        app_models = _app_models.get(app_label, {}) 
     76        if creation_order: 
     77            return [ app_models[name] 
     78                     for name in _app_model_order.get(app_label, []) ] 
     79        return app_models.values() 
    7280    else: 
    7381        model_list = [] 
    7482        for app_mod in app_list: 
  • django/db/models/fields/__init__.py

    old new  
    536536                except ValueError: 
    537537                    raise validators.ValidationError, gettext('Enter a valid date/time in YYYY-MM-DD HH:MM format.') 
    538538 
    539     def get_db_prep_save(self, value): 
    540         # Casts dates into string format for entry into database. 
     539    def pre_save(self, model_instance, add): 
     540        value = super(DateField, self).pre_save(model_instance, add) 
    541541        if value is not None: 
    542542            # MySQL will throw a warning if microseconds are given, because it 
    543543            # doesn't support microseconds. 
     544            settings = model_instance._default_manager.db.connection.settings 
    544545            if settings.DATABASE_ENGINE == 'mysql' and hasattr(value, 'microsecond'): 
    545546                value = value.replace(microsecond=0) 
     547        return value 
     548 
     549    def get_db_prep_save(self, value): 
     550        # Casts dates into string format for entry into database. 
     551        if value is not None: 
    546552            value = str(value) 
    547553        return Field.get_db_prep_save(self, value) 
    548554 
     
    909915        if value is not None: 
    910916            # MySQL will throw a warning if microseconds are given, because it 
    911917            # doesn't support microseconds. 
     918            settings = model_instance._default_manager.db.connection.settings 
    912919            if settings.DATABASE_ENGINE == 'mysql' and hasattr(value, 'microsecond'): 
    913920                value = value.replace(microsecond=0) 
    914921            if settings.DATABASE_ENGINE == 'oracle': 
  • django/db/models/fields/related.py

    old new  
    1 from django.db import backend, transaction 
     1from django.db import transaction 
    22from django.db.models import signals, get_model 
    33from django.db.models.fields import AutoField, Field, IntegerField, get_ul_class 
    44from django.db.models.related import RelatedObject 
     
    318318            # source_col_name: the PK colname in join_table for the source object 
    319319            # target_col_name: the PK colname in join_table for the target object 
    320320            # *objs - objects to add. Either object instances, or primary keys of object instances. 
    321             from django.db import connection 
     321            connection = self.model._default_manager.db.connection 
    322322 
    323323            # If there aren't any objects, there is nothing to do. 
    324324            if objs: 
     
    343343                    cursor.execute("INSERT INTO %s (%s, %s) VALUES (%%s, %%s)" % \ 
    344344                        (self.join_table, source_col_name, target_col_name), 
    345345                        [self._pk_val, obj_id]) 
    346                 transaction.commit_unless_managed(
     346            transaction.commit_unless_managed(connection
    347347 
    348348        def _remove_items(self, source_col_name, target_col_name, *objs): 
    349349            # source_col_name: the PK colname in join_table for the source object 
    350350            # target_col_name: the PK colname in join_table for the target object 
    351351            # *objs - objects to remove 
    352             from django.db import connection 
     352            connection = self.model._default_manager.db.connection 
    353353 
    354354            # If there aren't any objects, there is nothing to do. 
    355355            if objs: 
     
    366366                    (self.join_table, source_col_name, 
    367367                    target_col_name, ",".join(['%s'] * len(old_ids))), 
    368368                    [self._pk_val] + list(old_ids)) 
    369                 transaction.commit_unless_managed(
     369            transaction.commit_unless_managed(connection
    370370 
    371371        def _clear_items(self, source_col_name): 
    372372            # source_col_name: the PK colname in join_table for the source object 
    373             from django.db import connection 
     373            connection = self.model._default_manager.db.connection 
    374374            cursor = connection.cursor() 
    375375            cursor.execute("DELETE FROM %s WHERE %s = %%s" % \ 
    376376                (self.join_table, source_col_name), 
    377377                [self._pk_val]) 
    378             transaction.commit_unless_managed(
     378            transaction.commit_unless_managed(connection
    379379 
    380380    return ManyRelatedManager 
    381381 
     
    399399        superclass = rel_model._default_manager.__class__ 
    400400        RelatedManager = create_many_related_manager(superclass) 
    401401 
    402         qn = backend.quote_name 
     402        qn = rel_model._default_manager.db.backend.quote_name 
    403403        manager = RelatedManager( 
    404404            model=rel_model, 
    405405            core_filters={'%s__pk' % self.related.field.name: instance._get_pk_val()}, 
     
    440440        superclass = rel_model._default_manager.__class__ 
    441441        RelatedManager = create_many_related_manager(superclass) 
    442442 
    443         qn = backend.quote_name 
     443        qn = rel_model._default_manager.db.backend.quote_name 
    444444        manager = RelatedManager( 
    445445            model=rel_model, 
    446446            core_filters={'%s__pk' % self.field.related_query_name(): instance._get_pk_val()}, 
  • django/db/models/query.py

    old new  
    182182        # self._select is a dictionary, and dictionaries' key order is 
    183183        # undefined, so we convert it to a list of tuples. 
    184184        extra_select = self._select.items() 
    185  
    186         cursor = connection.cursor() 
     185        cursor = self.model._default_manager.db.connection.cursor() 
    187186        cursor.execute("SELECT " + (self._distinct and "DISTINCT " or "") + ",".join(select) + sql, params) 
    188187 
    189188        fill_cache = self._select_related 
     
    217216        """ 
    218217        if self._result_cache is not None: 
    219218            return len(self._result_cache) 
    220  
     219        #from multi-db 
     220        db = self.model._default_manager.db 
     221        backend = db.backend 
     222        connection = db.connection  
     223         
    221224        counter = self._clone() 
    222225        counter._order_by = () 
    223226        counter._select_related = False 
     
    304307        Returns a dictionary mapping each of the given IDs to the object with 
    305308        that ID. 
    306309        """ 
     310        backend = self.model._default_manager.db.backend 
    307311        assert self._limit is None and self._offset is None, \ 
    308312                "Cannot use 'limit' or 'offset' with in_bulk" 
    309313        assert isinstance(id_list, (tuple,  list)), "in_bulk() must be provided with a list of IDs." 
     
    481485 
    482486    def _get_sql_clause(self): 
    483487        opts = self.model._meta 
    484  
     488        backend = self.model._default_manager.db.backend 
     489        qn = backend.quote_name 
    485490        # Construct the fundamental parts of the query: SELECT X FROM Y WHERE Z. 
    486         select = ["%s.%s" % (backend.quote_name(opts.db_table), backend.quote_name(f.column)) for f in opts.fields] 
     491        select = ["%s.%s" % (qn(opts.db_table), qn(f.column)) 
     492                  for f in opts.fields] 
    487493        tables = [quote_only_if_word(t) for t in self._tables] 
    488494        joins = SortedDict() 
    489495        where = self._where[:] 
     
    504510 
    505511        # Add any additional SELECTs. 
    506512        if self._select: 
    507             select.extend(['(%s) AS %s' % (quote_only_if_word(s[1]), backend.quote_name(s[0])) for s in self._select.items()]) 
     513            select.extend(['(%s) AS %s' % (quote_only_if_word(s[1]), qn(s[0])) 
     514                           for s in self._select.items()]) 
    508515 
    509516        # Start composing the body of the SQL statement. 
    510         sql = [" FROM", backend.quote_name(opts.db_table)] 
     517        sql = [" FROM", qn(opts.db_table)] 
    511518 
    512519        # Compose the join dictionary into SQL describing the joins. 
    513520        if joins: 
     
    540547                    order = "ASC" 
    541548                if "." in col_name: 
    542549                    table_prefix, col_name = col_name.split('.', 1) 
    543                     table_prefix = backend.quote_name(table_prefix) + '.' 
     550                    table_prefix = qn(table_prefix) + '.' 
    544551                else: 
    545552                    # Use the database table as a column prefix if it wasn't given, 
    546553                    # and if the requested column isn't a custom SELECT. 
    547554                    if "." not in col_name and col_name not in (self._select or ()): 
    548                         table_prefix = backend.quote_name(opts.db_table) + '.' 
     555                        table_prefix = qn(opts.db_table) + '.' 
    549556                    else: 
    550557                        table_prefix = '' 
    551                 order_by.append('%s%s %s' % (table_prefix, backend.quote_name(orderfield2column(col_name, opts)), order)) 
     558                order_by.append('%s%s %s' % (table_prefix, qn(orderfield2column(col_name, opts)), order)) 
    552559        if order_by: 
    553560            sql.append("ORDER BY " + ", ".join(order_by)) 
    554561 
     
    597604 
    598605        columns = [f.column for f in fields] 
    599606        select = ['%s.%s' % (backend.quote_name(self.model._meta.db_table), backend.quote_name(c)) for c in columns] 
     607             
     608        #from multi-db 
     609        db = self.model._default_manager.db 
     610        backend = db.backend 
     611        qn = backend.quote_name 
     612        connection = db.connection 
     613 
    600614        # Add any additional SELECTs. 
    601615        if self._select: 
    602616            select.extend(['(%s) AS %s' % (quote_only_if_word(s[1]), backend.quote_name(s[0])) for s in self._select.items()]) 
    603617 
    604618        cursor = connection.cursor() 
     619        select = ['%s.%s' % (qn(self.model._meta.db_table), qn(c)) 
     620                  for c in columns] 
    605621        cursor.execute("SELECT " + (self._distinct and "DISTINCT " or "") + ",".join(select) + sql, params) 
    606622 
    607623        has_resolve_columns = hasattr(self, 'resolve_columns') 
     
    623639    def iterator(self): 
    624640        from django.db.backends.util import typecast_timestamp 
    625641        from django.db.models.fields import DateTimeField 
     642        db = self.model._default_manager.db 
     643        backend = db.backend 
     644        qn = backend.quote_name 
     645        connection = db.connection 
     646         
    626647        self._order_by = () # Clear this because it'll mess things up otherwise. 
    627648        if self._field.null: 
    628649            self._where.append('%s.%s IS NOT NULL' % \ 
    629                 (backend.quote_name(self.model._meta.db_table), backend.quote_name(self._field.column))) 
     650                (qn(self.model._meta.db_table), qn(self._field.column))) 
     651 
    630652        try: 
    631653            select, sql, params = self._get_sql_clause() 
    632654        except EmptyResultSet: 
    633655            raise StopIteration 
    634656 
    635         table_name = backend.quote_name(self.model._meta.db_table) 
    636         field_name = backend.quote_name(self._field.column) 
     657        table_name = qn(self.model._meta.db_table) 
     658        field_name = qn(self._field.column) 
    637659 
    638660        if backend.allows_group_by_ordinal: 
    639661            group_by = '1' 
     
    768790            return SortedDict(), [], [] 
    769791        return joins, where2, params 
    770792 
    771 def get_where_clause(lookup_type, table_prefix, field_name, value): 
     793def get_where_clause(opts, lookup_type, table_prefix, field_name, value): 
     794    backend = opts.get_default_manager().db.backend 
     795    qn = backend.quote_name 
     796     
    772797    if table_prefix.endswith('.'): 
    773         table_prefix = backend.quote_name(table_prefix[:-1])+'.' 
    774     field_name = backend.quote_name(field_name) 
     798        table_prefix = qn(table_prefix[:-1])+'.' 
     799    field_name = qn(field_name) 
    775800    if type(value) == datetime.datetime and backend.get_datetime_cast_sql(): 
    776801        cast_sql = backend.get_datetime_cast_sql() 
    777802    else: 
     
    832857    Helper function that recursively populates the select, tables and where (in 
    833858    place) for select_related queries. 
    834859    """ 
     860    qn = opts.get_default_manager().db.backend.quote_name 
    835861 
    836862    # If we've got a max_depth set and we've exceeded that depth, bail now. 
    837863    if max_depth and cur_depth > max_depth: 
    838864        return None 
    839865 
    840     qn = backend.quote_name 
    841866    for f in opts.fields: 
    842867        if f.rel and not f.null: 
    843868            db_table = f.rel.to._meta.db_table 
     
    935960    return choices 
    936961 
    937962def lookup_inner(path, lookup_type, value, opts, table, column): 
    938     qn = backend.quote_name 
    939963    joins, where, params = SortedDict(), [], [] 
    940964    current_opts = opts 
    941965    current_table = table 
    942966    current_column = column 
    943967    intermediate_table = None 
    944968    join_required = False 
     969    db = current_opts.get_default_manager().db 
     970    backend = db.backend 
     971    connection = db.connection 
     972    qn = backend.quote_name 
    945973 
    946974    name = path.pop(0) 
    947975    # Has the primary key been requested? If so, expand it out 
     
    10921120            # Last query term was a normal field. 
    10931121            column = field.column 
    10941122 
    1095         where.append(get_where_clause(lookup_type, current_table + '.', column, value)) 
     1123        where.append(get_where_clause(current_opts, lookup_type, current_table + '.', column, value)) 
    10961124        params.extend(field.get_db_prep_lookup(lookup_type, value)) 
    10971125 
    10981126    return joins, where, params 
    10991127 
    11001128def delete_objects(seen_objs): 
    11011129    "Iterate through a list of seen classes, and remove any instances that are referred to" 
    1102     qn = backend.quote_name 
    1103