Wie kann ein Standardwert für ein Fremdschlüsselfeld in einem Modell am besten festgelegt werden? Angenommen, ich habe zwei Modelle, Student und Exam, wobei der Student exam_taken als Fremdschlüssel hat. Wie würde ich im Idealfall einen Standardwert dafür einstellen? Hier ist ein Protokoll meiner Bemühungen
class Student(models.Model):
....
.....
exam_taken = models.ForeignKey("Exam", default=1)
Funktioniert, aber es gibt einen besseren Weg.
def get_exam():
return Exam.objects.get(id=1)
class Student(models.Model):
....
.....
exam_taken = models.ForeignKey("Exam", default=get_exam)
Von hier , aber bei fehlgeschlagenen Tabellen ist kein Fehler beim Synchronisieren vorhanden.
Jede Hilfe wäre dankbar.
In beiden Beispielen codieren Sie die ID der Standardinstanz fest. Wenn das unvermeidlich ist, würde ich einfach eine Konstante setzen.
DEFAULT_EXAM_ID = 1
class Student(models.Model):
...
exam_taken = models.ForeignKey("Exam", default=DEFAULT_EXAM_ID)
Weniger Code und die Benennung der Konstante machen sie lesbarer.
Ich benutze natürliche Schlüssel, um einen natürlicheren Ansatz zu verfolgen:
<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')
Ich würde die Antwort von @ vault oben leicht ändern (dies könnte eine neue Funktion sein). Es ist definitiv wünschenswert, das Feld mit einem natürlichen Namen zu bezeichnen. Anstatt jedoch das Manager
zu überschreiben, würde ich einfach das to_field
Parameter von 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 meinem Fall wollte ich die Standardeinstellung auf eine vorhandene Instanz des zugehörigen Modells setzen. Weil es möglich ist, dass der Exam
mit der ID 1
wurde gelöscht, ich habe Folgendes getan:
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)
Wenn exam_taken
existiert nicht, Django.db.models.fields.related_descriptors.RelatedObjectDoesNotExist
wird ausgelöst, wenn versucht wird, darauf zuzugreifen.
Sie könnten dieses Muster verwenden:
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)
Natürlich müssen Sie sicherstellen, dass die Tabelle von Other
eine Zeile enthält. Sie sollten eine Datenmigration verwenden, um sicherzustellen, dass sie vorhanden ist.