Hide model from main admin list, but allow creation in inline editor - django

In my Django app, I have an Attribute model which has a many-to-many relationship to a MeasurementMethod model.
I put an inline for MeasurementMethod in the admin interface for Attribute, but I don't think it is useful to have a separate interface for managing MeasurementMethods at all; there's no reason why a user would say, "Gee, I wonder what Attributes can be measured by water displacement."
However, this left no way to create new MeasurementMethods from the inline editor until I found Anton Belonovich's post, which says that I need to admin.site.register(MeasurementMethod) first. I did that, and sure enough the edit and create buttons appeared.
But now on the admin page, where there's a list of apps and the models that can be managed, there's an entry for MeasurementMethod that I don't want.
Is there a way to get rid of it? Or is there a better way to accomplish this?

The solution is to register the MeasurementMethod class with a custom admin class that overrides has_module_permission:
#admin.register(MeasurementMethod)
class MeasurementMethodAdmin(admin.ModelAdmin):
def has_module_permission(self, request):
return False
Then the class can still be edited inline.
ModelAdmin.has_module_permission(request)
Should return True if displaying the module on the admin index page and accessing the module’s index page is permitted, False otherwise. ... Overriding it does not restrict access to the add, change or delete views ...

You could create a custom admin site docs and then override the index method/view. Make sure you register your models with this new admin site and hook it up in the urls.py file.

Related

Add custom action to Django inline object on the admin interface

I have an admin interface that has a blog post, with inline models which are previus versions of the post.
I'd like to add an action for each one of the previous version (A revert action, custom model method)
how should I go about doing that?
its kinda similar to ModelAction actions keyword, but I want it to be inside the model view, not the list view
and also its for each inline model, not for the parent model
would love some help.
to make it clearer
my previous_version class has a function named revert. all I want is that in my blog post's view in the admin panel by each previous version I'll have a link or button or something. and pressing it will call previous_version.revert.
I guess the right thing to make this is Admin actions as described in documentation -
https://docs.djangoproject.com/en/dev/ref/contrib/admin/actions/
You can extend Blog ModelAdmin with action revert.
Overriding inline model template to add a button, like you said you already did is a good way to do it.
Just be sure to wrap created view within admin_view and allow only post requests.

Creating Pages for Django Admin add_form Inline Children

I have a node_user which extends auth.User in my django application. The node_user has many children. When creating a new node_user in the django admin I also provide access to node_users's child objects using the StackedInline sublclass.
However, I want to present the node_user children in a series of pages instead of a stacked one-page list. Is there anyway to spread the children out over pages? Does someone have an example? I think this would help user interaction but I'm unsure how to do it because I'm a newbie.
Thanks
angelo
Django doesn't do this out of the box sorry. You could write a custom admin view but you'd have some tricky decisions to make and coding to do regarding saving. I.e. does hitting 'next' lose changes you made on the first page? My approach to this problem would be to edit the node_user children through their own ModelAdmin - smart use of the list_filter and/or search_fields options (and perhaps list_editable) should make it pretty easy to edit them as a group.

Django admin: 'add' page, want to add multiple objects on one page

class Country(models.Model):
name = fields.CharField()
In admin, I want to display multiple forms for Country so I can add multiple different country objects at once. I don't know where to start? Please help, thanks.
I can't think of any way to do this inside the admin. The admin is a ready-made interface for editing single objects (and, optionally, multiple objects related to that object), but doesn't give you any way to edit multiple objects at once.
If you need this, write your own view using a formset.
My idea is you could extend the admin template change_form.html to display a formset, and have the 'add' url point to a view that would handle the page rendering. You will also need to override the url in your urls.py. Not the best but it would work.

Django-admin with callable functions

Django-admin view allows only for changing the values of model objects. Is it, however, possible to configure or change in an easy way the admin view so that it starts exposing functions on objects? I'm not talking about the functions that can be introduced in the drop-down menu on top of the object list. What I mean is a direct access to functions on model objects?
You can add your own view to the admin site by adding an "^admin/..." url in your url conf. You can use this to extend the admin site relatively easy and expose model methods through your own view. See Creating Custom Admin Views here: http://www.djangobook.com/en/1.0/chapter17/ (and another approach and notes here: https://docs.djangoproject.com/en/dev/ref/contrib/admin/#adding-views-to-admin-sites ).
To add this as a button in the model's "change form" in the admin site, override the change_form.html template for the required models (see https://docs.djangoproject.com/en/dev/ref/contrib/admin/#overriding-admin-templates ).
You will probably want to override the object-tools block, which holds the buttons in the top right side of the page. (In Django 1.3 you can extend the object-tools-items block instead, see: https://code.djangoproject.com/ticket/12694 )
(I am quite sure one can build a nice plugin/app that automatically adds object-tools to a model from a custom "object_tools" property in the ModelAdmin with a list of model methods. Let me know id you find something like this.)

Django - logical delete

I want to make the following modification to the Django framework.
I want it to create a "deleted" field for each model I create.
I want it to be checked as deleted when I delete it from the admin page instead of being physically deleted.
I do not want these records checked as deleted to be listed.
I'm new to Django, I'm seeing if I can do what I want to do with it easily. I need this change because it's the way we currently work.
So far these are the changes I have made, I would like to understand how the whole Django framewok works inside but I'm so far from that, is there any documentation online which explains clearly how the inside framework parts/files/modules/classes work together, the specific role of each one, etc
In the base.py file, in the modelbase class, below this code,
for obj_name, obj in attrs.items():
new_class.add_to_class(obj_name, obj)
I added,
from django.db import models
new_class.add_to_class('deleted', models.BooleanField())
When it creates a model it adds the "deleted" field to it.
In the base.py file, in the save method, I changed what it was there for
self.deleted = True
self.save()
So, now it check as deleted a record instead of physically delete it.
Now what I want is those records not to be listed.
I don't understand why you're modifying the framework code instead of putting your deleted field in a model base class that all of your models extend from.
Nevertheless, a nice way to filter those records out would be to add a custom manager to the model (or your base model class, if you choose to create one). To this manager, override the get_query_set method as described here. In your overridden method, add a exclude(deleted=True) filter.
Take a look at the Django-logicaldelete app, You just inherit your models from their provided Model class and you get Logical delete for all of them.
It comes with an adminModel as well so you can manage logically deleted models there too.
Override the delete() method in your model class, set the deleted attribute there
Create a custom manager which will filter by deleted attribute and set it as the default one (objects = MyDeletedManager)