Django ModelまたはAdminModelのForeignKeyフィールドにデフォルト値を設定するにはどうすればよいですか?
このようなもの(もちろんこれは機能しません)...
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以上の場合、
ForeignKeyオブジェクトを作成して保存するだけです。 「デフォルト」の値には、デフォルトでリンクするオブジェクトのIDを指定できます。
例えば、
created_by = models.ForeignKey(User, default=1)
Django 1.7で機能するソリューションを次に示します。フィールド定義でデフォルトを提供する代わりに、それをnull可能として設定しますが、「保存」関数をオーバーライドして、最初にそれを埋めます(それがnullの場合):
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の開発バージョンを使用している場合、_ formfield_for_foreignkey()
メソッドをAdminModel
に実装してデフォルト値を設定できます。
@o_cと同様にこれを行いましたが、単なるpk
ではなくget_or_create
を使用します。
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)
def get_user_default_id():
return 1
created_by = models.ForeignKey(User, default=get_user_default_id)
私に関しては、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で作業することだとは思わない。
Django> = 1.7の場合、ForeignKeyフィールドのデフォルトを2つの異なる方法で設定できます。
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)
参照:
これは o_c からの回答を少し変更したものです。データベースへのヒットが1つ減るはずです。 saveメソッドでは、self.a = Foo.objects.get(id = 1)の代わりにself.a_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)
ラムダ関数の代わりに部分関数を使用します。 Lambda関数はシリアル化されていないため、移行時にエラーが発生します。
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 ))
Settings.pyファイルには、setting.AUTH_USER_MODELに関連する設定が必要です。
あなたは以下の文書を見ることができます:
" https://docs.djangoproject.com/en/1.10/topics/auth/customizing/#substituting-a-custom-user-model "
より良い解決策を見つけるためのすべての反復の中で、小さな関数を作成すると、タスクの複雑さが大幅に解決されることがわかりました。一部のソリューションが古いか、または新しい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)
モデル管理者の 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)