Was ist der beste Weg, um einen Standardwert für ein Fremdschlüsselfeld in einem Modell festzulegen? Angenommen, ich habe zwei Modelle Student
und einen Exam
Schüler exam_taken
als Fremdschlüssel. Wie würde ich idealerweise einen Standardwert dafür festlegen? Hier ist ein Protokoll meiner Bemühungen
class Student(models.Model):
....
.....
exam_taken = models.ForeignKey("Exam", default=1)
Funktioniert, aber ahnen Sie, 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)
Dies schlägt jedoch fehl, da bei der Synchronisierung kein Fehler vorliegt.
Jede Hilfe wäre dankbar.
django
foreign-keys
default
Ursprünglicher Pappachan
quelle
quelle
default=get_exam()
ruftget_exam
sofort und den Wert fest, währenddefault=get_exam
speichert die Methode , die später jedes Mal aufgerufen werden , würde dasdefault
Attribut verwendet wird, um den Wert zu diesem Zeitpunkt zu erhalten. Es wird oft mit Datetime verwendet, das heißtdefault=datetime.now
, nichtdefault=datetime.now()
.Antworten:
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 besser lesbar.
quelle
TypeError: Additional arguments should be named <dialectname>_<argument>, got 'default'
Mit Code:category_id = db.Column(db.Integer, db.ForeignKey("category.id", default=1), primary_key=True)
Können Sie bitte helfen?Ich würde die Antwort von @ vault oben leicht ändern (dies könnte eine neue Funktion sein). Es ist auf jeden Fall wünschenswert, das Feld mit einem natürlichen Namen zu bezeichnen. Anstatt das zu überschreiben,
Manager
würde ich einfach dento_field
Parameter verwendenForeignKey
: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')
quelle
Ich benutze natürliche Schlüssel, um einen natürlicheren Ansatz zu wählen:
<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')
quelle
default=lambda: Country.objects.filter(sigla='IT').first()
def get_by_natural_key(self, sigla): return (self.get(sigla=sigla),)
oder auch mitdefault=('IT',)
. IchIn meinem Fall wollte ich die Standardeinstellung für eine vorhandene Instanz des zugehörigen Modells festlegen . Da es möglich ist, dass die
Exam
with-ID1
gelöscht wurde, habe ich 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
nicht vorhanden,django.db.models.fields.related_descriptors.RelatedObjectDoesNotExist
wird beim Versuch, darauf zuzugreifen, ausgelöst.quelle
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 sicher sein, dass die Tabelle von eine Zeile enthält
Other
. Sie sollten eine Datenmigration verwenden, um sicherzustellen, dass sie vorhanden ist.quelle
Wie bereits in der Antwort von @ gareth angedeutet ,
id
ist es möglicherweise nicht immer die beste Idee, einen Standardwert fest zu codieren :Wenn der
id
Wert nicht in der Datenbank vorhanden ist, treten Probleme auf. Selbst wenn dieser bestimmteid
Wert vorhanden ist, kann sich das entsprechende Objekt ändern. In jedem Fall müsstenid
Sie bei Verwendung eines fest codierten Werts auf Datenmigrationen oder die manuelle Bearbeitung vorhandener Datenbankinhalte zurückgreifen.Um dies zu verhindern, können Sie get_or_create () in Kombination mit einem
unique
anderen Feld als verwendenid
.So würde ich es machen:
from django.db import models class Exam(models.Model): title = models.CharField(max_length=255, unique=True) description = models.CharField(max_length=255) @classmethod def get_default_pk(cls): exam, created = cls.objects.get_or_create( title='default exam', defaults=dict(description='this is not an exam')) return exam.pk class Student(models.Model): exam_taken = models.ForeignKey(to=Exam, on_delete=models.CASCADE, default=Exam.get_default_pk)
Hier wird ein
Exam.title
Feld verwendet, um ein eindeutiges Objekt abzurufen, und einExam.description
Feld zeigt, wie wir dasdefaults
Argument (forget_or_create
) verwenden können, um das Standardobjekt vollständig anzugebenExam
.Beachten Sie, dass wir a zurückgeben
pk
, wie in den Dokumenten vorgeschlagen :Beachten Sie auch, dass
default
Callables inModel.__init__()
( Quelle ) ausgewertet werden . Wenn Ihr Standardwert also von einem anderen Feld desselben Modells oder vom Anforderungskontext oder vom Status des clientseitigen Formulars abhängt, sollten Sie wahrscheinlich woanders suchen .quelle
get_default_user_role
wie in Ihrem Beispiel den Rückruf als Standardparameter verwende. Also , wenn ich keine Migrationen habe ich bekamno such table: users_role
aufpython manage.py makemigration
. Aber wenn ichrole field
im Benutzermodell kommentiere undrun makemigrations
- ist das kein Problem. Nach dem, was ich auskommentiererole field
undrun migrations
wieder ohne Probleme. Vielleicht kannst du mich damit aufhalten?Ich suche nach der Lösung in Django Admin , dann habe ich Folgendes gefunden:
class YourAdmin(admin.ModelAdmin) def get_changeform_initial_data(self, request): return {'owner': request.user}
Dadurch kann ich auch den aktuellen Benutzer verwenden.
Siehe Django-Dokumente
quelle
Der beste Weg, den ich kenne, ist die Verwendung von Lambdas
class TblSearchCase(models.Model): weights = models.ForeignKey('TblSearchWeights', models.DO_NOTHING, default=lambda: TblSearchWeights.objects.get(weight_name='value_you_want'))
So können Sie die Standardzeile angeben.
default=lambda: TblSearchWeights.objects.get(weight_name='value_you_want')
quelle