django - dynamic query on form field - django

Lets say I have a form with some fields. I was wondering if it is possible to do dynamic query where I could do a string match while the user is typing into a field. Like when typing into google it returns a list of choices when you type into the search bar. Can someone give me an example on how and where to implement it?

If what you're looking to achieve is fields for a ForeignKey then you can provide a Queryset on the form field then use an app like django_select2 which can then provide a widget which will allow a user to search for items in the Queryset for the field. e.g.
city = forms.ModelChoiceField(
queryset=City.objects.all(),
label=u"City",
widget=ModelSelect2Widget(
model=City,
search_fields=['name__icontains'],
dependent_fields={'country': 'country'},
max_results=500,
)
)
Then in the form, as you started to type into the city field it'd start to search on City.name using an icontains lookup. The docs for this are here.
If that's not what you're looking for then you could just write some Javascript which detected input to a field, then sent an ajax request to a view with the contents of your field. That could then return a response which displayed content in the page related to the input.

Related

How to test CheckboxSelectMultiple in save

I have a form (ModelForm) in Django, where I am adding a field for users in the init method as so:
self.fields["users"] = forms.ModelMultipleChoiceField(
queryset=users, widget=forms.CheckboxSelectMultiple, required=False,label="Add Designer(s)"
)
In the save method how I can iterate over the queryset for this field, however, I do not know how I can test if the particular model has been selected/checked. Help, please.
EDIT:
Let's say that you have a form where you want to be able to add users to a certain project, I set the users field as above (also usedMultipleChoiceField) but my real question is how do you determine the state of those checkboxes (which users should be added)?
Managed to fix it using MultipleChoiceField instead of ModelMultipleChoiceField. Then populated the choices with existing event IDs and passed it to the template.
In forms:
choices = forms.MultipleChoiceField(widget = forms.CheckboxSelectMultiple())
In views:
form.fields['choices'].choices = [(x.eventID, "Event ID: " + x.eventID) for x in unapproved]
Had to change some of the logic for finding and editing Event objects too.
The Django documentation states that a ModelMultipleChoiceField normalizes to a QuerySet of model instances. That means in your example, it will only return the users that have been checked. If none have been checked, it will return an empty QuerySet.
If you are overriding your ModelForm save method, you could include something like this:
selected_users = self.cleaned_data.get('users')
for user in selected_users:
project_users.add(user)

Django validating empty ModelChoice form field

I have a form:
class ProjectInfoForm(forms.Form):
module = forms.ModelChoiceField(
queryset=Module.objects.all(),
)
piece = forms.ModelChoiceField(
queryset=Piece.objects.all(),
required=False,
)
The second field is populated with option from the first using ajax. However, instantiating it like this is not very efficient as it means the second field is populated on page load uneccessarily (not to mention populates the field before it should).
So I tried changing it to:
...
piece = forms.ModelChoiceField(
queryset=Piece.objects.none(),
required=False,
)
I get the desired result but of course the form does not validate has it has no choices to check against.
Is there some way I can validate the form without populating it or even better validate the two fields together as related models?
Any help much appreciated.
I think the easier way is just to roll your own. You'll just need:
A ChoiceField. Using coerce will let you transform IDs into objects transparently
A view that you AJAX component can query to retrieve the list of valid Pieces for a given Module.
A server-side validation method that checks that the Module and the Piece correspond

Django form validation model choices

I am having a problem with validating a forms.ChoiceField. I have two tables/models
class City(models.Model):
...
name = models.CharField(max_length=64)
...
class ShoppingCenter(models.Model):
...
name = models.CharField(max_length=64)
city = models.ForeignKey(City)
People can register their activity in a city and in a shopping center. But because there are lots of cities and even more shopping centers, I want to limit the shopping center choices to the selected city. I have created a form with a CharField for the city name and an empty ChoiceField.
After the user has entered a city in the CharField, using ajax/jquery autocomplete, I use ajax/jquery to fill in the values for for the ShoppingCenter ChoiceField.
All that seems to work. I enter a valid city, and the javascript fills in the options for the ShoppingCenter selectfield.
However when I want to validate this form it fails. I am getting:
form_errors
{'shopping_centre_id': [u'Select a valid choice. 1 is not one of the available choices.']}
although 1 is a valid shopping center id, it was selected from a the database.
I have another MultipleChoiceField is the same form and that works fine. The only difference between the two is that the MultipleChoiceField is generated using standard Django and the ChoiceField is created using javascript (ajax + django).
For now I have found a workaround by defining my own clean method in which I remove the error from self._errors and add the shopping_centre_id value to cleaned_data.
Does anyone know what might cause the validation error?
Fill in choices for ChoiceField on form's __init__. You can take a city name from provided data, retrieve a City, filter shopping centers and put them in choices.
But better to use ModelChoiceField for shopping centers, so you will not have to construct choices manually, but just pass a queryset to that field. If there is no data - it will be ShoppingCenter.objects.none(), otherwise - filtered by city.

How do I construct a Django form with model objects in a Select widget?

Let's say I'm using the Django Site model:
class Site(models.Model):
name = models.CharField(max_length=50)
My Site values are (key, value):
1. Stackoverflow
2. Serverfault
3. Superuser
I want to construct a form with an html select widget with the above values:
<select>
<option value="1">Stackoverflow</option>
<option value="2">Serverfault</option>
<option value="3">Superuser</option>
</select>
I'm thinking of starting with the following code but it's incomplete:
class SiteForm(forms.Form):
site = forms.IntegerField(widget=forms.Select())
Any ideas how I can achieve that with Django form?
EDIT
Different pages will present different site values. A dev page will show development sites while a cooking page will show recipe sites. I basically want to dynamically populate the widget choices based on the view. I believe I can achieve that at the moment by manually generating the html in the template.
I think you're looking for ModelChoiceField.
UPDATE: Especially note the queryset argument. In the view that is backing the page, you can change the QuerySet you provide based on whatever criteria you care about.
I haven't tested this, but I'm thinking something along the lines of...
site = forms.IntegerField(
widget=forms.Select(
choices=Site.objects.all().values_list('id', 'name')
)
)
Edit --
I just tried this out and it does generate the choices correctly. The choices argument is expecting a list of 2-tuples like this...
(
(1, 'stackoverflow'),
(2, 'superuser'),
(value, name),
)
The .values_list will return that exact format provided you have the ID and the name/title/whatever as so: .values_list('id', 'name'). When the form is saved, the value of .site will be the id/pk of the selected site.

How would you populate a field based on another field

From the admin panel I want to populate a slug field based on a certain text field
eg.
Title: My Awesome Page
would automaticaly populate
Slug: my_awesome_page
There used to be a prepoulate_from option for the SlugField up to 0.96. It became an admin option after that. See here for reference on that.
Alternatively, you could override the model's save method to calculate the value of the slug field on save().
This question may be helpful, too.
There is also an app called django-autoslug which provides a field type AutoSlugField. Using that, you could have:
class Something(models.Model):
title = models.CharField(max_lenght=200)
slug = AutoSlugField(populate_from='title')
...
This AutoSlugField has many nice features, such as generating a slug so that it is unique either globally of combined with some other field (maybe a category or the year part of a DateTimeField).
See http://pypi.python.org/pypi/django-autoslug for further details.