[Django]-How to make a model instance read-only after saving it once?

10👍

You can check if it is creation or update in the model’s save method:

def save(self, *args, **kwargs):
    if self.pk:
        raise StandardError('Can\'t modify bla bla bla.')
    super(Payment, self).save(*args, **kwargs)

Code above will raise an exception if you try to save an existing object. Objects not previously persisted don’t have their primary keys set.

👤muhuk

1👍

Suggested reading: The Zen of Admin in chapter 17 of the Django Book.

Summary: The admin is not designed for what you’re trying to do 🙁

However, the 1.0 version of the book covers only Django 0.96, and good things have happened since.

In Django 1.0, the admin site is more customizable. Since I haven’t customized admin myself, I’ll have to guess based on the docs, but I’d say overriding the model form is your best bet.

0👍

use readonlyadmin in ur amdin.py.List all the fields which u want to make readonly.After creating the object u canot edit them then

use the link

http://www.djangosnippets.org/snippets/937/

copy the file and then import in ur admin.py and used it

0👍

What you can easily do, is making all fields readonly:

class MyModelAdmin(ModelAdmin):
    form = ...
    def get_readonly_fields(self, request, obj=None):
        if obj:
            return MyModelAdmin.form.Meta.fields
        else: # This is an addition
            return []

As for making the Save disappear, it would be much easier if

  1. has_change_permission returning False wouldnt disable even displaying the form
  2. the code snippet responsible for rendering the admin form controls (the admin_modify.submit_row templatetag), wouldnt use show_save=True unconditionally.

Anyways, one way of making that guy not to be rendered :

  1. Create an alternate version of has_change_permission, with proper logic:

    class NoSaveModelAdminMixin(object):
        def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None):
            response = super(NoSaveModelAdmin, self).render_change_form(request, context, add, change,form_url, obj)
            response.context_data["has_change_permission"] = self.has_real_change_permission(request, obj)
        def has_real_change_permission(self, request, obj):
            return obj==None
        def change_view(self, request, object_id, extra_context=None):
            obj = self.get_object(request, unquote(object_id))
            if not self.has_real_change_permission(request, obj) and request.method == 'POST':
                raise PermissionDenied 
            return super(NoSaveModelAdmin, self).change_view(request, object_id, extra_context=extra_context)
    
  2. Override the submit_row templatetag similar to this:

    @admin_modify.register.inclusion_tag('admin/submit_line.html', takes_context=True)
    def submit_row(context):
        ...
            'show_save': context['has_change_permission']
        ...
    
    admin_modify.submit_row = submit_row
    

Leave a comment