web-dev-qa-db-ja.com

外部キー属性のデフォルト値の設定

モデルの外部キーフィールドにデフォルト値を設定する最良の方法は何ですか?私は、StudentとExamの2つのモデルを持っているとします。その場合、extuit_takenが外部キーになります。どのようにデフォルト値を理想的に設定しますか?ここに私の努力のログがあります

class Student(models.Model):
   ....
   .....
   exam_taken = models.ForeignKey("Exam", default=1)

動作しますが、より良い方法があります。

def get_exam():
    return Exam.objects.get(id=1)

class Student(models.Model):
    ....
    .....
    exam_taken = models.ForeignKey("Exam", default=get_exam)

here からですが、同期中にテーブルが存在しないというエラーが発生します。

任意の助けをいただければ幸いです。

53

どちらの例でも、デフォルトインスタンスのIDをハードコーディングしています。それが避けられない場合は、定数を設定するだけです。

DEFAULT_EXAM_ID = 1
class Student(models.Model):
    ...
    exam_taken = models.ForeignKey("Exam", default=DEFAULT_EXAM_ID)

コードが少なく、定数に名前を付けると読みやすくなります。

32
Gareth

自然なキーを使用して、より自然なアプローチを採用します。

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

上記の@vaultの答えを少し変更します(これは新しい機能の可能性があります)。フィールドを自然名で参照することは間違いなく望ましいことです。ただし、Managerをオーバーライドする代わりに、単にto_fieldForeignKeyのパラメーター:

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

私の場合、デフォルトを関連モデルの既存インスタンスに設定したかったのです。 Examがid 1は削除されました。次のことを行いました。

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)

exam_takenは存在しません、Django.db.models.fields.related_descriptors.RelatedObjectDoesNotExistは、アクセスしようとすると発生します。

6
connorbode

次のパターンを使用できます。

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)

もちろん、Otherのテーブルに行があることを確認する必要があります。データ移行を使用して、それが存在することを確認する必要があります。

4
guettli