33

如何在 django 模型或 AdminModel 中的 ForeignKey 字段上设置默认值?

像这样的东西(但当然这不起作用)......

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

我知道我可以在视图中“欺骗”它,但就 AdminModel 而言,这似乎是不可能的。

4

14 回答 14

38
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) )
于 2012-11-26T09:46:25.437 回答
16

对于 django 1.7 或更高版本,

只需创建一个 ForeignKey 对象并保存它。“默认”值可以是默认链接的对象的 ID。

例如,

created_by = models.ForeignKey(User, default=1)
于 2016-12-11T18:32:29.063 回答
11

这是一个适用于 Django 1.7 的解决方案。与其在字段定义中提供默认值,不如将其设置为可空,但覆盖“保存”函数以在第一次填充它(当它为空时):

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)
于 2016-03-10T21:41:57.140 回答
7

我的做法与@o_c 类似,但我宁愿使用get_or_create而不仅仅是 plain 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)
于 2016-09-24T12:41:06.740 回答
6

如果你使用的是 Django 的开发版本,你可以实现你的formfield_for_foreignkey()方法AdminModel来设置一个默认值。

于 2009-06-02T06:28:02.173 回答
2

至于我,对于 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 一起工作。

于 2015-03-23T04:26:23.920 回答
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)
于 2016-10-25T07:44:36.697 回答
1

对于 Django >= 1.7,您可以通过两种不同的方式为 ForeignKey 字段设置默认值:

1) 直接作为整数

DEFAULT_CREATED_BY_USER = 42

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

2) 作为返回整数的非 lambda 可调用对象

您还可以使用可解析为完整模块路径的可调用对象。这意味着 lambdas 不起作用。但这将:

def default_created_by_user():
    return 42

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

参考:

于 2018-08-28T08:12:38.733 回答
1
def get_user_default_id():
    return 1

created_by = models.ForeignKey(User, default=get_user_default_id)
于 2016-03-06T03:46:27.103 回答
0

在寻找更好解决方案的所有迭代中,我发现创建一个小函数将大大解决任务的复杂性。因为一些解决方案在较新的 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)
于 2019-08-28T19:08:45.473 回答
0

您应该在 settings.py 文件中有与 setting.AUTH_USER_MODEL 相关的设置。

您可以查看以下文档:

https://docs.djangoproject.com/en/1.10/topics/auth/customizing/#substituting-a-custom-user-model

于 2019-01-28T08:47:01.543 回答
0

使用偏函数代替 lambda 函数。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 ))
于 2019-01-17T12:13:20.460 回答
0

您可以覆盖模型管理员的get_form方法。

管理员.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)
于 2019-01-29T10:26:49.467 回答
-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)
于 2015-09-30T14:09:23.987 回答