Как вы указываете значение по умолчанию для поля Django ForeignKey Model или AdminModel?

17

Как установить значение по умолчанию в поле ForeignKey в модели django или в AdminModel?

Что-то вроде этого (но, конечно, это не работает) ...

created_by = models.ForeignKey(User, default=request.user)

Я знаю, что могу «обмануть» его в представлении, но с точки зрения AdminModel это не представляется возможным.

    
задан T. Stone 02.06.2009 в 06:56
источник

9 ответов

25
class Foo(models.Model):
    a = models.CharField(max_length=42)

class Bar(models.Model):
    b = models.CharField(max_length=42)
    a = models.ForeignKey(Foo, default=lambda: Foo.objects.get(id=1) )
    
ответ дан Daniel Magnusson 26.11.2012 в 10:46
источник
  • Вы тот же парень из этой статьи? Если нет, подумайте о добавлении ссылки. djangodays.com/2009/05/11/... –  Paolo 29.01.2013 в 17:48
  • Использование имен символов в моделях для значений по умолчанию является довольно распространенным использованием. Я не помню сайт, но изменил фрагмент на более короткий шаблон. –  Daniel Magnusson 03.02.2013 в 03:34
  • Это должен быть принятый ответ. –  dhilipsiva 29.12.2014 в 05:21
  • Начиная с Django 1.7, если вы используете миграции Django, это решение больше не будет работать, поскольку Django не может сериализовать lambdas. docs.djangoproject.com/en/1.7/topics/migrations/... –  Eric Ressler 01.03.2015 в 18:46
  • @EricRessler Как можно заставить его работать в Django 1.10? –  MadPhysicist 04.12.2016 в 22:41
7

Вот решение, которое будет работать в Django 1.7. Вместо того, чтобы указывать значение по умолчанию в определении поля, установите его как null-able, но переопределите функцию «сохранить», чтобы заполнить его в первый раз (пока он равен нулю):

class Foo(models.Model):
    a = models.CharField(max_length=42)

class Bar(models.Model):
    b = models.CharField(max_length=42)
    a = models.ForeignKey(Foo, null=True)

    def save(self, *args, **kwargs):
        if self.a is None:  # Set default reference
            self.a = Foo.objects.get(id=1)
        super(Bar, self).save(*args, **kwargs)
    
ответ дан o_c 10.03.2016 в 22:41
источник
  • Вам действительно нужно сделать поле нулевым? Я думаю, что объект еще не сохранен, т.е. он еще не имеет идентификатора, он не «очищается», если вы не поставили «full_clean» перед супер (.. save .. Поэтому я бы изменил условие, если self.id - None: и он должен работать без null = True , –  Milano Slesarik 24.02.2017 в 15:49
  • @MilanoSlesarik, возможно, вы правы. Причина, по которой я его поставил в первую очередь, состоит в том, что это новое поле, которое я добавил к существующей модели (с существующими строками записи), и поэтому мне пришлось разрешить ей быть нулевым. –  o_c 26.02.2017 в 13:27
  • @o_c Не очень хорошая идея, так как save (..) не вызывается из пакетного обновления QuerySets .. если вы явно не зацикливаете на каждом возвращенном элементе и не вызываете save, что затем поражает цель использования пакетного обновления в первую очередь (и разработчики, как правило, забывают). –  strangetimes 23.05.2017 в 13:42
5

Для django 1.7 или больше,

Просто создайте объект ForeignKey и сохраните его. Значение по умолчанию может быть идентификатором объекта, который по умолчанию должен быть связан.

Например,

created_by = models.ForeignKey(User, default=1)
    
ответ дан Rahul Reddy Vemireddy 11.12.2016 в 19:32
источник
4

Если вы используете версию Django для разработки, вы можете реализовать formfield_for_foreignkey() на вашем AdminModel , чтобы установить значение по умолчанию.

    
ответ дан Steef 02.06.2009 в 08:28
источник
3

Я сделал это аналогично @o_c, но я предпочел бы использовать get_or_create , чем просто pk .

class UserSettings(models.Model):
    name = models.CharField(max_length=64, unique=True)
    # ... some other fields 

    @staticmethod
    def get_default_user_settings():
        user_settings, created = UserSettings.objects.get_or_create(
            name = 'Default settings'
        )
        return user_settings

class SiteUser(...):
    # ... some other fields

    user_settings = models.ForeignKey(
        to=UserSettings, 
        on_delete=models.SET_NULL, 
        null=True
    )

    def save(self, *args, **kwargs):
        if self.user_settings is None:
            self.user_settings = UserSettings.get_default_params()
        super(SiteUser, self).save(*args, **kwargs)
    
ответ дан Max Malysh 24.09.2016 в 14:41
источник
  • Этот ответ должен быть выше, потому что он просто и умный. –  Take_Care_ 04.09.2017 в 23:23
1

Что касается меня, то для Django 1.7 его работы просто pk:

category = models.ForeignKey(Category, editable=False, default=1)

, но помните, что миграция выглядит как

migrations.AlterField(
            model_name='item',
            name='category',
            field=models.ForeignKey(default=1, editable=False, to='item.Category'),
            preserve_default=True,
        ),

поэтому, я не думаю, что это должно работать с динамическим пользователем pk.

    
ответ дан Vermus 23.03.2015 в 05:26
источник
1

Это небольшое изменение в ответе от o_c . Он должен сэкономить вам одно попадание в базу данных. Обратите внимание, что в методе сохранения я использую self.a_id = 1 вместо self.a = Foo.objects.get (id = 1). Он имеет такой же эффект, не запрашивая Foo.

class Foo(models.Model):
    a = models.CharField(max_length=42)

class Bar(models.Model):
    b = models.CharField(max_length=42)
    a = models.ForeignKey(Foo, null=True)

    def save(self, *args, **kwargs):
        if self.a is None:  # Set default reference
            self.a_id = 1
        super(Bar, self).save(*args, **kwargs)
    
ответ дан Andrew Simpson 25.10.2016 в 09:44
источник
1
def get_user_default_id():
    return 1

created_by = models.ForeignKey(User, default=get_user_default_id)
    
ответ дан Philippos 06.03.2016 в 04:46
источник
  • добавьте описание. –  Shree Krishna 06.03.2016 в 05:09
-2
class table1(models.Model):
    id = models.AutoField(primary_key=True)
    agentname = models.CharField(max_length=20)

class table1(models.Model):
    id = models.AutoField(primary_key=True)
    lastname = models.CharField(max_length=20)
    table1 = models.ForeignKey(Property)
    
ответ дан Swayam Infologic 30.09.2015 в 16:09
источник
  • Пожалуйста, добавьте некоторое объяснение в код, почему это отвечает на вопрос? –  MeanGreen 30.09.2015 в 16:27