Open CoryADavis opened 5 years ago
Nice 0day hack !
Accepted, let's see what a pull request looks like :joy:
Apologies, I'm really naive when it comes to this sort of thing! Does that mean my code has some sort of vulnerability in it?
Well you said your patches were hacks, and you found them the day you opened the issue so it's like a 0day hack you hacker you.
I don't understand the last filter_choices_to_render:
self.choices.queryset = self.choices.queryset.filter(
choice__in=[c for c in selected_choices if c]
Shouldn't it be more like ?
filter(**{
self.to_field_name or 'pk' + '__in': [c for c in selected_choices if c]
})
OH, haha! You're likely right about the filter_choices_to_render, will test the change!
Go ahead and submit a pull request if you feel like it.
Have fun !
I went with a similar hack recently:
class BaseForm(forms.ModelForm):
form_specific_option = None
field1 = autocomplete.Select2ListChoiceField(
get_all_options(),
widget=autocomplete.ListSelect2(url='autocomplete-url'),
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
field1_widget = self.fields['field1'].widget
field1_widget.initial = self.initial.get('field1', '')
field1_widget.forward = [
'field2',
forward.Const(self.form_specific_option, 'option'),
]
I was wondering why displaying the initial value is not the default behavior in the first place?
Thanks for the help everyone! I was struggling populating the value for a field that doesn't have a defined list of choices in advance.
In case of anyone searching from google like me - keywords are: populate, initial value, Select2ListCreateChoiceField
class FlatUsageForm(forms.ModelForm):
project_name = autocomplete.Select2ListCreateChoiceField(
widget=autocomplete.Select2(
url="project-autocomplete", attrs={"data-tags": "true"}
),
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if self.instance.id:
project_name_field = self.fields['project_name']
project_name = self.instance.project.name
project_name_field.initial = project_name
project_name_field.choices = [(project_name, project_name)]
This should definitely be documented somewhere
I can't believe this isn't documented somewhere! This fix was crazy hard to find.
Someone can help me solve this problem with "Select2Multiple" If I use the example above the Multiselect-Field is populated but the value is a single list item.
class ExportTemplateForm(forms.ModelForm):
content_type = forms.ModelChoiceField(
queryset=ContentType.objects.all(),
required=True,
widget=autocomplete.ModelSelect2(url="custom_export:content_type-autocomplete"),
label="Datenbank",
)
columns = forms.MultipleChoiceField(
required=False, widget=autocomplete.Select2Multiple(), label="Felder"
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
content_type = self.instance.content_type if self.instance.pk else None
if content_type:
model = content_type.model_class()
self.fields["columns"].widget.url = "custom_export:column-autocomplete"
self.fields["columns"].choices = [
(field.name, field.verbose_name) for field in model._meta.fields
]
self.fields["columns"].widget.attrs.update(
{"data-placeholder": "Wählen Sie Felder aus..."}
)
self.fields["columns"].widget.forward = ["content_type"]
# Setze die initialen Werte für das columns-Feld basierend auf der Modellinstanz
if self.instance.id:
project_name_field = self.fields["columns"]
project_name = self.instance.columns
project_name_field.initial = project_name.split(",")
project_name_field.choices = [(project_name, project_name)]
Someone can help me solve this problem with "Select2Multiple" If I use the example above the Multiselect-Field is populated but the value is a single list item.
class ExportTemplateForm(forms.ModelForm): content_type = forms.ModelChoiceField( queryset=ContentType.objects.all(), required=True, widget=autocomplete.ModelSelect2(url="custom_export:content_type-autocomplete"), label="Datenbank", ) columns = forms.MultipleChoiceField( required=False, widget=autocomplete.Select2Multiple(), label="Felder" ) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) content_type = self.instance.content_type if self.instance.pk else None if content_type: model = content_type.model_class() self.fields["columns"].widget.url = "custom_export:column-autocomplete" self.fields["columns"].choices = [ (field.name, field.verbose_name) for field in model._meta.fields ] self.fields["columns"].widget.attrs.update( {"data-placeholder": "Wählen Sie Felder aus..."} ) self.fields["columns"].widget.forward = ["content_type"] # Setze die initialen Werte für das columns-Feld basierend auf der Modellinstanz if self.instance.id: project_name_field = self.fields["columns"] project_name = self.instance.columns project_name_field.initial = project_name.split(",") project_name_field.choices = [(project_name, project_name)]
@rene-schwabe were you able to solve this issue, facing the same.. Thank you
I'm working with a large FormWizard, and the way that users will interact with the data after form submission is such that Foreign Key fields in the model would be a problem. So, I'm using the plain Select2, not ModelSelect2.
The Select2 works! You can submit the form, and the selection comes through just fine. But, if you go to edit, the initial values populate for everything but the example Select2 field. It's not just a display issue, if you submit the edit, the value is blanked out in the database.
My question, is this supported and not working as a bug, or implementation failure on my part? Or is this not supported? If not, how might this be accomplished? I've tried setting the initial in the choice field manually, but that didn't appear to be the answer like in other issues I saw while searching my problem.
-- EDIT START --
I solved my problem, it's not supported, using ModelSelect2 is specifically what's required to get the information needed to set the initial values. I used a combination of seemingly hacky nonsense to get it to work without using a foreign key. Is there a more proper way to do this? If so, would that be a good addition to the documentation?
hacky forms.py snippet
hacky widgets.py snippet (just the filter_choices_to_render)
-- EDIT END --
models.py snippet
forms.py snippet (CustomSelect2 is just Select2 with media for bootstrap styling)
forms.py alternate snippet (This is the failed setting initial attempt)
views.py snippet