问题
What is the best way to set a default value for a foreign key field in a model? Suppose I have two models, Student and Exam with student having exam_taken as foreign key. How would I ideally set a default value for it? Here's a log of my effort
class Student(models.Model):
....
.....
exam_taken = models.ForeignKey("Exam", default=1)
Works, but have a hunch there's a better way.
def get_exam():
return Exam.objects.get(id=1)
class Student(models.Model):
....
.....
exam_taken = models.ForeignKey("Exam", default=get_exam)
From here, but fails with tables does not exist error while syncing.
Any help would be appreciated.
回答1:
In both of your examples, you're hard-coding the id of the default instance. If that's inevitable, I'd just set a constant.
DEFAULT_EXAM_ID = 1
class Student(models.Model):
...
exam_taken = models.ForeignKey("Exam", default=DEFAULT_EXAM_ID)
Less code, and naming the constant makes it more readable.
回答2:
I use natural keys to adopt a more natural approach:
<app>/models.py
from django.db import models
class CountryManager(models.Manager):
"""Enable fixtures using self.sigla instead of `id`"""
def get_by_natural_key(self, sigla):
return self.get(sigla=sigla)
class Country(models.Model):
objects = CountryManager()
sigla = models.CharField(max_length=5, unique=True)
def __unicode__(self):
return u'%s' % self.sigla
class City(models.Model):
nome = models.CharField(max_length=64, unique=True)
nation = models.ForeignKey(Country, default='IT')
回答3:
I would modify @vault's answer above slightly (this may be a new feature). It is definitely desirable to refer to the field by a natural name. However instead of overriding the Manager
I would simply use the to_field
param of ForeignKey
:
class Country(models.Model):
sigla = models.CharField(max_length=5, unique=True)
def __unicode__(self):
return u'%s' % self.sigla
class City(models.Model):
nome = models.CharField(max_length=64, unique=True)
nation = models.ForeignKey(Country, to_field='sigla', default='IT')
回答4:
In my case, I wanted to set the default to any existing instance of the related model. Because it's possible that the Exam
with id 1
has been deleted, I've done the following:
class Student(models.Model):
exam_taken = models.ForeignKey("Exam", blank=True)
def save(self, *args, **kwargs):
try:
self.exam_taken
except:
self.exam_taken = Exam.objects.first()
super().save(*args, **kwargs)
If exam_taken
doesn't exist, django.db.models.fields.related_descriptors.RelatedObjectDoesNotExist
will be raised when a attempting to access it.
回答5:
You could use this pattern:
class Other(models.Model):
DEFAULT_PK=1
name=models.CharField(max_length=1024)
class FooModel(models.Model):
other=models.ForeignKey(Other, default=Other.DEFAULT_PK)
Of course you need to be sure that there is a row in the table of Other
. You should use a datamigration to be sure it exists.
来源:https://stackoverflow.com/questions/9311996/setting-default-value-for-foreign-key-attribute