MultipleChoiceField with massive choices best practice - python

I need have MultipleChoiceField field in a form that should have over 50000 choices, therefore I cannot render it properly; I emptied the choices and went through an Ajax call to filter the options depending on the user inputs. Problem is that Django is obviously complaining that the choice is not part of the empty choices I provided.
I think of three solutions to fix this but would like to know which one is 'best practice' or if there was a better one :
Create a second form which I check when the request is POST, same as the first one but with the choices initialized at the server starts
Define the __init__ of the form where if passed a parameter it would set choices to a variable initialized outside the form at the server starts
Find a way to display the input without displaying the options in the template

I went through the second option:
in the class object the queryset / choices is set to the full list
in the init it is set to empty
This show nothing in the template (and I add through Ajax) but allow everything in the cleaning

Related

Django: validation fails for many-to-many field with empty QueryDict as initial data

Setup:
Python 3.5.1 with Django 1.9.
I have a class-based generic view CreateRentView operating on the model Rent. I implemented a custom ModelForm RentForm to implement additional validations (e.g., ensure start_time <= end_time).
When creating a new Rent (via CreateRentView), first user defines start and end time. This triggers an AJAX request to get the available objects for this time frame and fills the rental_objects HTML widget using Javascript (see screenshot below).
Problem:
Everything is working fine (custom validation and AJAX communication), but when submitting the form I get a validation error for (many-to-many) field rental_objects: Select a valid choice. 1 is not one of the available choices.
Note: in the screenshot below, rental object MB1 was selected before submitting the form.
This is caused because I want to initialize the field rental_objects empty. Therefore, method get_form() of class CreateRentView sets form field rental_objects to an empty QuerySet:
def get_form(self):
form = super(generic.CreateView, self).get_form()
# Rental objects are retrieved via AJAX after start and end time is defined.
form.fields["rental_objects"].queryset = RentalObject.objects.none()
Obviously this triggers an internal Django validation that ensures that this field is submitted empty.
How can I avoid this validation?
PS: Of course, I could not override get_form() and empty the HTML widget for rental_objects using Javascript. But, this would be just a messy workaround
Django-AJAX-ManyToManyField:
I believe this is from your rental objects' choices.
If you use integers for your choices you should use IntegerField. For CharField use strings

How to give extra kwargs to a modelform field - Django

I'm trying to create a simple cropping utility using jQuery and Jcrop (would be inside a modelform).
Initially I had this in my models:
photo = CustomImageField(null=True, allowed_types=['type:image'],
width=960, height=340)
However now I have Jcrop data (that I would like to insert for 'width' and 'height' parameters) in my main.js and would have to be sent to Django.
To do that, I created a hidden form field in my modelform and I populate it with jQuery after the user has created a selection (a default is also provided, in case the user does not select anything).
I was thinking that maybe I could add the extra keyword arguments when I override the form save() method, but
a) does it pass the kwargs to the CustomImageField?
b) I have no idea (syntax-wise) how to get/add/edit the kwargs of photo.
I've tried self.fields['photo'].kwargs, self.fields['photo'].getattr('width') and many other similar constructions that I've used in the past, but none provided any results.
After some googling I stumbled upon x = kwargs.pop('y', None) (it's not the same as list.pop(), is it?), but was unable to find any documentation on that and overall I get the feeling, that when I call kwargs.pop(x, y) in the save() method, then it handles the kwargs of the save() method, no matter what I set for x and y.
A little help or a hint in the right direction would be much appreciated guys, been stuck with this for days now. :)
PS. I am well aware of django-image-cropping and also well aware of that it fails to function with some specific generic Django views.

Django forms.Choicefield get selected Choice

I need to get the selected Value of a forms.Choicefield for an if/else statement which produces another forms.Choicefield based on the selected Value
forms.py:
class ReceiverForm(forms.Form):
receivers = forms.ChoiceField(choices=db_mails(), required=True, label='Receivers')
if db_certs(<- selected value from receivers ChoiceField ->):
print "cert found"
encryption = forms.ChoiceField(choices=EncryptionChoiceAll, initial='smime_mail', required=True, label='Encryption')
else:
print "no cert found"
encryption = forms.ChoiceField(choices=EncryptionChoiceNoCert, initial='smime_mail', required=True, label='Encryption')
db_mails() and db_certs(mail) are working as expected
Is there a way to achieve what i need in forms.py or am I totally wrong with the design?
When the form is built and you specify the choice list, you have no way to know which value is selected, as:
You create an instance of the form class
This instance is used to create the view (On a GET request). The user can modify the selection
He submits the form. For this you create an instance of the class, which is filled with the POST values.
So at the time you create the class you do not have the information.
There are possibilities to have dynamic values in one choice, depending on the other one, but this needs to be done on the client side, when the user changes the selection:
Use javascript/jquery to update the list of choices depending on the answer. For this, you could have hidden values in the HTML file, and Javascript will update the list from these hidden values.
If the choice to update is more dynamic (For example a list of towns depending on the post code), you still need to use Javascript, but with Ajax that will send an asynchronous request to the server to get the list and update the choices.
There are plenty of tutorials to do this, and this is not directly linked to Django. As an example:
https://css-tricks.com/dynamic-dropdowns/

Database queries with ModelForm Model(Multiple) Choice fields in Django

I have a form with some Model(Multiple)Choice fields that have so many options that I would like to trim down the available options based on user responses on the front-end, and then populate the select options through AJAX.
I am a little confused as to when Django will query the database in this case, and what are considered the best practices for Django ModelChoice fields that are populated with AJAX data.
Originally, I had been doing things like this:
contact = forms.ModelChoiceField(queryset=aRelatedModel.objects.all())
or a restricted queryset:
contact = forms.ModelChoiceField(queryset=aRelatedModel.objects.filter(somefield = someValue))
So, my question is, when does the DB get queried for ModelChoice options?
The confusion stems from another form I did, where I had a ModelChoiceField with the ability to add new options dynamically. In that case, unless I instantiated the ModelChoiceField after saving the new option, I would get an error. This makes me feel like the database is queried on form instantiation. But, given the lazy nature of Django querysets, it seems like it would also make sense that the DB is not queried until you iterate over said list (ie, when printing the form options).
So, in this kind of case is there a way to avoid potentially needless DB queries? What is the best practice for ModelChoiceFields that will be populated with AJAX data?
I've seen mentions of:
contact = forms.ModelChoiceField(queryset=aRelatedModel.objects.none())
...but never any explicit explanation on why to use this.
Edit:
In that case, I had a form with
field = forms.ModelChoiceField(queryset = relatedModel.objects.all())
Subsequently in the view, I naively did:
myForm = modelForm(request.POST). This produced an error if I instantiated the form before first saving the dynamically added field. After adding the field, and then calling modelForm(request.POST) I no longer had an "invalid choice" error - presumably because the dynamically added field was now included in the modelForm queryset.
I am not sure how that is relevant to the question, however. The question is when a modelForm's queryset is populated with data from the DB.

Django best practice for displaying mostly read-only form, one field writeable

I have a requirement where one user creates an 'instance' of an object via a ModelForm. Another user of a different group has access to read all of the fields of the form, but has to update only one field. Think of a student who creates an exam object. Then a teach pulls up the exam and just needs to put in a grade, the rest of the exam is read only.
What's the best way to do that? Should I just query for the object, and display each field individually, then create a form (not a ModelForm?) for just the one field?
Should I just query for the object, and display each field individually, then create a form (not a ModelForm?) for just the one field?
This is probably the best way to go about it. Note you can use a ModelForm for the teacher form, see the Django documentation on using a subset of fields on a model form. You will have to display all the other fields manually in your template, but you should probably have a separate template for this view (I would use separate views as well).
You could find some code for a read only field on Django Snippets, but generally it's better to be explicit about what fields you are updating from each view. This is likely to be more trouble than it's worth.

Categories

Resources