2012-02-16 20 views
36

¿Cuál es la mejor manera de establecer un valor predeterminado para un campo de clave externa en un modelo? Supongamos que tengo dos modelos, Estudiante y Examen con el estudiante que tiene exam_taken como clave externa. ¿Cómo idealmente establecería un valor predeterminado para él? Aquí hay un registro de mi esfuerzoConfiguración del valor predeterminado para el atributo de clave externa

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

Funciona, pero tengo la corazonada de que hay una mejor manera.

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

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

De here, pero falla con tablas no existe error al sincronizar.

Cualquier ayuda sería apreciada.

+0

qué tal: http://stackoverflow.com/questions/937954/how-do-you-specify-a-default-for-a-django-foreignkey-model-or-adminmodel-field –

+2

@TomIngram no it no deberia! – balazs

+0

@NitzanTomer Es para un AdminModelField. Lo había visto anteriormente. – primpap

Respuesta

18

En sus dos ejemplos, está codificando la identificación de la instancia predeterminada. Si eso es inevitable, simplemente establecería una constante.

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

Menos código, y nombrar la constante lo hace más legible.

+0

Me sale el siguiente error: 'TypeError: Los argumentos adicionales deben llamarse _ , get 'default'' Con código: 'category_id = db.Column (db.Integer, db.ForeignKey (" category.id ", default = 1), primary_key = True)' ¿Puede ayudarnos? – ChickenFeet

+0

Por cierto, hay dos PK, por lo que la clave seguirá siendo única. – ChickenFeet

6

que utilizan claves naturales para adoptar un enfoque más natural:

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

Intenté esto en Django 1.6 pero me aparece el error "Literal inválido para int() con base 10: 'IT'. (Mi cadena es diferente, pero se entiende la idea) – Seth

+2

Esto funcionó bien, sin embargo, y parece más Pythonic: 'default = lambda: Country.objects.filter (sigla = 'IT'). first()' – Seth

+0

Extraño, recuerdo haber probado esto con django 1.6. Google buscando encontré que es un problema de tupla, intente: 'def get_by_natural_key (self, sigla): return (self.get (sigla = sigla),) 'o también con' default = ('IT',) '. Solo estoy adivinando;) – vault

2

Usted podría utilizar este patrón:

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) 

Por supuesto que necesita para asegurarse de que no hay una fila en la tabla de Other. Debe usar una migración de datos para asegurarse de que existe.

1

En mi caso, quería establecer el valor predeterminado para cualquier instancia existente del modelo relacionado. Debido a que es posible que el Exam con id 1 ha sido eliminado, he hecho lo siguiente:

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) 

Si exam_taken no existe, django.db.models.fields.related_descriptors.RelatedObjectDoesNotExist serán levantados cuando un intento de acceder a él.

Cuestiones relacionadas