Python 如何为Django ForeignKey模型或AdminModel字段指定默认值?

Python 如何为Django ForeignKey模型或AdminModel字段指定默认值?,python,django-models,django-admin,Python,Django Models,Django Admin,如何在django模型或AdminModel中设置ForeignKey字段的默认值 像这样的东西(当然这不起作用) 我知道我可以在视图中“欺骗”它,但就AdminModel而言,这似乎是不可能的。如果您使用的是Django的开发版本,您可以在您的AdminModel上实现该方法来设置默认值。至于我,对于Django 1.7的工作,只需pk: class Foo(models.Model): a = models.CharField(max_length=42) class Bar(mo

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

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


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

如果您使用的是Django的开发版本,您可以在您的
AdminModel上实现该方法来设置默认值。

至于我,对于Django 1.7的工作,只需pk:

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) )
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中适用的解决方案。
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)
与其在字段定义中提供默认值,不如将其设置为null-able,但要覆盖“save”函数以在第一次填充它(当它为null时):


我这样做与@o_c类似,但我更愿意使用
get_或
而不是简单的
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)

这是对来自的答案的轻微修改。它应该能帮你在数据库上省下一笔钱。注意,在save方法中,我使用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对象并保存它。“default”值可以是默认情况下应该链接的对象的id

比如说,

created_by = models.ForeignKey(User, default=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可调用

DEFAULT_CREATED_BY_USER = 42

class MyModel(Model):
    created_by = models.ForeignKey(User, default=DEFAULT_CREATED_BY_USER)
您还可以使用可调用函数,该函数可以解析为完整的模块路径。这意味着lambdas不起作用。但这将:

def default_created_by_user():
    return 42

class MyModel(Model):
    created_by = models.ForeignKey(User, default=default_created_by_user)
参考资料:

  • (django文件)
  • (为什么lambdas会失败)

使用部分函数代替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 ))

您应该在settings.py文件中具有与setting.AUTH\u USER\u MODEL相关的设置

您可以查看以下文档:

“”

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

管理员

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)

你和这篇文章的作者是同一个人吗?如果没有,请考虑添加链接。在模型中使用符号名作为默认值是非常常见的用法。我不记得该站点,但将代码段更改为较短的模式。从Django 1.7开始,如果使用Django的迁移,此解决方案将不再有效,因为Django无法序列化lambda@EricRessler如何让它在Django 1.10中工作?@MadPhysician这种方法在更现代的Django版本中工作:请给代码添加一些解释,为什么这能回答这个问题?添加一些描述。你真的需要让字段为空吗?我认为,该对象还没有保存,即它还没有id,它还没有被“清理”,除非你在超链接前加上“完全清理”(…save..因此我将条件更改为if self.id为None:并且在不使用null=True的情况下应该可以工作。@MilanoSlesarik您可能是对的。我之所以将它放在那里,首先是因为它是我添加到现有模型(具有现有记录行)中的一个新字段,所以我必须允许它为null。@o_c作为save(..)不是一个好主意不是从批处理更新查询集调用的。除非您显式循环每个返回的项并调用save,否则这将首先破坏使用批处理更新的目的(开发人员往往会忘记)。这个答案应该更高,因为它简单而聪明。
未解析的引用“请求”
。您如何在这里传递请求?;)Django在2009年是否有
AdminModel
?我想没有。您的意思是
ModelAdmin
def get_request_user():
    # or any complex query result to set default value in ForeignKey
    return request.user.id
created_by = models.ForeignKey(User, default=get_request_user)