My question is closely related to this question, yet subtly different.
Given the following Django models:
class Country(models.Model):
code = models.CharField(primary_key=True)
class Person(models.Model):
country = models.ForeignKey(Country, on_delete=models.CASCADE)
Note that I have specified a custom primary key field on Country
called code
. The Country
class should have no id
field or attribute. This is working fine.
And of course I want the Person
class's foreign key to Country
to use the code
field. That is also working fine. So far so good.
However, I also really want the underlying column name in the Person
table to be exactly country_code
. NOT country_id
. So I added the db_column
field argument:
class Person(models.Model):
country = models.ForeignKey(
Country,
on_delete=models.CASCADE,
db_column='country_code',
)
Now the column name is correctly named country_code
instead of country_id
. So far so good.
Now. In my python code, I want to be able to access a country via a person in the normal way:
person = Person.objects.get(...)
country = person.country
BUT, I want to be able to access the country code pk via a person using country_code
, not country_id
, like so:
person = Person.objects.get(...)
country_code = person.country_code
And I also want to be able to create Person objects with the country_code
argument, not country_id
:
person = Person(country_code='foo')
And I also want to be able to query for Person objects with the country_code
argument, not country_id
:
people = Person.objects.filter(country_code='foo')
There should be no person.country_id
attribute, field, or column. Only person.country
and person.country_code
. And yes, I want that field/attribute/column to be called exactly person.country_code
, NOT person.country_id
even if it holds the same value. That's the exact name I want in both Python and in the RDBMS.
So far, I have not been able to achieve this. I have tried tinkering with adding the to_field
argument to the Person.country
field declaration like so:
class Person(models.Model):
country = models.ForeignKey(
Country,
on_delete=models.CASCADE,
to_field='code',
db_column='country_code',
)
This does not seem have the desired effect.
Is it possible to change a model's foreign key field attribute name (as well as the underlying column name) in Django?
This doesn't seem to me like like such a strange thing to do. Maybe I'm wrong. Is this possible? Is this just too hard/non-standard to be worth it? Am I asking for trouble?