Setting default value for Foreign Key attribute

烈酒焚心 提交于 2019-11-28 18:32:15

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.

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')

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')

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.

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!