multi combo box in django - django

I have a model called Bar:
class Bar(models.Model):
country = models.CharField(max_length=20)
city = models.CharField(max_length=20)
name = models.CharField(max_length=20)
I want the user to be able to choose a bar through a combox box of first choosing a country, than a city (in that country), than a bar(in that city).
I tried doing it with django forms, but no success. What is the best way to do it? thanks

I think you should take a look on ChoiceField at Django Docs:
"(Default widget: Select)"
ChoiceField is rendered as select box in HTML. It should work for your case.

You should check out Django Smart Selects
PyPi
Blog post about implementation here
You can also fork it on GitHub I believe
I was recommended this in the past when I asked a similar question about How to create 'child' questions in Django forms? I never got a chance to play around with it but it seems very close to what you are looking for.
I was also never sure what to call this type of functionality but it seems like "Chained Select Boxes" which got from the above post is the best I've heard so far.

Related

Wagtail - passing queryset to inline

I am facing a problem from days, but, no matter how much I keep searching, I could not find any solution here or anywhere in the web.
So here it is: I am developing a website for some sort of institution which offers teaching courses. I am using WAGTAIL and I am structuring the classes this way:
class Course(Page):
...
content_panels = Page.content_panels
class Exam(Page):
#fields
content_panels = Page.content_panels + [
#fields
InlinePanel('preparatory_exam', heading='Preparatory Exams'),
]
class PreparatoryExam(Orderable):
page = ParentalKey('Exam',
on_delete=models.CASCADE,
related_name = 'preparatory_exams',
)
name = models.ForeignKey(
Exam,
on_delete=models.CASCADE,
blank=True,
null=True,
related_name = 'preparatory_exam',
)
I also structured the ADMIN section PAGES this way:
\COURSE_1_PAGE
\-----------\EXAM_1
\-----------\EXAM_2
\------------------\Prep exam 1
\------------------\Prep exam 2
\-----------\EXAM_3
...
\COURSE_2_PAGE
\-----------\EXAM_1
\-----------\EXAM_2
\-----------\EXAM_3
....
So, the problem is: is there any way to pass a custom queryset to the inline dropdown box when choosing the preparatory exams for a certain one? What I want is to restrict the set to the exams present in the same Course.
I could do that with a limit_choices_to added to the foreignkey field, but AFAIK, it would be a "static" filter, because it would be related to the model and not to its istances, so it would be the same for every newly instantiated exam...
One first- highly unsatisfactory - solution would be to change the InlinePanel with 2-3 FieldPanels (generally an exam does not need more than 2-3 other prep exams)...
Another UGLY solution would be explicitly defining Course_1, Course_2 and so on classses, but the problem here is that every year I would have to add another class, because they set up a new course every year!
So it leaves me not a lot of choices: overriding somehow (but i'm in the dark) the InlinePanel object behavior, or change the way I designed the site.
Can anyone help me? Thank you very very much!
One pragmatic option might be to use "ordinary Django views" to build this particular part of the application, borrowing Wagtail visual designs freely so that everything continues to look the same to the end-user. Given that you are building a display of a very rigid data-structure - course, exam, etc., as opposed to "free-form content," this is probably how I would choose to do it.
(Note that Wagtail template tags might or might not work properly when Wagtail isn't the one driving the page display. I'd recommend implementing your own, of course freely copying from the Wagtail source-code for inspiration.) In the end, the user would not perceive a difference, and you can very freely develop URLs that would send the user to a Wagtail-managed target page, e.g. the course-descriptions and exams themselves.
Another pragmatic option is to use Django template-tags to construct portions of the display that are otherwise managed by Wagtail, although this gets maybe a bit more complicated. Since Django is underneath the whole thing, "Django rules still apply."

django admin site: foreign key dropdown

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

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).

facebook django type select for many-to-many fields

I am wondering if there is maybe a way with django to display bring in extra data into the display of CheckboxSelectMultiple ie avatar or first_name or last_name
With the manytomany field its really good that a user can check their options and proceed, but what sometimes it might be that a user has the same information twice, ie a name that is the same, or a reference to something that is the same.
Facebook has a very nice style when you want to share something with somebody you can select that user and see their avatar at the same time, so if you have two friends with the same name and surname, you can always distinguish them by their avatar.
is there some way with the __init__ that this can be achieved, or do you guys have any pointers on achieving this in another way?
The answer linked to below has an example of a custom SelectMultiple widget which makes the objects being selected available for use in presenting further details to the user in the widget's render() method:
Formsets with checkboxes

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.