Ответ 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) )
Как установить значение по умолчанию в поле ForeignKey в модели django или в AdminModel?
Что-то вроде этого (но, конечно, это не работает)...
created_by = models.ForeignKey(User, default=request.user)
Я знаю, что могу "обмануть" его в представлении, но с точки зрения AdminModel это не представляется возможным.
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) )
Вот решение, которое будет работать в 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)
Для django 1.7 или больше,
Просто создайте объект ForeignKey и сохраните его. Значение по умолчанию может быть идентификатором объекта, который по умолчанию должен быть связан.
Например,
created_by = models.ForeignKey(User, default=1)
Если вы используете версию Django для разработки, вы можете реализовать метод formfield_for_foreignkey()
в AdminModel
чтобы установить значение по умолчанию.
Я сделал это аналогично @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)
Что касается меня, то для 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.
def get_user_default_id():
return 1
created_by = models.ForeignKey(User, default=get_user_default_id)
Это небольшая модификация ответа 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)
Для 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)
Рекомендации:
Вместо лямбда-функции используйте частичную функцию. Лямбда-функция не является сериализацией и, следовательно, выдает ошибку при миграции.
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 ))
У вас должны быть настройки, связанные с setting.AUTH_USER_MODEL в файле settings.py.
Вы можете посмотреть ниже документ:
" https://docs.djangoproject.com/en/1.10/topics/auth/customizing/#substituting-a-custom-user-model "
Вы можете переопределить метод 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)
Из всех итераций, чтобы найти лучшее решение, я обнаружил, что создание небольшой функции существенно решит сложность задачи. Потому что некоторые решения устарели или больше поддерживаются в новых версиях 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)
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)