#11265: ForeignKey/OneToOneField should support user-defined id attribute name
-----------------------------------------------------+----------------------
Reporter: dstora | Owner: nobody
Status: new | Milestone:
Component: Database layer (models, ORM) | Version: 1.0
Keywords: foreign key ForeignKey OneToOneField id | Stage: Unreviewed
Has_patch: 1 |
-----------------------------------------------------+----------------------
Currently, when defining a !ForeignKey/OneToOneField field XXX, Django
automatically defines a XXX_id attribute to store the id value.[[BR]]
However, it is sometimes desirable to decide of the name as XXX_id may not
be the most appropriate.
----
Let's take the following example:
- I initially have a table "Payment" with a "ccy_code" field designating a
3-letter currency code.
My model definition looks like:
{{{
from django.db import model
class Payment(models.Model):
# ...
ccy_code = models.CharField(max_length=3)
}}}
In my python code I refer to the currency code as follows:
{{{
p = Payment()
#...
print p.ccy_code
}}}
- Later, I decide to actually create a "Currency" table to hold some
information about currencies.
And I also decide to define a foreign key constraint from "Payment" to
"Currency".
My model now looks like:
{{{
from django.db import model
class Currency(models.Model):
ccy_code = models.CharField(max_length=3, primary_key=True)
#...
class Payment(models.Model):
# ...
ccy = models.ForeignKey(Currency, to_field="ccy_code",
db_column="ccy_code")
}}}
The problem here is that my existing Python code is broken, because
"ccy_code" is not defined anymore for "Payment".
Django has instead define a "ccy_id" attribute.
----
Based on the principle that defining things like foreign keys should only
add functionality (and not remove any) it seems quite important to me that
one can choose the id attribute name.[[BR]]
[[BR]]
This can be achieved by adding an optional keyword argument to
!ForeignKey/OneToOneField constructors (here I decided to call it
"id_attr_name").[[BR]]
The implementation of this feature is pretty small and fully backward-
compatible.[[BR]]
Here is the SVN diff against trunk:
{{{
Index: related.py
===================================================================
--- related.py (revision 10924)
+++ related.py (working copy)
@@ -660,6 +660,7 @@
class ForeignKey(RelatedField, Field):
empty_strings_allowed = False
def __init__(self, to, to_field=None, rel_class=ManyToOneRel,
**kwargs):
+ self.__id_attr_name = kwargs.pop('id_attr_name', None)
try:
to_name = to._meta.object_name.lower()
except AttributeError: # to._meta doesn't exist, so it must be
RECURSIVE_RELATIONSHIP_CONSTANT
@@ -679,7 +680,10 @@
self.db_index = True
def get_attname(self):
- return '%s_id' % self.name
+ if self.__id_attr_name:
+ return self.__id_attr_name
+ else:
+ return '%s_id' % self.name
def get_validator_unique_lookup_type(self):
return '%s__%s__exact' % (self.name,
self.rel.get_related_field().name)
}}}
In my example, I could then define my model like:
{{{
from django.db import model
class Currency(models.Model):
ccy_code = models.CharField(max_length=3, primary_key=True)
#...
class Payment(models.Model):
# ...
ccy = models.ForeignKey(Currency, to_field="ccy_code",
db_column="ccy_code", id_attr_name="ccy_code")
}}}
--
Ticket URL: <http://code.djangoproject.com/ticket/11265>
Django <http://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/django-updates?hl=en
-~----------~----~----~----~------~----~------~--~---