wake-up-neo.com

Festlegen des Standardwerts für das Fremdschlüsselattribut

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.

53

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.

32
Gareth

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

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

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.

6
connorbode

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.

4
guettli