Creative crypter
Creative crypter

Reputation: 1496

Django Admin - Prepopulate field and set readonly

i want to set a field (current user) in a model automatically when an object gets created or is being updated and make it readonly, so the user can not change it:

In order to prepopulate the field:

@admin.register(Model)
class ModelAdmin(admin.ModelAdmin):
    list_display = ('field_1', 'user')

    def get_form(self, request, obj=None, **kwargs):
        form = super(ModelAdmin, self).get_form(request, obj, **kwargs)
        form.base_fields['user'].initial = request.user
        return form

This works, but when i then want to make the field readonly using:

readonly_fields=('user', )

the app crashed with error:

KeyError at /admin/api/model/add/
'user'

Can anybody help me out and explain how i can reach my goal using django admin?

thanks!

Upvotes: 2

Views: 2370

Answers (3)

darkrat
darkrat

Reputation: 691

Try overriding the get_readonly_fields() method on the ModelAdmin

def get_readonly_fields(self, request, obj=None):
    try:
        return 'user',
    except AttributeError:
        return super().get_readonly_fields(request, obj)

Upvotes: 0

Carson Zhang
Carson Zhang

Reputation: 115

A work around I found was this:

form.base_fields['user'].disabled = True

You can also add a help text by:

form.base_fields['user'].help_text = "some help text"

So in your code it would be:

    def get_form(self, request, obj=None, **kwargs):
        form = super(ModelAdmin, self).get_form(request, obj, **kwargs)
        form.base_fields['user'].initial = request.user
        form.base_fields['user'].disabled = True
        form.base_fields['user'].help_text = "This field is not editable"
        return form

Then you don't have to use readonly_fields

Upvotes: 5

markwalker_
markwalker_

Reputation: 12849

Admin provides a method called save_model which you can use to add the current user to the object when it's saved;

@admin.register(Model)
class ModelAdmin(admin.ModelAdmin):

    def save_model(self, request, obj, form, change):
        obj.user = request.user
        super().save_model(request, obj, form, change)

Upvotes: 2

Related Questions