Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Readonly for existing items only in Django admin inline

I have a tabular inline model in the Django admin. I need 1 of the fields to not be changeable after it has been created, but setting it as readonly (via readonly_fields) which works fine, but turns the field into a label when clicking 'Add another item' instead of a dropdown.

Is there a way to keep a field readonly, but still allow new items to be created with the proper field input?

Thanks!

Thomas

Edit: Managed to figure it out by way of a custom widget

class ReadOnlySelectWidget(forms.Select):     def render(self, name, value, attrs=None):         if value:             final_attrs = self.build_attrs(attrs, name=name)             output = u'<input value="%s" type="hidden" %s />' % (value, flatatt(final_attrs))             return mark_safe(output + str(self.choices.queryset.get(id=value)))         else:             return super(ReadOnlySelectWidget, self).render(name, value, attrs) 

It just turns it into a hidden if there is a value, won't work in every situation (only really works with 1 read only field).

like image 730
user569888 Avatar asked Apr 11 '11 09:04

user569888


1 Answers

Having the same problem, I came across this fix:

Create two inline objects, one with no change permission, and the other with all the fields read-only. Include both in the model admin.

class SubscriptionInline(admin.TabularInline):     model = Subscription     extra = 0     readonly_fields = ['subscription', 'usedPtsStr', 'isActive', 'activationDate', 'purchaseDate']      def has_add_permission(self, request):         return False  class AddSupscriptionInline(admin.TabularInline):     model = Subscription     extra = 0     fields = ['subscription', 'usedPoints', 'isActive', 'activationDate', 'purchaseDate']      def has_change_permission(self, request, obj=None):         return False      # For Django Version > 2.1 there is a "view permission" that needs to be disabled too (https://docs.djangoproject.com/en/2.2/releases/2.1/#what-s-new-in-django-2-1)     def has_view_permission(self, request, obj=None):         return False 

Include them in the same model admin:

class UserAdmin(admin.ModelAdmin):     inlines = [ AddSupscriptionInline, SubscriptionInline] 

To add a new subscription I use the AddSubscriptionInline in the admin. Once it is saved, the new subscription disappears from that inline, but now does appear in the SubscriptionInline, as read only.

For SubscriptionInline, it is important to mention extra = 0, so it won't show junk read-only subscriptions. It is better also to hide the add option for SubscriptionInline, to allow adding only via AddSubscriptionInline, by setting the has_add_permission to always return False.

Not perfect at all, but it's the best option for me, since I must provide the ability to add subscriptions on the user admin page, but after one is added, it should be changed only via the internal app logic.

like image 196
olessia Avatar answered Sep 21 '22 20:09

olessia