mirror of https://github.com/django/django.git
Fixed #13774 -- Added models.Field.rel_db_type().
This commit is contained in:
parent
0e7d59df3e
commit
b61eab18f7
|
@ -626,6 +626,14 @@ class Field(RegisterLookupMixin):
|
|||
except KeyError:
|
||||
return None
|
||||
|
||||
def rel_db_type(self, connection):
|
||||
"""
|
||||
Return the data type that a related field pointing to this field should
|
||||
use. For example, this method is called by ForeignKey and OneToOneField
|
||||
to determine its data type.
|
||||
"""
|
||||
return self.db_type(connection)
|
||||
|
||||
def db_parameters(self, connection):
|
||||
"""
|
||||
Extension of db_type(), providing a range of different return
|
||||
|
@ -960,6 +968,9 @@ class AutoField(Field):
|
|||
params={'value': value},
|
||||
)
|
||||
|
||||
def rel_db_type(self, connection):
|
||||
return IntegerField().db_type(connection=connection)
|
||||
|
||||
def validate(self, value, model_instance):
|
||||
pass
|
||||
|
||||
|
@ -2072,7 +2083,24 @@ class NullBooleanField(Field):
|
|||
return super(NullBooleanField, self).formfield(**defaults)
|
||||
|
||||
|
||||
class PositiveIntegerField(IntegerField):
|
||||
class PositiveIntegerRelDbTypeMixin(object):
|
||||
|
||||
def rel_db_type(self, connection):
|
||||
"""
|
||||
Return the data type that a related field pointing to this field should
|
||||
use. In most cases, a foreign key pointing to a positive integer
|
||||
primary key will have an integer column data type but some databases
|
||||
(e.g. MySQL) have an unsigned integer type. In that case
|
||||
(related_fields_match_type=True), the primary key should return its
|
||||
db_type.
|
||||
"""
|
||||
if connection.features.related_fields_match_type:
|
||||
return self.db_type(connection)
|
||||
else:
|
||||
return IntegerField().db_type(connection=connection)
|
||||
|
||||
|
||||
class PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField):
|
||||
description = _("Positive integer")
|
||||
|
||||
def get_internal_type(self):
|
||||
|
@ -2084,7 +2112,7 @@ class PositiveIntegerField(IntegerField):
|
|||
return super(PositiveIntegerField, self).formfield(**defaults)
|
||||
|
||||
|
||||
class PositiveSmallIntegerField(IntegerField):
|
||||
class PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField):
|
||||
description = _("Positive small integer")
|
||||
|
||||
def get_internal_type(self):
|
||||
|
|
|
@ -18,10 +18,7 @@ from django.utils.functional import cached_property, curry
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.version import get_docs_version
|
||||
|
||||
from . import (
|
||||
AutoField, Field, IntegerField, PositiveIntegerField,
|
||||
PositiveSmallIntegerField,
|
||||
)
|
||||
from . import Field
|
||||
from .related_descriptors import (
|
||||
ForwardManyToOneDescriptor, ManyToManyDescriptor,
|
||||
ReverseManyToOneDescriptor, ReverseOneToOneDescriptor,
|
||||
|
@ -935,19 +932,7 @@ class ForeignKey(ForeignObject):
|
|||
return super(ForeignKey, self).formfield(**defaults)
|
||||
|
||||
def db_type(self, connection):
|
||||
# The database column type of a ForeignKey is the column type
|
||||
# of the field to which it points. An exception is if the ForeignKey
|
||||
# points to an AutoField/PositiveIntegerField/PositiveSmallIntegerField,
|
||||
# in which case the column type is simply that of an IntegerField.
|
||||
# If the database needs similar types for key fields however, the only
|
||||
# thing we can do is making AutoField an IntegerField.
|
||||
rel_field = self.target_field
|
||||
if (isinstance(rel_field, AutoField) or
|
||||
(not connection.features.related_fields_match_type and
|
||||
isinstance(rel_field, (PositiveIntegerField,
|
||||
PositiveSmallIntegerField)))):
|
||||
return IntegerField().db_type(connection=connection)
|
||||
return rel_field.db_type(connection=connection)
|
||||
return self.target_field.rel_db_type(connection=connection)
|
||||
|
||||
def db_parameters(self, connection):
|
||||
return {"type": self.db_type(connection), "check": []}
|
||||
|
|
|
@ -374,14 +374,14 @@ For example::
|
|||
else:
|
||||
return 'timestamp'
|
||||
|
||||
The :meth:`~Field.db_type` method is called by Django when the framework
|
||||
constructs the ``CREATE TABLE`` statements for your application -- that is,
|
||||
when you first create your tables. It is also called when constructing a
|
||||
``WHERE`` clause that includes the model field -- that is, when you retrieve data
|
||||
using QuerySet methods like ``get()``, ``filter()``, and ``exclude()`` and have
|
||||
the model field as an argument. 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.
|
||||
The :meth:`~Field.db_type` and :meth:`~Field.rel_db_type` methods are called by
|
||||
Django when the framework constructs the ``CREATE TABLE`` statements for your
|
||||
application -- that is, when you first create your tables. The methods are also
|
||||
called when constructing a ``WHERE`` clause that includes the model field --
|
||||
that is, when you retrieve data using QuerySet methods like ``get()``,
|
||||
``filter()``, and ``exclude()`` and have the model field as an argument. They
|
||||
are 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,
|
||||
|
@ -423,6 +423,23 @@ 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.
|
||||
|
||||
The :meth:`~Field.rel_db_type` method is called by fields such as ``ForeignKey``
|
||||
and ``OneToOneField`` that point to another field to determine their database
|
||||
column data types. For example, if you have an ``UnsignedAutoField``, you also
|
||||
need the foreign keys that point to that field to use the same data type::
|
||||
|
||||
# MySQL unsigned integer (range 0 to 4294967295).
|
||||
class UnsignedAutoField(models.AutoField):
|
||||
def db_type(self, connection):
|
||||
return 'integer UNSIGNED AUTO_INCREMENT'
|
||||
|
||||
def rel_db_type(self, connection):
|
||||
return 'integer UNSIGNED'
|
||||
|
||||
.. versionadded:: 1.10
|
||||
|
||||
The :meth:`~Field.rel_db_type` method was added.
|
||||
|
||||
.. _converting-values-to-python-objects:
|
||||
|
||||
Converting values to Python objects
|
||||
|
|
|
@ -1701,7 +1701,8 @@ Field API reference
|
|||
|
||||
where the arguments are interpolated from the field's ``__dict__``.
|
||||
|
||||
To map a ``Field`` to a database-specific type, Django exposes two methods:
|
||||
To map a ``Field`` to a database-specific type, Django exposes several
|
||||
methods:
|
||||
|
||||
.. method:: get_internal_type()
|
||||
|
||||
|
@ -1717,6 +1718,16 @@ Field API reference
|
|||
|
||||
See :ref:`custom-database-types` for usage in custom fields.
|
||||
|
||||
.. method:: rel_db_type(connection)
|
||||
|
||||
.. versionadded:: 1.10
|
||||
|
||||
Returns the database column data type for fields such as ``ForeignKey``
|
||||
and ``OneToOneField`` that point to the :class:`Field`, taking
|
||||
into account the ``connection``.
|
||||
|
||||
See :ref:`custom-database-types` for usage in custom fields.
|
||||
|
||||
There are three main situations where Django needs to interact with the
|
||||
database backend and fields:
|
||||
|
||||
|
|
|
@ -202,6 +202,10 @@ Models
|
|||
accessible as a descriptor on the proxied model class and may be referenced in
|
||||
queryset filtering.
|
||||
|
||||
* The new :meth:`Field.rel_db_type() <django.db.models.Field.rel_db_type>`
|
||||
method returns the database column data type for fields such as ``ForeignKey``
|
||||
and ``OneToOneField`` that point to another field.
|
||||
|
||||
* The :attr:`~django.db.models.Func.arity` class attribute is added to
|
||||
:class:`~django.db.models.Func`. This attribute can be used to set the number
|
||||
of arguments the function accepts.
|
||||
|
|
Loading…
Reference in New Issue