django admin site: foreign key dropdown - django

For the django admin site, for example, I have a model as follow:
class Book(models.Model):
...
author = models.ForeignKey(Author)
...
(to make it simple, we assume each book only has one author)
So when I try to add a new Book in admin site, author will display as a dropdown list and I can roll and select the author it belong to.
The problem is that when you get a lot of Authors, it will be hard to find one you want. So someone suggest to use "raw_id_fields" to solve the problem.
I think it works. However, I want better. I want something like a search box inside the same page rather than pop a page to do so. And probably keep the dropdown list at the same time.
What I am thinking is that I probably need to write some customized template. I did some research on this, but I am still confused. I want to know which template I should override and what kind of approach I should use.
Thanks for any help!

There are several type-ahead / autocomplete plugins for Django admin that will take the place of the standard drop-down list. Here's a couple: https://github.com/artscoop/django-admin-autocomplete or https://github.com/sxalexander/django-autocomplete

Related

Django Admin: How to change model name?

I would like to change the model name displayed in admin. The idea is to be able to register filtered versions of the model to the admin view. I know that I can add filter options when viewing the model. I am not interested in doing that.
I don't think using the approach for solving admin plural naming is an option: Django fix Admin plural. I could be wrong. If so, please tell me how this can be done.
I found this approach which seems to be the right solutions: Change 'Change model class name' in Django Admin || Change the 'Change' <h1>. However, I can't make it work. Is it just me not trying hard enough?
It is also an option to make a number of models and then register each of them. However, I will prefer to rename and register filtered versions in admin.
Any suggestions for solving this little issue?

django admin choices with submenus

I have a model with this field:
exercise = models.CharField(max_length=25, choices=EXERCISES_CHOICES)
but the list of exercises is VERY long, when I use it in the admin interface it occupies all the length of the page, is there a way to display in subitems?
I have a similar problem, but mine is not a list of choices - instead it is a foreign key field and the default in the Admin is also to display the entire list of available values in an option menu; as the database fills, this will probably be unusable. My plan is to create a custom Admin widget which uses a text input instead of an option menu, and use autocomplete to help fill in the value. I have not yet implemented it - I've started looking for autocomplete packages. Maybe once I decide on one, I'll come back and post an update.
P.S. It seems to me this would be a common problem and should already have been solved. Why can't I find anything out there?
---- EDIT ----
Apparently this has been solved! According to its documentation, the "django-extensions" package includes a "ForeignKeyAutocompleteAdmin" class. Hurray! See here:
http://pythonhosted.org/django-extensions/admin_extensions.html
https://pypi.python.org/pypi/django-extensions
Disclaimer: I haven't tried it yet (but I intend to!)

Can I make Django admin reflect a hierarchy of models?

Assume a Django application with a few models connected by one-to-many relationships:
class Blog(models.Model):
...
class Post(models.Model):
blog = models.ForeignKey(Blog)
...
class Comment(models.Model):
post = models.ForeignKey(Post)
...
Conceptually, they form a hierarchy, a tree-like structure. I want the Django admin to reflect that. In particular:
in a changelist of posts, every post should have a link to the changelist of corresponding comments;
similarly, a post’s edit page should link to the changelist of comments from the top-right buttons area;
when I open that list of related comments, it needs to reflect the relationship in the breadcrumbs (something like: Posts › “Hello world” › Comments) and, ideally, also in the URL (post/123/comment/).
This should of course also apply to the other levels of the hierarchy.
Number 1 is pretty easy with a custom list_display entry and using the ?post__id= query to the comments changelist. But this is little more than a hack. Generally Django assumes my three models to be independent, top-level entities.
Is there a straightforward way to accomplish this? I guess I could override a bunch of templates and AdminModel methods, but perhaps there is a better solution for what seems like a common situation?
Are you sure you are not just looking at Django Admin Inline Models ?
There is no way that an automated admin will pick up your relationships, because in an RDBS there can be any number of foreign keys / one to one / many to many relations, and Django does not have a customized hierarchical behavior built in.
You can indeed edit the breadcrumb customizing an admin template if you want.
For relations you might also be interested into django MPTT that allows to make hierarchical model instances. Also see this question: Creating efficient database queries for hierarchical models (django) in that respect.
How is this a common situation? Consider the fact a model can have a virtually unlimited number of foreign key relationships, let alone visa versa. How would the admin 'know' how to represent this data the way a user requires without customizing things?
One would suggest you are used to work with content management systems rather than webframeworks (no pun intended). It's important to notice Django isn't a cms, but a webframework you can built on top of as you see fit. In a nutshell: 'Django is rather clueless and unaware of contextual requirements'.
Although the admin is quite a beast out-of-the-box, it can be hard to customize. There have been quite some discussions whether it should even be part of core. I can only suggest, if customizing things tends to get hacky, you should probably write your own 'admin', it's not that hard.

Django admin: Change selected box of related fields to autocomplete

We have some models that are have a user as a foreign key. But with about 25000 users in our system, it's a bit daunting to find the one we need.
Is there a solution out there that's better than the select box? Maybe an autocomplete so we can start typing the user name / address? Or just a search box? When switching the related user for these objects, it's getting harder and harder with 25000 unsorted users.
Even just setting it to sort the users by username would be helpful.
I had this problem and my conclusion was to use an autocomplete field instead. It works pretty well in most cases. The only problem is when you have a lot of entries that are mostly the same. For example, in your case, if you type Robert for the name and there's a few hundred Robert entries in the list...
UPDATE
As mentions in shuckc's answer, Django 2.0+ admin as now autocomplete built in.
For older Django or to use outside of the admin (old answer)
There are many apps that add autocomplete to the Django admin:
django-autocomplete-light
django-extensions (ForeignKeyAutocompleteAdmin)
django-autocomplete (on google code)
django-ajax-selects
django-admin-autocomplete
django-autocomplete (tyrion)
My preferred one is the last one. It's well written, it can be used with the admin and outside of the admin, it works with ManyToManyFields, ForeignKeyFields, CharFields, etc.
I did a fork of this project for my client that adds some niceties like a lookup (loupe) button like the ForeignKeyRawIdWidget.
Django 2.0 admin has autocomplete built in, just set the autocomplete_fields field on the ModelAdmin class. e.g.
class QuestionAdmin(admin.ModelAdmin):
ordering = ['date_created']
search_fields = ['question_text']
class ChoiceAdmin(admin.ModelAdmin):
autocomplete_fields = ['question']
The simplest out-of-the-box solution is to add the field to your ModelAdmin's raw_id_fields -- then you'll get a pop-up window in which you can use the built-in searching/filtering and pagination control's to find and select the object you're after.
If you really want autocomplete, the other answers give a you reasonable starting point.
You can use the ForeignKeyRawIdWidget from django.contrib.admin.widgets. It renders FK relations as an input with a small button along-side which presents a searchable pop up.
There is an app for that (django-autocomplete).

Pre-Filling a ForeignKey from a link to the Admin?

Some introduction. I have a "planet-like" feed aggregator with an extra layer on top. That extra layer allows for comments and elaboration on the aggregated posts. Here's some code for reference.
class Post(models.Model):
title = models.CharField()
published = models.DateTimeField()
class Story(models.Model):
title = models.CharField()
post = models.ForiegnKey(Post)
Story has a ForeignKey to Post and when I write a story I pick a post from the drop-down. Now, after a few weeks the list could get pretty unruly. I could use raw_id_fields, but that's a bit counter-intuitive since I would have to find the ID of the post I needed.
EDIT: After doing some research, I removed my misleading question. I'm wondering if something like this is possible (given that application is the name of my... application.
Write about this post.
Let me know if THIS needs any more explanation. :)
Looks like the admin recognizes GET values. So,
/admin/application/story/add/?post=[post.id]
would set post to the proper ID. :)
You might want to think about using an autocomplete field instead of raw_id_fields.
Jannis Leidel has a good explanation, with examples, on how to add auto-complete functionality to the djando admin exactly for cases like yours.
You will need to add jquery to the mix, but the process is not that complicated.