Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make a Django model read-only?

What it says on the tin. Is there a way to make a Django model read-only?

By this I mean a Django model in which once records have been created, they can't be edited.

This would be useful for a model that records transaction history.

like image 831
AP257 Avatar asked Dec 02 '10 10:12

AP257


4 Answers

You can override the model's save method and check whether it's an existing entity, in which case you won't save any changes:

def save(self, *args, **kwargs):
    if self.id is None:
        super(ModelName, self).save(*args, **kwargs)

So in this example you only save the changes when the entity has not got an id yet, which is only the case when it's a new entity that hasn't been inserted yet.

like image 122
Tom van Enckevort Avatar answered Nov 03 '22 11:11

Tom van Enckevort


You can override the save method and not call super if you wanted to. That'd be a fairly easy way of accomplishing this.

# blatantly ripped the save from another answer, since I forgot to save original model
def save(self, *args, **kwargs):
    if self.id is None:
        super(ModelName, self).save(*args, **kwargs)

def delete(self, *args, **kwargs):
    return

You should probably also raise an exception if a delete or update is attempting to occur instead of simply returning. You want to signal the user what is happening - that the behaviour isn't valid.

like image 42
Josh Smeaton Avatar answered Nov 03 '22 10:11

Josh Smeaton


In addition to other solutions: If your main goal is to avoid write access from the admin, you can modify the used admin class so that nobody has an add/change permission:

class HistoryAdmin(admin.ModelAdmin):

    def has_add_permission(self, request):
        return False

    def has_change_permission(self, request, obj=None):
        return False

    def has_delete_permission(self, request, obj=None):
        return False
like image 2
Bernhard Vallant Avatar answered Nov 03 '22 11:11

Bernhard Vallant


If you don't want an attempt to modify a record to fail silently:

def save(self, *args, **kwargs):
    if self.pk:
        (raise an exception)
    super(YourModel, self).save(*args, **kwargs)


def delete(self, *args, **kwargs):
    (raise an exception)
like image 1
Vinayak Kaniyarakkal Avatar answered Nov 03 '22 11:11

Vinayak Kaniyarakkal