diff options
| author | Russell Keith-Magee <russell@keith-magee.com> | 2009-12-22 15:18:51 +0000 |
|---|---|---|
| committer | Russell Keith-Magee <russell@keith-magee.com> | 2009-12-22 15:18:51 +0000 |
| commit | ff60c5f9de3e8690d1e86f3e9e3f7248a15397c8 (patch) | |
| tree | a4cb0ebdd55fcaf8c8855231b6ad3e1a7bf45bee /docs/howto | |
| parent | 7ef212af149540aa2da577a960d0d87029fd1514 (diff) | |
Fixed #1142 -- Added multiple database support.
This monster of a patch is the result of Alex Gaynor's 2009 Google Summer of Code project.
Congratulations to Alex for a job well done.
Big thanks also go to:
* Justin Bronn for keeping GIS in line with the changes,
* Karen Tracey and Jani Tiainen for their help testing Oracle support
* Brett Hoerner, Jon Loyens, and Craig Kimmerer for their feedback.
* Malcolm Treddinick for his guidance during the GSoC submission process.
* Simon Willison for driving the original design process
* Cal Henderson for complaining about ponies he wanted.
... and everyone else too numerous to mention that helped to bring this feature into fruition.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@11952 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'docs/howto')
| -rw-r--r-- | docs/howto/custom-model-fields.txt | 129 | ||||
| -rw-r--r-- | docs/howto/initial-data.txt | 34 | ||||
| -rw-r--r-- | docs/howto/legacy-databases.txt | 17 |
3 files changed, 121 insertions, 59 deletions
diff --git a/docs/howto/custom-model-fields.txt b/docs/howto/custom-model-fields.txt index 1475aaf62d..1da8eae4b1 100644 --- a/docs/howto/custom-model-fields.txt +++ b/docs/howto/custom-model-fields.txt @@ -272,9 +272,9 @@ Documenting your Custom Field As always, you should document your field type, so users will know what it is. In addition to providing a docstring for it, which is useful for developers, you can also allow users of the admin app to see a short description of the -field type via the ``django.contrib.admindocs`` application. To do this simply -provide descriptive text in a ``description`` class attribute of your custom field. -In the above example, the type description displayed by the ``admindocs`` application +field type via the ``django.contrib.admindocs`` application. To do this simply +provide descriptive text in a ``description`` class attribute of your custom field. +In the above example, the type description displayed by the ``admindocs`` application for a ``HandField`` will be 'A hand of cards (bridge style)'. Useful methods @@ -288,10 +288,13 @@ approximately decreasing order of importance, so start from the top. Custom database types ~~~~~~~~~~~~~~~~~~~~~ -.. method:: db_type(self) +.. method:: db_type(self, connection) + +.. versionadded:: 1.2 + The ``connection`` argument was added to support multiple databases. Returns the database column data type for the :class:`~django.db.models.Field`, -taking into account the current :setting:`DATABASE_ENGINE` setting. +taking into account the connection object, and the settings associated with it. Say you've created a PostgreSQL custom type called ``mytype``. You can use this field with Django by subclassing ``Field`` and implementing the :meth:`db_type` @@ -300,7 +303,7 @@ method, like so:: from django.db import models class MytypeField(models.Field): - def db_type(self): + def db_type(self, connection): return 'mytype' Once you have ``MytypeField``, you can use it in any model, just like any other @@ -315,13 +318,13 @@ If you aim to build a database-agnostic application, you should account for differences in database column types. For example, the date/time column type in PostgreSQL is called ``timestamp``, while the same column in MySQL is called ``datetime``. The simplest way to handle this in a ``db_type()`` method is to -import the Django settings module and check the :setting:`DATABASE_ENGINE` setting. +check the ``connection.settings_dict['ENGINE']`` attribute. + For example:: class MyDateField(models.Field): - def db_type(self): - from django.conf import settings - if settings.DATABASE_ENGINE == 'mysql': + def db_type(self, connection): + if connection.settings_dict['ENGINE'] == 'django.db.backends.mysql': return 'datetime' else: return 'timestamp' @@ -329,7 +332,7 @@ For example:: The :meth:`db_type` method is only called by Django when the framework constructs the ``CREATE TABLE`` statements for your application -- that is, when you first create your tables. It's not called at any other time, so it can -afford to execute slightly complex code, such as the :setting:`DATABASE_ENGINE` +afford to execute slightly complex code, such as the ``connection.settings_dict`` check in the above example. Some database column types accept parameters, such as ``CHAR(25)``, where the @@ -340,7 +343,7 @@ sense to have a ``CharMaxlength25Field``, shown here:: # This is a silly example of hard-coded parameters. class CharMaxlength25Field(models.Field): - def db_type(self): + def db_type(self, connection): return 'char(25)' # In the model: @@ -358,7 +361,7 @@ time -- i.e., when the class is instantiated. To do that, just implement self.max_length = max_length super(BetterCharField, self).__init__(*args, **kwargs) - def db_type(self): + def db_type(self, connection): return 'char(%s)' % self.max_length # In the model: @@ -421,33 +424,67 @@ Python object type we want to store in the model's attribute. called when it is created, you should be using `The SubfieldBase metaclass`_ mentioned earlier. Otherwise :meth:`to_python` won't be called automatically. -Converting Python objects to database values -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Converting Python objects to query values +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. method:: get_prep_value(self, value) + +.. versionadded:: 1.2 + This method was factored out of ``get_db_prep_value()`` -.. method:: get_db_prep_value(self, value) +This is the reverse of :meth:`to_python` when working with the +database backends (as opposed to serialization). The ``value`` +parameter is the current value of the model's attribute (a field has +no reference to its containing model, so it cannot retrieve the value +itself), and the method should return data in a format that has been +prepared for use as a parameter in a query. -This is the reverse of :meth:`to_python` when working with the database backends -(as opposed to serialization). The ``value`` parameter is the current value of -the model's attribute (a field has no reference to its containing model, so it -cannot retrieve the value itself), and the method should return data in a format -that can be used as a parameter in a query for the database backend. +This conversion should *not* include any database-specific +conversions. If database-specific conversions are required, they +should be made in the call to :meth:`get_db_prep_value`. For example:: class HandField(models.Field): # ... - def get_db_prep_value(self, value): + def get_prep_value(self, value): return ''.join([''.join(l) for l in (value.north, value.east, value.south, value.west)]) -.. method:: get_db_prep_save(self, value) +Converting query values to database values +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. method:: get_db_prep_value(self, value, connection, prepared=False) + +.. versionadded:: 1.2 + The ``connection`` and ``prepared arguments were added to support multiple databases. + +Some data types (for example, dates) need to be in a specific format +before they can be used by a database backend. +:meth:`get_db_prep_value` is the method where those conversions should +be made. The specific connection that will be used for the query is +passed as the ``connection`` parameter. This allows you to use +backend-specific conversion logic if it is required. + +The ``prepared`` argument describes whether or not the value has +already been passed through :meth:`get_prep_value` conversions. When +``prepared`` is False, the default implementation of +:meth:`get_db_prep_value` will call :meth:`get_prep_value` to do +initial data conversions before performing any database-specific +processing. -Same as the above, but called when the Field value must be *saved* to the -database. As the default implementation just calls ``get_db_prep_value``, you -shouldn't need to implement this method unless your custom field needs a -special conversion when being saved that is not the same as the conversion used -for normal query parameters (which is implemented by ``get_db_prep_value``). +.. method:: get_db_prep_save(self, value, connection) + +.. versionadded:: 1.2 + The ``connection`` argument was added to support multiple databases. + +Same as the above, but called when the Field value must be *saved* to +the database. As the default implementation just calls +``get_db_prep_value``, you shouldn't need to implement this method +unless your custom field needs a special conversion when being saved +that is not the same as the conversion used for normal query +parameters (which is implemented by ``get_db_prep_value``). Preprocessing values before saving ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -475,7 +512,16 @@ correct value. Preparing values for use in database lookups ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. method:: get_db_prep_lookup(self, lookup_type, value) +As with value conversions, preparing a value for database lookups is a +two phase process. + +.. method:: get_prep_lookup(self, lookup_type, value) + +.. versionadded:: 1.2 + This method was factored out of ``get_db_prep_lookup()`` + +:meth:`get_prep_lookup` performs the first phase of lookup preparation, +performing generic data validity checks Prepares the ``value`` for passing to the database when used in a lookup (a ``WHERE`` constraint in SQL). The ``lookup_type`` will be one of the valid @@ -492,34 +538,45 @@ by with handling the lookup types that need special handling for your field and pass the rest to the :meth:`get_db_prep_lookup` method of the parent class. If you needed to implement ``get_db_prep_save()``, you will usually need to -implement ``get_db_prep_lookup()``. If you don't, ``get_db_prep_value`` will be +implement ``get_prep_lookup()``. If you don't, ``get_prep_value`` will be called by the default implementation, to manage ``exact``, ``gt``, ``gte``, ``lt``, ``lte``, ``in`` and ``range`` lookups. You may also want to implement this method to limit the lookup types that could be used with your custom field type. -Note that, for ``range`` and ``in`` lookups, ``get_db_prep_lookup`` will receive +Note that, for ``range`` and ``in`` lookups, ``get_prep_lookup`` will receive a list of objects (presumably of the right type) and will need to convert them to a list of things of the right type for passing to the database. Most of the -time, you can reuse ``get_db_prep_value()``, or at least factor out some common +time, you can reuse ``get_prep_value()``, or at least factor out some common pieces. -For example, the following code implements ``get_db_prep_lookup`` to limit the +For example, the following code implements ``get_prep_lookup`` to limit the accepted lookup types to ``exact`` and ``in``:: class HandField(models.Field): # ... - def get_db_prep_lookup(self, lookup_type, value): + def get_prep_lookup(self, lookup_type, value): # We only handle 'exact' and 'in'. All others are errors. if lookup_type == 'exact': - return [self.get_db_prep_value(value)] + return [self.get_prep_value(value)] elif lookup_type == 'in': - return [self.get_db_prep_value(v) for v in value] + return [self.get_prep_value(v) for v in value] else: raise TypeError('Lookup type %r not supported.' % lookup_type) +.. method:: get_db_prep_lookup(self, lookup_type, value, connection, prepared=False) + +.. versionadded:: 1.2 + The ``connection`` and ``prepared`` arguments were added to support multiple databases. + +Performs any database-specific data conversions required by a lookup. +As with :meth:`get_db_prep_value`, the specific connection that will +be used for the query is passed as the ``connection`` parameter. +The ``prepared`` argument describes whether the value has already been +prepared with :meth:`get_prep_lookup`. + Specifying the form field for a model field ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/howto/initial-data.txt b/docs/howto/initial-data.txt index d36329daa4..b071d6d529 100644 --- a/docs/howto/initial-data.txt +++ b/docs/howto/initial-data.txt @@ -118,23 +118,27 @@ The SQL files are read by the :djadmin:`sqlcustom`, :djadmin:`sqlreset`, <ref-django-admin>`. Refer to the :ref:`manage.py documentation <ref-django-admin>` for more information. -Note that if you have multiple SQL data files, there's no guarantee of the order -in which they're executed. The only thing you can assume is that, by the time -your custom data files are executed, all the database tables already will have -been created. +Note that if you have multiple SQL data files, there's no guarantee of +the order in which they're executed. The only thing you can assume is +that, by the time your custom data files are executed, all the +database tables already will have been created. Database-backend-specific SQL data ---------------------------------- -There's also a hook for backend-specific SQL data. For example, you can have -separate initial-data files for PostgreSQL and MySQL. For each app, Django -looks for a file called ``<appname>/sql/<modelname>.<backend>.sql``, where -``<appname>`` is your app directory, ``<modelname>`` is the model's name in -lowercase and ``<backend>`` is the value of :setting:`DATABASE_ENGINE` in your -settings file (e.g., ``postgresql``, ``mysql``). +There's also a hook for backend-specific SQL data. For example, you +can have separate initial-data files for PostgreSQL and MySQL. For +each app, Django looks for a file called +``<appname>/sql/<modelname>.<backend>.sql``, where ``<appname>`` is +your app directory, ``<modelname>`` is the model's name in lowercase +and ``<backend>`` is the last part of the module name provided for the +:setting:`ENGINE` in your settings file (e.g., if you have defined a +database with an :setting:`ENGINE` value of +``django.db.backends.postgresql``, Django will look for +``<appname>/sql/<modelname>.postgresql.sql``). -Backend-specific SQL data is executed before non-backend-specific SQL data. For -example, if your app contains the files ``sql/person.sql`` and -``sql/person.postgresql.sql`` and you're installing the app on PostgreSQL, -Django will execute the contents of ``sql/person.postgresql.sql`` first, then -``sql/person.sql``. +Backend-specific SQL data is executed before non-backend-specific SQL +data. For example, if your app contains the files ``sql/person.sql`` +and ``sql/person.postgresql.sql`` and you're installing the app on +PostgreSQL, Django will execute the contents of +``sql/person.postgresql.sql`` first, then ``sql/person.sql``. diff --git a/docs/howto/legacy-databases.txt b/docs/howto/legacy-databases.txt index c4eb1d82c7..b2aa7e4ea6 100644 --- a/docs/howto/legacy-databases.txt +++ b/docs/howto/legacy-databases.txt @@ -18,15 +18,16 @@ Give Django your database parameters ==================================== You'll need to tell Django what your database connection parameters are, and -what the name of the database is. Do that by editing these settings in your -:ref:`settings file <topics-settings>`: +what the name of the database is. Do that by editing the :setting:`DATABASES` +setting and assigning values to the following keys for the ``'default'`` +connection: - * :setting:`DATABASE_NAME` - * :setting:`DATABASE_ENGINE` - * :setting:`DATABASE_USER` - * :setting:`DATABASE_PASSWORD` - * :setting:`DATABASE_HOST` - * :setting:`DATABASE_PORT` + * :setting:`NAME` + * :setting:`ENGINE` + * :setting:`USER` + * :setting:`PASSWORD` + * :setting:`HOST` + * :setting:`PORT` Auto-generate the models ======================== |
