jazzband / django-smart-selects

chained and grouped selects for django forms
https://django-smart-selects.readthedocs.io/
BSD 3-Clause "New" or "Revised" License
1.13k stars 352 forks source link

Need ChainedCheckboxSelectMultiple widget (checkboxes instead of multi-select) #191

Open toweralaka opened 7 years ago

toweralaka commented 7 years ago

All versions of django-smart-selects prior to version 1.2.8 are vulnerable to an XSS attack as detailed in issue 171. As a result, all previous versions have been removed from PyPI to prevent users from installing insecure versions. All users are urged to upgrade as soon as possible.

Checklist

Steps to reproduce

Expected behavior

Actual behavior

chained m2m breaks when checkboxmultipleselect widget is introduced. All the objects of the m2m field comes up in the template instead of a filtered list

models.py:

class Examination(models.Model):
    name = models.CharField(max_length=20)

class Subject(models.Model):
    examination = models.ForeignKey(Examination, on_delete=models.CASCADE)
    name = models.CharField(max_length=30)

class UserProfile(models.Model):
    user = models.OneToOneField(User)
    examination = models.ForeignKey(Examination, blank=True, null=True)
    subject = ChainedManyToManyField(
        Subject,
        chained_field="examination",
        chained_model_field="examination",
        ) 

forms.py:

class UserProfileForm(forms.ModelForm):
    subject = forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple)

    class Meta:
        model = UserProfile

@blag Please what do you mean by "fill out the template"? it cannot be click; can you expantiate

Edit (by blag): Formatted code with GitHub Flavored Markdown. Edit 2 (by blag): Edited title to reflect the actual issue.

blag commented 7 years ago

@toweralaka When you first filled out the issue form, the template should have already been there in text form:

issue_template

The intent was for users to modify the text of that template when they submitted issues:

issue_template_2

That way users include all of the information I need to help them. It gets super annoying to have to ask everybody who submits an issue to include the exact same information all the time, so the issue template is supposed to save everybody time.

The reason I was so unhelpful before was because you literally had to delete all of the template text to submit your single line issue report. You disregarded ALL of the work I've put in trying to make reporting issues easier!

No worries though! 😎 GitHub does syntax highlight your code if you format it properly - check out the GitHub Flavored Markdown page on code: https://help.github.com/articles/creating-and-highlighting-code-blocks/ That lets you paste your code between ```python ``` blocks like this:

```python
class Examination(models.Model):
    name = models.CharField(max_length=20)

class Subject(models.Model):
    examination = models.ForeignKey(Examination, on_delete=models.CASCADE)
    name = models.CharField(max_length=30)
```

and GitHub will render it like this:

class Examination(models.Model):
    name = models.CharField(max_length=20)

class Subject(models.Model):
    examination = models.ForeignKey(Examination, on_delete=models.CASCADE)
    name = models.CharField(max_length=30)

and that makes it a LOT easier to read.

Anyway, onto solving your issue...

blag commented 7 years ago

As of right now, overriding the widgets for Chained*Field is not supported, because uses its own custom widget. Check out smart_selects/widgets.py.

I would love to add a checkbox widget, but Javascript isn't my forté and I don't really have time.

It shouldn't be too difficult to add your own widget though. You will need to subclass forms.CheckboxSelectMultiple and add smart_selects.widgets.JqueryMediaMixin:

my_widgets.py:

from django.forms import CheckboxSelectMultiple

from smart_selects.widgets import JqueryMediaMixin

class ChainedCheckboxSelectMultiple(JqueryMediaMixin, CheckboxSelectMultiple):
    # ...

And then use that in your form:

from my_widgets import ChainedCheckboxSelectMultiple

class UserProfileForm(forms.ModelForm):
    subject = forms.MultipleChoiceField(widget=ChainedCheckboxSelectMultiple)

    class Meta:
        model = UserProfile

and then fix whatever breaks. You'll need to adjust chainedm2m.js to build a sequence of checkboxes as well.

If you get it working, create a pull request with it and I'll take a look and try to merge it in.

In the meantime, I've added this to the TODO section of the README.

toweralaka commented 7 years ago

Thank you.

ghost commented 6 years ago

I have a related request. I would like to have some sort of auto-comlete field for my ChainedManyToManyField. I have > 20 items to choose from and this is annoying for users. There are lots of auto-complete solutions for Django, but none of them combines nicely with smart selects.

Since @blag says:

but Javascript isn't my forté and I don't really have time.

wouldn't it be a better idea to integrate one of the already available Django widgets for autocomplete? Or even better, create a way to use any widget in combination with smart selects?

blag commented 6 years ago

@bkummel I would highly recommend django-autocomplete-light for your use case. Despite the name, it's actually a complete and well done autocomplete solution for Django. It specifically has a section for filtering the results based on the value of other fields in the form.