Prithviraj Mitra
Prithviraj Mitra

Reputation: 11812

Display a model field as readonly in Django admin

I want to display a model field ie module_name as read only in django user profile edit page. The model Category has a manytomany relationship with Profile model.

Category

id   category_name module_name
1    A             X
2    B             Y

profile_category

id    profile_id    category_id
1     2             1

So for eg. when I am on the admin page to editing a user id of 2 then I would like to display the module name X if category id 1 is assigned to the user id 2

models.py

class Category(models.Model):
    category_name = models.CharField(max_length=150, blank=False, null=True, default="", unique=True)
    module_name = models.TextField(blank=False, null=True)

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name ='profile')
    phone_number = PhoneNumberField( blank=True, null=True)
    organisation = models.CharField(max_length=30, blank=True)
    category = models.ManyToManyField(Category)

admin.py

class ProfileInline(admin.StackedInline):
    model = Profile
    filter_horizontal = ('category',)

class CustomUserAdmin(UserAdmin):
    inlines = (ProfileInline, )
    list_select_related = ( 'profile',  )

Please suggest if this is possible or not.

Any help/suggestion is highly appreciated. Thanks in advance.

Upvotes: 2

Views: 4337

Answers (1)

gdlmx
gdlmx

Reputation: 6789

Method 1

Use readonly_fields which is inherited from admin.BaseModelAdmin.

class ProfileInline(admin.StackedInline):
    model = Profile
    readonly_fields = ('module_names',)

    def module_names(self, instance):
        # Write a get-method for a list of module names in the class Profile
        # return HTML string which will be display in the form
        return format_html_join(
              mark_safe('<br/>'),
              '{}',
              ((line,) for line in instance.get_module_names()),
        ) or mark_safe("<span>The user belongs to no category</span>")

    # short_description functions like a model field's verbose_name
    module_names.short_description = "Module names"

Method 2

For older versions of admin site, you can hook the get_fieldsets method of admin.StackedInline. This method was posted here with a nice example.

Upvotes: 3

Related Questions