Setting default value for Foreign Key attribute

后端 未结 8 727
后悔当初
后悔当初 2020-12-08 01:32

What is the best way to set a default value for a foreign key field in a model? Suppose I have two models, Student and Exam with student having

相关标签:
8条回答
  • 2020-12-08 02:03

    I would modify @vault's answer above slightly (this may be a new feature). It is definitely desirable to refer to the field by a natural name. However instead of overriding the Manager I would simply use the to_field param of 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')
    
    0 讨论(0)
  • 2020-12-08 02:03

    the best way I know is to use lambdas

    class TblSearchCase(models.Model):
        weights = models.ForeignKey('TblSearchWeights', models.DO_NOTHING, default=lambda: TblSearchWeights.objects.get(weight_name='value_you_want'))
    

    so you can specify the default row..

    default=lambda: TblSearchWeights.objects.get(weight_name='value_you_want')
    
    0 讨论(0)
  • 2020-12-08 02:06

    You could use this pattern:

    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)
    

    Of course you need to be sure that there is a row in the table of Other. You should use a datamigration to be sure it exists.

    0 讨论(0)
  • 2020-12-08 02:08

    As already implied in @gareth's answer, hard-coding a default id value might not always be the best idea:

    If the id value does not exist in the database, you're in trouble. Even if that specific id value does exist, the corresponding object may change. In any case, when using a hard-coded id value, you'd have to resort to things like data-migrations or manual editing of existing database content.

    To prevent that, you could use get_or_create() in combination with a unique field (other than id).

    Here's how I would do it:

    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)
    

    Here an Exam.title field is used to get a unique object, and an Exam.description field illustrates how we can use the defaults argument (for get_or_create) to fully specify the default Exam object.

    Note that we return a pk, as suggested by the docs:

    For fields like ForeignKey that map to model instances, defaults should be the value of the field they reference (pk unless to_field is set) instead of model instances.

    Also note that default callables are evaluated in Model.__init__() (source). So, if your default value depends on another field of the same model, or on the request context, or on the state of the client-side form, you should probably look elsewhere.

    0 讨论(0)
  • 2020-12-08 02:10

    In my case, I wanted to set the default to any existing instance of the related model. Because it's possible that the Exam with id 1 has been deleted, I've done the following:

    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)
    

    If exam_taken doesn't exist, django.db.models.fields.related_descriptors.RelatedObjectDoesNotExist will be raised when a attempting to access it.

    0 讨论(0)
  • 2020-12-08 02:12

    I'm looking for the solution in Django Admin, then I found this:

    class YourAdmin(admin.ModelAdmin)
    
        def get_changeform_initial_data(self, request):
            return {'owner': request.user}
    

    this also allows me to use the current user.

    see django docs

    0 讨论(0)
提交回复
热议问题