Подтвердить что ты не робот

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

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

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

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

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

4b9b3361

Ответ 1

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) )

Ответ 2

Вот решение, которое будет работать в 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)

Ответ 3

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

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

Например,

created_by = models.ForeignKey(User, default=1)

Ответ 4

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

Ответ 5

Я сделал это аналогично @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)

Ответ 6

Что касается меня, то для 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.

Ответ 7

def get_user_default_id():
    return 1

created_by = models.ForeignKey(User, default=get_user_default_id)

Ответ 8

Это небольшая модификация ответа 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)

Ответ 9

Для Django> = 1.7 вы можете установить значение по умолчанию для поля ForeignKey двумя разными способами:

1) Непосредственно как целое число

DEFAULT_CREATED_BY_USER = 42

class MyModel(Model):
    created_by = models.ForeignKey(User, default=DEFAULT_CREATED_BY_USER)

2) Как небальбда, вызываемый, возвращающий целое число

Вы также можете использовать вызываемый, который может быть разрешен для полного пути к модулю. Это означает, что лямбда не работает. Но это будет:

def default_created_by_user():
    return 42

class MyModel(Model):
    created_by = models.ForeignKey(User, default=default_created_by_user)

Рекомендации:

Ответ 10

Вместо лямбда-функции используйте частичную функцию. Лямбда-функция не является сериализацией и, следовательно, выдает ошибку при миграции.

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=partial(Foo.objects.get, id=1 ))

Ответ 12

Вы можете переопределить метод get_form администратора вашей модели.

admin.py

class YourModelAdmin(admin.ModelAdmin):
    def get_form(self, request, obj=None, **kwargs):
        form = super(YourModelAdmin, self).get_form(request, obj, **kwargs)
        form.base_fields['created_by'].initial = request.user
    return form

admin.site.register(YourModel, YourModelAdmin)

Ответ 13

Из всех итераций, чтобы найти лучшее решение, я обнаружил, что создание небольшой функции существенно решит сложность задачи. Потому что некоторые решения устарели или больше поддерживаются в новых версиях Django.

def get_request_user():
    # or any complex query result to set default value in ForeignKey
    return request.user.id

Затем вы можете передать вышеуказанную функцию в качестве аргумента в ForeignKey.

created_by = models.ForeignKey(User, default=get_request_user)

Ответ 14

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)