I would like to separate my app's models in the admin index:
I registered all my models in admin.py and I get all of them in the default admin index under the big red 1 shown below.
Now I'd like to have some of my models in another "block", as shown below under the big red 2.
To make it harder, I also need to have some models in both "blocks", but with different queryset.
How can I do that?
I tested my solution and it works.
Do this:
class MyModelTest(models.Model):
# Fields here
class Meta:
app_label = 'My other app namespace'
UPDATE:
To achieve your goal (max flexibility) , you will need to modify the template admin/app_index.html and the view django.contrib.admin.sites.app_index to your own needs.
Related
I have a model that I only want to use one row of its table. So, on admin, I would like to remove the list and add pages, and only edit the existing object. The model is this:
from django.db import models
class Banner(models.Model):
pass
class BannerImg(models.Model):
img = models.ImageField(upload_to="banners")
banner = models.ForeignKey(Banner, on_delete=models.CASCADE)
Basically, the Banner(pk=1) will be loaded by the frontend to display a landing page hero slider. I want multiple images, but also want them to be on the same admin form, so one could order, add or remove images from the same place. Of course having to Banner objects, wouldn't make sense in this case.
I can use inline fields to do the form, but how can I achieve the pages functionality (going directly to edit)?
Thanks!
Accordion to documentation.
from django.contrib import admin
class BannerImgInline(admin.TabularInline):
model = BannerImg
class BannerAdmin(admin.ModelAdmin):
inlines = [
BannerImgInline,
]
I am building an app in Django.
I found there is a very easy way to integrate a widget into django admin that allows the admin to filter model objects by fields values. That is achieved by including the line
list_filter = ['field_to_filter_by_its_values']
into the class mymodelAdmin(ImportExportModelAdmin) in admin.py, as shown below
class target_area_history_dataAdmin(ImportExportModelAdmin):
resource_class = target_area_history_dataResource
list_filter = ['Target_area_input_data__Name']
admin.site.register(target_area_history_data, target_area_history_dataAdmin)
Now, instead of integrate a widget to filter my model objects by that field, is there a way to integrate a widget to sort my model objects by that field?
Note: I am using Django Import-Export in my model.
I'll suggest you use django-treebeard. This allows you to view tree nodes hierarchically in the administration interface, with interface features dependent upon the tree algorithm used.
# admin.py
from django.contrib import admin
from treebeard.admin import TreeAdmin
from .models import Category
class CategoryAdmin(TreeAdmin):
list_display = ("title", "created", "modified",)
list_filter = ("created",)
admin.site.register(Category, CategoryAdmin)
What's cool about this is that you can not only sort (by clicking the header row) but also drag things around, as shown in this image.
I recommend you using the grapelli admin interface that allows what you need and a bit more. here you have the grapelli project page and the https://github.com/sehmaschine/django-grappelli.
It's a well documented package and is plug and play for what you need. It also gives a fresh face to Django Admin and is compatible with Django import/export package.
I am registering my (numerous) models using looping through apps.get_models() much like in the below answer:
Register every table/class from an app in the Django admin page
My goal: as most of the models contain a common field that I would like to exclude from Django Admin I wonder if there is any way to do it without resorting to registering each model separately with exclude = FieldToBeExcluded
You could create a common model admin class that every model uses
class CommonAdmin(admin.ModelAdmin):
exclude = ['field_to_exclude']
for model in app_models:
admin.site.register(model, CommonAdmin)
Lets say for example I have a Model called "Client" and a model called "PhoneNumbers"
class PhoneNumbers(models.Model):
number = forms.IntegerField()
class Client(models.Model):
number = forms.ManyToManyField(PhoneNumbers)
Client has a ManyToMany relationship with PhoneNumbers. PhoneNumbers has almost 500,000 records in it so when it comes to editing a Client record from a model form with a MultiSelect widget that comes with a M2M filed, it takes forever to load. In fact, it never does. It just sits there trying to load all of those phone objects I am assuming.
My workaround was to so some tedious things with ajax and jquery to edit only the phone numbers in a Client record. Before wasting my time with all of that I wanted to see if there is somehow another way to go about it without having my page hang.
You need to create a custom widget for this field that lets you autocomplete for the correct record. If you don't want to roll your own: http://django-autocomplete-light.readthedocs.io/
I've used this for its generic relationship support, the M2M autocomplete looks pretty easy and intuitive as well. see video of use here: http://www.youtube.com/watch?v=fJIHiqWKUXI&feature=youtu.be
After reading your comment about needing it outside the admin, I took another look at the django-autocomplete-light library. It provides widgets you can use outside the admin.
from dal import autocomplete
from django import forms
class PersonForm(forms.ModelForm):
class Meta:
widgets = {
'myformfield': autocomplete.ModelSelect2(
# ...
),
}
Since Django 2.0, Django Admin ships with an autocomplete_fields attribute that generates autocomplete widgets for foreign keys and many-to-many fields.
class PhoneNumbersAdmin(admin.ModelAdmin):
search_fields = ['number']
class ClientAdmin(admin.ModelAdmin):
autocomplete_fields = ['number']
Note that this only works in the scope of Django admin of course. To get autocomplete fields outside the admin you would need an extra package such as django-autocomplete-light as already suggested in other answers.
Out of the box, the model admin has a raw_id_fields option that let your page load much quicker. However, the user interface of raw id fields isn't very intuitive, so you might have to roll your own solution.
We use this 3rd party widget for this:
https://github.com/crucialfelix/django-ajax-selects
Btw, your 'example' above is really bad DB design for a bunch of reasons. You should just have the phone number as a text field on the Client model and then you would have none of these issues. ;-)
I have a table that only has a handful of entries in it, and it'd be nice if I could use inlines for their list instead of forcing staff to click through to the edit page each time.
That is, when someone clicks on the link that ordinarily gives a list of the model objects, they should instead see the model objects displayed inline.
I tried something like this, but unsurprisingly it gives an error because there's no foreign key:
class MyModelInline(admin.StackedInline):
model = MyModel
class MyModelAdmin(admin.ModelAdmin):
inlines = [MyModelInline,]
admin.site.register(MyModel, MyModelAdmin)
For it to work as you've described you'll need an "editor" model to be a parent for the data. All the rows you want to display should have a foreign key to a single 'editor' model object. So, in models.py:
from django.db import models
class Editor(models.Model):
pass
class MyModel(models.Model):
name = models.CharField(max_length=100) # Field added for demonstration
# ... add any other fields you like ...
editor = models.ForeignKey(Editor)
And in admin.py:
from django.contrib import admin
from Test.models import Editor, MyModel
class MyModelInline(admin.StackedInline):
model = MyModel
class EditorAdmin(admin.ModelAdmin):
inlines = [MyModelInline,]
admin.site.register(Editor, EditorAdmin)
Some other things to consider:
When you make a new MyModel() object programmatically you must always set the foreign key to point to the editor. There should only be one instance of the editor for this to work as you've described. When using the admin interface, this foreign key should be set automatically by using the admin page for the editor object. I would suggest restricting creation and deletion of editor objects for everyone except yourself in production. If someone deletes the editor object then all MyModel objects disappear as well.
Alternative options:
1) If the edits the admin staff is doing are simple then I would recommend implementing "actions" instead.
2) There's also the possibility of overriding the admin template. I personally like this option less because every time Django is updated I have to check that my changes aren't interfering with new features. However, sometimes this is the only way to do some more advanced things in the admin interface. I've done this in my own project, but like to keep the changes minimal.