简体   繁体   中英

How do you specify a default for a Django ForeignKey Model or AdminModel field?

How can I set a default value on a ForeignKey field in a django Model or AdminModel?

Something like this (but of course this doesn't work)...

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

I know I can 'trick' it in the view, but in terms of the AdminModel it doesn't seem possible.

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

Here's a solution that will work in Django 1.7. Instead of providing the default at the field definition, set it as null-able, but overide the 'save' function to fill it on the first time (while it's 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)

For django 1.7 or greater,

Just create an ForeignKey object and save it. "default" value can be the id of the the object that should be linked by default.

For example,

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

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

I've done this similarly to @o_c, but I'd rather use get_or_create than just 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)

As for me, for Django 1.7 its work, just pk:

category = models.ForeignKey(Category, editable=False, default=1)

but remember, that migration looks like

migrations.AlterField(
            model_name='item',
            name='category',
            field=models.ForeignKey(default=1, editable=False, to='item.Category'),
            preserve_default=True,
        ),

so, i don't think it's to be working with dynamic user pk.

def get_user_default_id():
    return 1

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

This is a slight modification to the answer from o_c . It should save you one hit on the database. Notice in the save method I use self.a_id = 1 instead of self.a = Foo.objects.get(id=1). It has the same effect without having to query 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)

For Django >= 1.7, you can set the default for a ForeignKey field in two different ways:

1) Directly as an integer

DEFAULT_CREATED_BY_USER = 42

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

2) As a nonlambda callable returning an integer

You can also use a callable that can be resolved to a full module path. This means that lambdas does not work. But this will:

def default_created_by_user():
    return 42

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

References:

Instead of lambda function use partial function. Lambda function is not serialization and hence gives error in migrations.

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

You should have settings related to setting.AUTH_USER_MODEL in settings.py file.

You can look in below document:

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

You can override the get_form method of your model admin.

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)

Out of all along iterations to find a better solution, I find creating a small function will resolve the complexity of task substantially. Because some of the solutions are outdated or longer supported in newer Django versions.

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

Then you can pass above function as an argument in 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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM