| =========================== |
| Writing custom model fields |
| =========================== |
| |
| .. currentmodule:: django.db.models |
| |
| Introduction |
| ============ |
| |
| The :doc:`model reference </topics/db/models>` documentation explains how to use |
| Django's standard field classes -- :class:`~django.db.models.CharField`, |
| :class:`~django.db.models.DateField`, etc. For many purposes, those classes are |
| all you'll need. Sometimes, though, the Django version won't meet your precise |
| requirements, or you'll want to use a field that is entirely different from |
| those shipped with Django. |
| |
| Django's built-in field types don't cover every possible database column type -- |
| only the common types, such as ``VARCHAR`` and ``INTEGER``. For more obscure |
| column types, such as geographic polygons or even user-created types such as |
| `PostgreSQL custom types`_, you can define your own Django ``Field`` subclasses. |
| |
| .. _PostgreSQL custom types: http://www.postgresql.org/docs/8.2/interactive/sql-createtype.html |
| |
| Alternatively, you may have a complex Python object that can somehow be |
| serialized to fit into a standard database column type. This is another case |
| where a ``Field`` subclass will help you use your object with your models. |
| |
| Our example object |
| ------------------ |
| |
| Creating custom fields requires a bit of attention to detail. To make things |
| easier to follow, we'll use a consistent example throughout this document: |
| wrapping a Python object representing the deal of cards in a hand of Bridge_. |
| Don't worry, you don't have know how to play Bridge to follow this example. |
| You only need to know that 52 cards are dealt out equally to four players, who |
| are traditionally called *north*, *east*, *south* and *west*. Our class looks |
| something like this:: |
| |
| class Hand(object): |
| """A hand of cards (bridge style)""" |
| |
| def __init__(self, north, east, south, west): |
| # Input parameters are lists of cards ('Ah', '9s', etc) |
| self.north = north |
| self.east = east |
| self.south = south |
| self.west = west |
| |
| # ... (other possibly useful methods omitted) ... |
| |
| .. _Bridge: http://en.wikipedia.org/wiki/Contract_bridge |
| |
| This is just an ordinary Python class, with nothing Django-specific about it. |
| We'd like to be able to do things like this in our models (we assume the |
| ``hand`` attribute on the model is an instance of ``Hand``):: |
| |
| example = MyModel.objects.get(pk=1) |
| print example.hand.north |
| |
| new_hand = Hand(north, east, south, west) |
| example.hand = new_hand |
| example.save() |
| |
| We assign to and retrieve from the ``hand`` attribute in our model just like |
| any other Python class. The trick is to tell Django how to handle saving and |
| loading such an object. |
| |
| In order to use the ``Hand`` class in our models, we **do not** have to change |
| this class at all. This is ideal, because it means you can easily write |
| model support for existing classes where you cannot change the source code. |
| |
| .. note:: |
| You might only be wanting to take advantage of custom database column |
| types and deal with the data as standard Python types in your models; |
| strings, or floats, for example. This case is similar to our ``Hand`` |
| example and we'll note any differences as we go along. |
| |
| Background theory |
| ================= |
| |
| Database storage |
| ---------------- |
| |
| The simplest way to think of a model field is that it provides a way to take a |
| normal Python object -- string, boolean, ``datetime``, or something more |
| complex like ``Hand`` -- and convert it to and from a format that is useful |
| when dealing with the database (and serialization, but, as we'll see later, |
| that falls out fairly naturally once you have the database side under control). |
| |
| Fields in a model must somehow be converted to fit into an existing database |
| column type. Different databases provide different sets of valid column types, |
| but the rule is still the same: those are the only types you have to work |
| with. Anything you want to store in the database must fit into one of |
| those types. |
| |
| Normally, you're either writing a Django field to match a particular database |
| column type, or there's a fairly straightforward way to convert your data to, |
| say, a string. |
| |
| For our ``Hand`` example, we could convert the card data to a string of 104 |
| characters by concatenating all the cards together in a pre-determined order -- |
| say, all the *north* cards first, then the *east*, *south* and *west* cards. So |
| ``Hand`` objects can be saved to text or character columns in the database. |
| |
| What does a field class do? |
| --------------------------- |
| |
| .. class:: Field |
| |
| All of Django's fields (and when we say *fields* in this document, we always |
| mean model fields and not :doc:`form fields </ref/forms/fields>`) are subclasses |
| of :class:`django.db.models.Field`. Most of the information that Django records |
| about a field is common to all fields -- name, help text, uniqueness and so |
| forth. Storing all that information is handled by ``Field``. We'll get into the |
| precise details of what ``Field`` can do later on; for now, suffice it to say |
| that everything descends from ``Field`` and then customizes key pieces of the |
| class behavior. |
| |
| It's important to realize that a Django field class is not what is stored in |
| your model attributes. The model attributes contain normal Python objects. The |
| field classes you define in a model are actually stored in the ``Meta`` class |
| when the model class is created (the precise details of how this is done are |
| unimportant here). This is because the field classes aren't necessary when |
| you're just creating and modifying attributes. Instead, they provide the |
| machinery for converting between the attribute value and what is stored in the |
| database or sent to the :doc:`serializer </topics/serialization>`. |
| |
| Keep this in mind when creating your own custom fields. The Django ``Field`` |
| subclass you write provides the machinery for converting between your Python |
| instances and the database/serializer values in various ways (there are |
| differences between storing a value and using a value for lookups, for |
| example). If this sounds a bit tricky, don't worry -- it will become clearer in |
| the examples below. Just remember that you will often end up creating two |
| classes when you want a custom field: |
| |
| * The first class is the Python object that your users will manipulate. |
| They will assign it to the model attribute, they will read from it for |
| displaying purposes, things like that. This is the ``Hand`` class in our |
| example. |
| |
| * The second class is the ``Field`` subclass. This is the class that knows |
| how to convert your first class back and forth between its permanent |
| storage form and the Python form. |
| |
| Writing a field subclass |
| ======================== |
| |
| When planning your :class:`~django.db.models.Field` subclass, first give some |
| thought to which existing :class:`~django.db.models.Field` class your new field |
| is most similar to. Can you subclass an existing Django field and save yourself |
| some work? If not, you should subclass the :class:`~django.db.models.Field` |
| class, from which everything is descended. |
| |
| Initializing your new field is a matter of separating out any arguments that are |
| specific to your case from the common arguments and passing the latter to the |
| :meth:`~django.db.models.Field.__init__` method of |
| :class:`~django.db.models.Field` (or your parent class). |
| |
| In our example, we'll call our field ``HandField``. (It's a good idea to call |
| your :class:`~django.db.models.Field` subclass ``<Something>Field``, so it's |
| easily identifiable as a :class:`~django.db.models.Field` subclass.) It doesn't |
| behave like any existing field, so we'll subclass directly from |
| :class:`~django.db.models.Field`:: |
| |
| from django.db import models |
| |
| class HandField(models.Field): |
| |
| description = "A hand of cards (bridge style)" |
| |
| def __init__(self, *args, **kwargs): |
| kwargs['max_length'] = 104 |
| super(HandField, self).__init__(*args, **kwargs) |
| |
| Our ``HandField`` accepts most of the standard field options (see the list |
| below), but we ensure it has a fixed length, since it only needs to hold 52 |
| card values plus their suits; 104 characters in total. |
| |
| .. note:: |
| |
| Many of Django's model fields accept options that they don't do anything |
| with. For example, you can pass both |
| :attr:`~django.db.models.Field.editable` and |
| :attr:`~django.db.models.DateField.auto_now` to a |
| :class:`django.db.models.DateField` and it will simply ignore the |
| :attr:`~django.db.models.Field.editable` parameter |
| (:attr:`~django.db.models.DateField.auto_now` being set implies |
| ``editable=False``). No error is raised in this case. |
| |
| This behavior simplifies the field classes, because they don't need to |
| check for options that aren't necessary. They just pass all the options to |
| the parent class and then don't use them later on. It's up to you whether |
| you want your fields to be more strict about the options they select, or to |
| use the simpler, more permissive behavior of the current fields. |
| |
| .. method:: Field.__init__ |
| |
| The :meth:`~django.db.models.Field.__init__` method takes the following |
| parameters: |
| |
| * :attr:`~django.db.models.Field.verbose_name` |
| * :attr:`~django.db.models.Field.name` |
| * :attr:`~django.db.models.Field.primary_key` |
| * :attr:`~django.db.models.Field.max_length` |
| * :attr:`~django.db.models.Field.unique` |
| * :attr:`~django.db.models.Field.blank` |
| * :attr:`~django.db.models.Field.null` |
| * :attr:`~django.db.models.Field.db_index` |
| * :attr:`~django.db.models.Field.rel`: Used for related fields (like |
| :class:`ForeignKey`). For advanced use only. |
| * :attr:`~django.db.models.Field.default` |
| * :attr:`~django.db.models.Field.editable` |
| * :attr:`~django.db.models.Field.serialize`: If ``False``, the field will |
| not be serialized when the model is passed to Django's :doc:`serializers |
| </topics/serialization>`. Defaults to ``True``. |
| * :attr:`~django.db.models.Field.unique_for_date` |
| * :attr:`~django.db.models.Field.unique_for_month` |
| * :attr:`~django.db.models.Field.unique_for_year` |
| * :attr:`~django.db.models.Field.choices` |
| * :attr:`~django.db.models.Field.help_text` |
| * :attr:`~django.db.models.Field.db_column` |
| * :attr:`~django.db.models.Field.db_tablespace`: Only for index creation, if the |
| backend supports :doc:`tablespaces </topics/db/tablespaces>`. You can usually |
| ignore this option. |
| * :attr:`~django.db.models.Field.auto_created`: True if the field was |
| automatically created, as for the `OneToOneField` used by model |
| inheritance. For advanced use only. |
| |
| All of the options without an explanation in the above list have the same |
| meaning they do for normal Django fields. See the :doc:`field documentation |
| </ref/models/fields>` for examples and details. |
| |
| The ``SubfieldBase`` metaclass |
| ------------------------------ |
| |
| .. class:: django.db.models.SubfieldBase |
| |
| As we indicated in the introduction_, field subclasses are often needed for |
| two reasons: either to take advantage of a custom database column type, or to |
| handle complex Python types. Obviously, a combination of the two is also |
| possible. If you're only working with custom database column types and your |
| model fields appear in Python as standard Python types direct from the |
| database backend, you don't need to worry about this section. |
| |
| If you're handling custom Python types, such as our ``Hand`` class, we need to |
| make sure that when Django initializes an instance of our model and assigns a |
| database value to our custom field attribute, we convert that value into the |
| appropriate Python object. The details of how this happens internally are a |
| little complex, but the code you need to write in your ``Field`` class is |
| simple: make sure your field subclass uses a special metaclass: |
| |
| For example:: |
| |
| class HandField(models.Field): |
| |
| description = "A hand of cards (bridge style)" |
| |
| __metaclass__ = models.SubfieldBase |
| |
| def __init__(self, *args, **kwargs): |
| # ... |
| |
| This ensures that the :meth:`.to_python` method, documented below, will always |
| be called when the attribute is initialized. |
| |
| ModelForms and custom fields |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| If you use :class:`~django.db.models.SubfieldBase`, :meth:`.to_python` |
| will be called every time an instance of the field is assigned a |
| value. This means that whenever a value may be assigned to the field, |
| you need to ensure that it will be of the correct datatype, or that |
| you handle any exceptions. |
| |
| This is especially important if you use :doc:`ModelForms |
| </topics/forms/modelforms>`. When saving a ModelForm, Django will use |
| form values to instantiate model instances. However, if the cleaned |
| form data can't be used as valid input to the field, the normal form |
| validation process will break. |
| |
| Therefore, you must ensure that the form field used to represent your |
| custom field performs whatever input validation and data cleaning is |
| necessary to convert user-provided form input into a |
| `to_python()`-compatible model field value. This may require writing a |
| custom form field, and/or implementing the :meth:`.formfield` method on |
| your field to return a form field class whose `to_python()` returns the |
| correct datatype. |
| |
| Documenting your custom field |
| ----------------------------- |
| |
| .. attribute:: Field.description |
| |
| 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 :doc:`django.contrib.admindocs |
| </ref/contrib/admin/admindocs>` application. To do this simply provide |
| descriptive text in a ``description`` class attribute of your custom field. In |
| the above example, the description displayed by the ``admindocs`` |
| application for a ``HandField`` will be 'A hand of cards (bridge style)'. |
| |
| Useful methods |
| -------------- |
| |
| Once you've created your :class:`~django.db.models.Field` subclass and set up |
| the ``__metaclass__``, you might consider overriding a few standard methods, |
| depending on your field's behavior. The list of methods below is in |
| approximately decreasing order of importance, so start from the top. |
| |
| Custom database types |
| ~~~~~~~~~~~~~~~~~~~~~ |
| |
| .. method:: Field.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 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` method, like so:: |
| |
| from django.db import models |
| |
| class MytypeField(models.Field): |
| def db_type(self, connection): |
| return 'mytype' |
| |
| Once you have ``MytypeField``, you can use it in any model, just like any other |
| ``Field`` type:: |
| |
| class Person(models.Model): |
| name = models.CharField(max_length=80) |
| something_else = MytypeField() |
| |
| 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 :meth:`.db_type` |
| method is to check the ``connection.settings_dict['ENGINE']`` attribute. |
| |
| For example:: |
| |
| class MyDateField(models.Field): |
| def db_type(self, connection): |
| if connection.settings_dict['ENGINE'] == 'django.db.backends.mysql': |
| return 'datetime' |
| else: |
| return 'timestamp' |
| |
| 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 |
| ``connection.settings_dict`` check in the above example. |
| |
| Some database column types accept parameters, such as ``CHAR(25)``, where the |
| parameter ``25`` represents the maximum column length. In cases like these, |
| it's more flexible if the parameter is specified in the model rather than being |
| hard-coded in the ``db_type()`` method. For example, it wouldn't make much |
| sense to have a ``CharMaxlength25Field``, shown here:: |
| |
| # This is a silly example of hard-coded parameters. |
| class CharMaxlength25Field(models.Field): |
| def db_type(self, connection): |
| return 'char(25)' |
| |
| # In the model: |
| class MyModel(models.Model): |
| # ... |
| my_field = CharMaxlength25Field() |
| |
| The better way of doing this would be to make the parameter specifiable at run |
| time -- i.e., when the class is instantiated. To do that, just implement |
| :meth:`django.db.models.Field.__init__`, like so:: |
| |
| # This is a much more flexible example. |
| class BetterCharField(models.Field): |
| def __init__(self, max_length, *args, **kwargs): |
| self.max_length = max_length |
| super(BetterCharField, self).__init__(*args, **kwargs) |
| |
| def db_type(self, connection): |
| return 'char(%s)' % self.max_length |
| |
| # In the model: |
| class MyModel(models.Model): |
| # ... |
| my_field = BetterCharField(25) |
| |
| Finally, if your column requires truly complex SQL setup, return ``None`` from |
| :meth:`.db_type`. This will cause Django's SQL creation code to skip |
| over this field. You are then responsible for creating the column in the right |
| table in some other way, of course, but this gives you a way to tell Django to |
| get out of the way. |
| |
| Converting database values to Python objects |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| .. method:: Field.to_python(self, value) |
| |
| Converts a value as returned by your database (or a serializer) to a Python |
| object. |
| |
| The default implementation simply returns ``value``, for the common case in |
| which the database backend already returns data in the correct format (as a |
| Python string, for example). |
| |
| If your custom :class:`~django.db.models.Field` class deals with data structures |
| that are more complex than strings, dates, integers or floats, then you'll need |
| to override this method. As a general rule, the method should deal gracefully |
| with any of the following arguments: |
| |
| * An instance of the correct type (e.g., ``Hand`` in our ongoing example). |
| |
| * A string (e.g., from a deserializer). |
| |
| * Whatever the database returns for the column type you're using. |
| |
| In our ``HandField`` class, we're storing the data as a VARCHAR field in the |
| database, so we need to be able to process strings and ``Hand`` instances in |
| :meth:`.to_python`:: |
| |
| import re |
| |
| class HandField(models.Field): |
| # ... |
| |
| def to_python(self, value): |
| if isinstance(value, Hand): |
| return value |
| |
| # The string case. |
| p1 = re.compile('.{26}') |
| p2 = re.compile('..') |
| args = [p2.findall(x) for x in p1.findall(value)] |
| return Hand(*args) |
| |
| Notice that we always return a ``Hand`` instance from this method. That's the |
| Python object type we want to store in the model's attribute. |
| |
| **Remember:** If your custom field needs the :meth:`to_python` method to be |
| called when it is created, you should be using `The SubfieldBase metaclass`_ |
| mentioned earlier. Otherwise :meth:`.to_python` won't be called |
| automatically. |
| |
| .. warning:: |
| |
| If your custom field allows ``null=True``, any field method that takes |
| ``value`` as an argument, like :meth:`~Field.to_python` and |
| :meth:`~Field.get_prep_value`, should handle the case when ``value`` is |
| ``None``. |
| |
| Converting Python objects to query values |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| .. method:: Field.get_prep_value(self, value) |
| |
| .. versionadded:: 1.2 |
| This method was factored out of ``get_db_prep_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 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_prep_value(self, value): |
| return ''.join([''.join(l) for l in (value.north, |
| value.east, value.south, value.west)]) |
| |
| .. warning:: |
| |
| If your custom field uses the ``CHAR``, ``VARCHAR`` or ``TEXT`` |
| types for MySQL, you must make sure that :meth:`.get_prep_value` |
| always returns a string type. MySQL performs flexible and unexpected |
| matching when a query is performed on these types and the provided |
| value is an integer, which can cause queries to include unexpected |
| objects in their results. This problem cannot occur if you always |
| return a string type from :meth:`.get_prep_value`. |
| |
| Converting query values to database values |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| .. method:: Field.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. |
| |
| .. method:: Field.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 |
| :meth:`.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 :meth:`.get_db_prep_value`). |
| |
| Preprocessing values before saving |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| .. method:: Field.pre_save(self, model_instance, add) |
| |
| This method is called just prior to :meth:`.get_db_prep_save` and should return |
| the value of the appropriate attribute from ``model_instance`` for this field. |
| The attribute name is in ``self.attname`` (this is set up by |
| :class:`~django.db.models.Field`). If the model is being saved to the database |
| for the first time, the ``add`` parameter will be ``True``, otherwise it will be |
| ``False``. |
| |
| You only need to override this method if you want to preprocess the value |
| somehow, just before saving. For example, Django's |
| :class:`~django.db.models.DateTimeField` uses this method to set the attribute |
| correctly in the case of :attr:`~django.db.models.DateField.auto_now` or |
| :attr:`~django.db.models.DateField.auto_now_add`. |
| |
| If you do override this method, you must return the value of the attribute at |
| the end. You should also update the model's attribute if you make any changes |
| to the value so that code holding references to the model will always see the |
| correct value. |
| |
| Preparing values for use in database lookups |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| As with value conversions, preparing a value for database lookups is a |
| two phase process. |
| |
| .. method:: Field.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 |
| Django filter lookups: ``exact``, ``iexact``, ``contains``, ``icontains``, |
| ``gt``, ``gte``, ``lt``, ``lte``, ``in``, ``startswith``, ``istartswith``, |
| ``endswith``, ``iendswith``, ``range``, ``year``, ``month``, ``day``, |
| ``isnull``, ``search``, ``regex``, and ``iregex``. |
| |
| Your method must be prepared to handle all of these ``lookup_type`` values and |
| should raise either a ``ValueError`` if the ``value`` is of the wrong sort (a |
| list when you were expecting an object, for example) or a ``TypeError`` if |
| your field does not support that type of lookup. For many fields, you can get |
| 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_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_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_prep_value()``, or at least factor out some common |
| pieces. |
| |
| 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_prep_lookup(self, lookup_type, value): |
| # We only handle 'exact' and 'in'. All others are errors. |
| if lookup_type == 'exact': |
| return self.get_prep_value(value) |
| elif lookup_type == 'in': |
| return [self.get_prep_value(v) for v in value] |
| else: |
| raise TypeError('Lookup type %r not supported.' % lookup_type) |
| |
| .. method:: Field.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 |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| .. method:: Field.formfield(self, form_class=forms.CharField, **kwargs) |
| |
| Returns the default form field to use when this field is displayed in a model. |
| This method is called by the :class:`~django.forms.ModelForm` helper. |
| |
| All of the ``kwargs`` dictionary is passed directly to the form field's |
| :meth:`~django.forms.Field__init__` method. Normally, all you need to do is |
| set up a good default for the ``form_class`` argument and then delegate further |
| handling to the parent class. This might require you to write a custom form |
| field (and even a form widget). See the :doc:`forms documentation |
| </topics/forms/index>` for information about this, and take a look at the code in |
| :mod:`django.contrib.localflavor` for some examples of custom widgets. |
| |
| Continuing our ongoing example, we can write the :meth:`.formfield` method as:: |
| |
| class HandField(models.Field): |
| # ... |
| |
| def formfield(self, **kwargs): |
| # This is a fairly standard way to set up some defaults |
| # while letting the caller override them. |
| defaults = {'form_class': MyFormField} |
| defaults.update(kwargs) |
| return super(HandField, self).formfield(**defaults) |
| |
| This assumes we've imported a ``MyFormField`` field class (which has its own |
| default widget). This document doesn't cover the details of writing custom form |
| fields. |
| |
| .. _helper functions: ../forms/#generating-forms-for-models |
| .. _forms documentation: ../forms/ |
| |
| Emulating built-in field types |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| .. method:: Field.get_internal_type(self) |
| |
| Returns a string giving the name of the :class:`~django.db.models.Field` |
| subclass we are emulating at the database level. This is used to determine the |
| type of database column for simple cases. |
| |
| If you have created a :meth:`.db_type` method, you don't need to worry about |
| :meth:`.get_internal_type` -- it won't be used much. Sometimes, though, your |
| database storage is similar in type to some other field, so you can use that |
| other field's logic to create the right column. |
| |
| For example:: |
| |
| class HandField(models.Field): |
| # ... |
| |
| def get_internal_type(self): |
| return 'CharField' |
| |
| No matter which database backend we are using, this will mean that ``syncdb`` |
| and other SQL commands create the right column type for storing a string. |
| |
| If :meth:`.get_internal_type` returns a string that is not known to Django for |
| the database backend you are using -- that is, it doesn't appear in |
| ``django.db.backends.<db_name>.creation.DATA_TYPES`` -- the string will still be |
| used by the serializer, but the default :meth:`.db_type` method will return |
| ``None``. See the documentation of :meth:`.db_type` for reasons why this might be |
| useful. Putting a descriptive string in as the type of the field for the |
| serializer is a useful idea if you're ever going to be using the serializer |
| output in some other place, outside of Django. |
| |
| Converting field data for serialization |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| .. method:: Field.value_to_string(self, obj) |
| |
| This method is used by the serializers to convert the field into a string for |
| output. Calling :meth:`Field._get_val_from_obj(obj)` is the best way to get the |
| value to serialize. For example, since our ``HandField`` uses strings for its |
| data storage anyway, we can reuse some existing conversion code:: |
| |
| class HandField(models.Field): |
| # ... |
| |
| def value_to_string(self, obj): |
| value = self._get_val_from_obj(obj) |
| return self.get_prep_value(value) |
| |
| Some general advice |
| -------------------- |
| |
| Writing a custom field can be a tricky process, particularly if you're doing |
| complex conversions between your Python types and your database and |
| serialization formats. Here are a couple of tips to make things go more |
| smoothly: |
| |
| 1. Look at the existing Django fields (in |
| :file:`django/db/models/fields/__init__.py`) for inspiration. Try to find |
| a field that's similar to what you want and extend it a little bit, |
| instead of creating an entirely new field from scratch. |
| |
| 2. Put a :meth:`__str__` or :meth:`__unicode__` method on the class you're |
| wrapping up as a field. There are a lot of places where the default |
| behavior of the field code is to call |
| :func:`~django.utils.encoding.force_unicode` on the value. (In our |
| examples in this document, ``value`` would be a ``Hand`` instance, not a |
| ``HandField``). So if your :meth:`__unicode__` method automatically |
| converts to the string form of your Python object, you can save yourself |
| a lot of work. |
| |
| |
| Writing a ``FileField`` subclass |
| ================================= |
| |
| In addition to the above methods, fields that deal with files have a few other |
| special requirements which must be taken into account. The majority of the |
| mechanics provided by ``FileField``, such as controlling database storage and |
| retrieval, can remain unchanged, leaving subclasses to deal with the challenge |
| of supporting a particular type of file. |
| |
| Django provides a ``File`` class, which is used as a proxy to the file's |
| contents and operations. This can be subclassed to customize how the file is |
| accessed, and what methods are available. It lives at |
| ``django.db.models.fields.files``, and its default behavior is explained in the |
| :doc:`file documentation </ref/files/file>`. |
| |
| Once a subclass of ``File`` is created, the new ``FileField`` subclass must be |
| told to use it. To do so, simply assign the new ``File`` subclass to the special |
| ``attr_class`` attribute of the ``FileField`` subclass. |
| |
| A few suggestions |
| ------------------ |
| |
| In addition to the above details, there are a few guidelines which can greatly |
| improve the efficiency and readability of the field's code. |
| |
| 1. The source for Django's own ``ImageField`` (in |
| ``django/db/models/fields/files.py``) is a great example of how to |
| subclass ``FileField`` to support a particular type of file, as it |
| incorporates all of the techniques described above. |
| |
| 2. Cache file attributes wherever possible. Since files may be stored in |
| remote storage systems, retrieving them may cost extra time, or even |
| money, that isn't always necessary. Once a file is retrieved to obtain |
| some data about its content, cache as much of that data as possible to |
| reduce the number of times the file must be retrieved on subsequent |
| calls for that information. |