in my Django model I have a m2m relation with an intermediate model that contain the two foreign keys of the respective two models.
My problems is that, the first model may have many entries and when I associate it with other model I have a too large drop down widget in the admin.
The default ManyToManyField widget (with filter_horizontal set) may be ok, but it is compatible only with m2m relations....
Is there a solution (even 3rd parts) for the ForeignKeyFields?
Any suggestions?
Edit:
For the other users, I've solved my problem using django-selectable
http://django-selectable.readthedocs.org/en/v0.8.X/index.html
The 3rd party component Django Ajax Selects does exactly what you are looking for.
I played around with django-selectable as well, but found django-autocomplete-light (https://github.com/yourlabs/django-autocomplete-light‎) easier to use and more flexible for what I wanted to achieve.
Perhaps it can be useful to you as well.
Related
This scenario happens way too often in my project:
someone adds a model Foo that has several ForeignKey fields, one of them to refers to model Bar
an admin is added for that model (and works OK)
the code is deployed
on production server, Bar has millions of instances
someone accesses Foo's admin page; Django tries to retrieve all Bars at once (to display them in a combo box) and the server gets overloaded
later the problem gets fixed by editing Foo's admin and adding bar to raw_id_fields.
I'd like to prevent this situation from happening in the future, preferably by somehow stating (once and for all) that Bar has many rows and it should be always treated as if the field referring to it was listed in raw_id_fields in all admin pages. Is this possible somehow?
This is an excelent point. This is a critical issue that can turn down the database and even the web server.
Considering this, I believe the default approach MUST be the raw_id_fields thing. If you know what you are doing, then you change this behavior.
Unfortunately, most of the authors of the admin interfaces libraries disagree of this thought. Not just for Python-Django, but also for other communities like Ruby-Rails.
5 years ago I got tired having the same problem, then I developed the django-smart-autoregister, that do this and also auto configure using another good patterns. Even today I face this problem, so I guess it is worth to take a look.
ps: the library was originally implemented using a modular approach, though you just call some functions that will configure the raw_id_fields for you according to the model field.
From the docs:
ForeignKey is represented by django.forms.ModelChoiceField, which is a
ChoiceField whose choices are a model QuerySet.
ModelChoiceField extends Field, and therefor has a widget property that can be abused
https://github.com/django/django/blob/master/django/forms/fields.py#L49
Add this somewhere in your project files.
from django.forms import ModelChoiceField
from django.contrib.admin.widgets import ForeignKeyRawIdWidget
ModelChoiceField.widget = ForeignKeyRawIdWidget
downside: this is also going to happen on non-admin forms
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).
I have a field in a Django model, and I want there to be a small (~20) set of possibilities (which are strings) which can be autocompleted (preferably with django-autocomplete-light, which I am using already) in django-admin. Should I make this a foreign key field and create a model containing just these 20 possibilities? or is there a better way?
django orm limit should be done something like:
Entry.objects.all()[:5]
so creating a new model for limiting number of results would not make sense.
I've looked at django-autocomplete-light and saw limit_choices here (didn't give it a try.
in any case it should be something like line 77 in this snippet.
I hope this is helpful.
The only way to do this is to have a separate model with only those possibilities and to make the field we want to limit into a foreign key field.
By default, Django's admin renders ForeignKey fields in admin as a select field, listing every record in the foreign table as an option. In one admin-accessible model, I'm referencing the User model as a ForeignKey, and since I have thousands of users Django is populating the select with thousands of options. This is causing the admin page to load incredibly slowly, and the select is not very useful since it can take a while to scroll through thousands of options to find the one you want.
What's the best way to change the rendering of this field in order to improve page load and usability? I'd like the select field to be replaced with some sort of button to launch a search form popup, or a text field that searches keywords via Ajax to find the Id for the specific User they want to associate. Does admin have anything like this builtin, or would I have to write this from scratch?
Add raw_id_fields to your model to only show the ID instead of a dropdown.
You're right, Cerin, the cause of the slowdown is because Django is populating the <select> element with too many options. You might want to use an autocomplete element instead.
Interestingly, Django 2.0 has introduced a new feature on the admin site, called autocomplete_fields, which I think you will find useful in this case. It uses AJAX.
class ExampleAdmin(models.ModelAdmin):
autocomplete_fields = ['example_field_user']
You can use one of the few autocomplete apps for Django. Check them at Django Packages.
There's also django-extensions that have ForeignKeyAutocompleteAdmin that fit your needs pretty well.
Another option is to add readonly_fields instead of raw_id_fields
I'm trying to do such a thing: I have two models, connected via Foreign Key, and every instance of first model needs to be linked with exactly 4 instances of second (I use InlineAdmin to create them at the same time using extra=4 and max_num=4).
There are two problems:
1 - I need each of four models to has it's own default read only value for one of it's fields, this value needs to be selected from the field's choices option. But I need them to be read only (I know about readonly_fields, but it's useless for that. Javascript don't seems to be a good solution...
2 - I need to specify default values for some field for all four models at the same time editing only one field. I'm thinking of two possible solutions: javascript or one additional, "fifth" model with all hidden fields except the one I need so I can override save() to use it's values for other models and delete it.
But which is the right way?
Try this documentation, it might help:
https://docs.djangoproject.com/en/1.5/ref/models/fields/#editable