18

I have Django model "AmountOfBooks" that is used just as balance for Book model.
If this is not good pattern for database modeling just say so.

Anyway AmountOfBooks have two fields:

class AmountOfBooks(models.Model):
    book     = models.ForeignKey(Book, editable=False)
    amount   = models.PositiveIntegerField(default=0, editable=False, help_text="Amount of book.")

They are set to editable=False, because this model is meant to be edited only by code.
Eg. when book is created object for that book in AmountOfBooks is set to 0 and when books are added or taken balance is either increased or decreased.

So in this way fields for AmountOfBooks model are not shown when I click on"Add Amount of books" button in Django admin.

But I want to remove that button from Django admin just for AmountOfBooks model.
How to do it ?

UPDATE
Continuation of this question is available on How to make Django model just view (read-only) in Django Admin?

Community
  • 1
  • 1
WebOrCode
  • 6,852
  • 9
  • 43
  • 70
  • Is there a reason you're not just tracking this as a field on `Book`? That said, the `add` button only shows up for users who have the appropriate permission, so if you don't give anyone the `add` permission for this model no one will see the `add` button except superusers. – Peter DeGlopper Nov 30 '13 at 07:02
  • I am building application where there will be lost of input and output for each book (and there is like 100 books) on daily basic. Eg. somebody will take 50 book, on ether one will take 30, then they will add 200 books and so on. So model AmountOfBooks is used like a balance, so that they know how much of each book is there. If left only change permission, user can see books, but still have option to change, altho he can not change anything because of editable=False. So this is some workaround. But I would be better if there was a way to give read-only (view-only) access to this Model. – WebOrCode Nov 30 '13 at 07:27
  • Check the answers in this question: http://stackoverflow.com/questions/7920371/whole-model-as-read-only/7965193#7965193, also look for `get_readonly_fields` on `ModelAdmin` – jbub Nov 30 '13 at 07:35
  • @WebOrCode - that comment still doesn't explain why this isn't just a field on `Book`. Every book will have a row in the appropriate table. A running count of the copies available can be maintained for each row, and will be more efficiently looked up and edited. Plus you can set the field as `editable=False` and the admin will not offer the possibility of changing it. – Peter DeGlopper Nov 30 '13 at 07:47
  • @PeterDeGlopper I am starting to see the benefit of your design. I think that my current design is to complicated. Can you explain me how would you handle the transaction table (table that should have data who took or give what book and when) ? – WebOrCode Nov 30 '13 at 07:55
  • @WebOrCode - if you're going to maintain a record of all transactions regarding a given book, I think you should treat the amount as a calculated value instead. If your scale allows it, you could sum the additions and withdrawals each time the quantity is needed. If it doesn't allow it, you could maintain a timestamped amount and sum with the additions and withdrawals that postdate that timestamp to keep the number of records reasonable. The latter is a bit awkward to maintain and requires a more complicated model setup, so I'd avoid it if you can - but if you have enough data you can't. – Peter DeGlopper Nov 30 '13 at 08:04

3 Answers3

28

It is easy, just overload has_add_permission method in your Admin class like so:

class MyAdmin(admin.ModelAdmin):
    def has_add_permission(self, request):
        return False
Avinash Garg
  • 1,374
  • 14
  • 18
  • 2
    Sorry, is allowed to use "copy and past" of other user's answers? http://stackoverflow.com/questions/4143886/django-admin-disable-the-add-action-for-a-specific-model#answer-4144088 – Alesanco Nov 08 '16 at 10:03
  • Is it possible disable add permission for User model? I want to disable Add user button in Wagtail admin – Nick May 12 '20 at 14:59
8

To do it you need to override has_add_permission method in your Admin class:

class AmountOfBooksAdmin(admin.ModelAdmin):
    def has_add_permission(self, request):
        return False

    # to disable editing for specific or all fields
    # you can use readonly_fields attribute
    # (to see data you need to remove editable=False from fields in model):
    readonly_fields = ('book', 'amount')

Docs here: https://docs.djangoproject.com/en/dev/ref/contrib/admin/

ndpu
  • 22,225
  • 6
  • 54
  • 69
  • If I do this I still can change Model and I would like to have just view functionality. – WebOrCode Nov 30 '13 at 07:42
  • @WebOrCode you need has_change_permission – ndpu Nov 30 '13 at 07:48
  • when I add has_change_permision then I can not see that table any more. has_add_permission and has_change_permission work the same way as appropriate permission for users. – WebOrCode Nov 30 '13 at 07:53
  • @WebOrCode you right, with has_change_permission you cant view data... editable in model didnt help? – ndpu Nov 30 '13 at 08:00
1

You asked about your design itself so I'll address this first. If you want to keep an history of your stock then having a distinct table (model) makes sense but then you'd need a timestamp field and a unique constraint on (book, timestamp). Now if you just want to keep the stock current the relationship between book and amount is really one to one so the amount field really belongs to the book table. In this case you just have to add "amount" to the book's ModelAdmin "readonly_fields" attribute and your problem is solved.

bruno desthuilliers
  • 75,974
  • 6
  • 88
  • 118