yourlabs / django-autocomplete-light

A fresh approach to autocomplete implementations, specially for Django. Status: v4 alpha, v3 stable, v2 & v1 deprecated.
https://django-autocomplete-light.readthedocs.io
MIT License
1.81k stars 468 forks source link

TypeError with TagSelect2 #669

Open AchilleAsh opened 8 years ago

AchilleAsh commented 8 years ago

Hello,

I just updated to 3.1.5 and my TagSelect2 widgets stopped working :

TypeError at xxxx can only join an iterable

Django Version: 1.9.5 Exception Type: TypeError Exception Value:
can only join an iterable Exception Location: [...]/dal_select2/widgets.py in value_from_datadict, line 61

values = super(TagSelect2, self).value_from_datadict(data, files, name)
        return six.text_type(',').join(values)

a print showed me that values var is None, hence the TypeError. According to Django's documentation this method can return None : this is missing here and that's causing the TypeError. A simple wrap with try/except will fix this ; as I don't understand the function of value_from_datadict (which was not in 3.0), I abstained from submitting a PR.

Thank you for your work!

jpic commented 8 years ago

What are the models, forms, urls and the full traceback like ? On Apr 8, 2016 12:16 AM, "Timothé Perez" notifications@github.com wrote:

Hello,

I just updated to 3.1.5 and my TagSelect2 widgets stopped working :

TypeError at xxxx can only join an iterable

Django Version: 1.9.5 Exception Type: TypeError Exception Value:

can only join an iterable Exception Location: [...]/dal_select2/widgets.py in value_from_datadict, line 61

values = super(TagSelect2, self).value_from_datadict(data, files, name) return six.text_type(',').join(values)

a print showed me that values var is None, hence the TypeError. According to Django's documentation https://docs.djangoproject.com/fr/1.9/_modules/django/forms/widgets/#Widget.value_from_datadict this method can return None : this is missing here and that's causing the TypeError. A simple wrap with try/except will fix this ; as I don't understand the function of value_from_datadict (which was not in 3.0), I abstained from submitting a PR.

Thank you for your work!

— You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub https://github.com/yourlabs/django-autocomplete-light/issues/669

ggilley commented 8 years ago

I have the same problem. I think there's a problem with taggit and django 1.9.5:

urls.py: url( r'^tag-autocomplete/$', TagAutocomplete.as_view(create_field='name'), name='tag-autocomplete', ),

forms.py: class MyEditForm(forms.Form): tags = TagField(required=False, widget=autocomplete.TaggitSelect2('tag-autocomplete'))

views.py: from dal import autocomplete

from taggit.models import Tag

class TagAutocomplete(autocomplete.Select2QuerySetView): def get_queryset(self):

Don't forget to filter out results depending on the visitor !

    if not self.request.user.is_authenticated():
        print "TagAutoComplete: user not authenticated"
        return Tag.objects.none()
    qs = Tag.objects.all()

    if self.q:
        qs = qs.filter(name__istartswith=self.q)

    print "TagAutoComplete: ", qs

    return qs

Traceback (most recent call last): File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py", line 149, in get_response response = self.process_exception_by_middleware(e, request) File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py", line 147, in get_response response = wrapped_callback(request, _callback_args, _callback_kwargs) File "/usr/local/lib/python2.7/dist-packages/django/utils/decorators.py", line 184, in inner return func(_args, _kwargs) File "/usr/local/lib/python2.7/dist-packages/django/contrib/auth/decorators.py", line 23, in _wrapped_view return view_func(request, _args, *_kwargs) File "/vagrant/foodcircle/recipes/views.py", line 310, in recipe_edit return render(request, 'recipes/recipe/edit.html', { 'form': form }) File "/usr/local/lib/python2.7/dist-packages/django/shortcuts.py", line 67, in render template_name, context, request=request, using=using) File "/usr/local/lib/python2.7/dist-packages/django/template/loader.py", line 97, in render_to_string return template.render(context, request) File "/usr/local/lib/python2.7/dist-packages/django/template/backends/django.py", line 95, in render return self.template.render(context) File "/usr/local/lib/python2.7/dist-packages/django/template/base.py", line 206, in render return self._render(context) File "/usr/local/lib/python2.7/dist-packages/django/test/utils.py", line 92, in instrumented_test_render return self.nodelist.render(context) File "/usr/local/lib/python2.7/dist-packages/django/template/base.py", line 992, in render bit = node.render_annotated(context) File "/usr/local/lib/python2.7/dist-packages/django/template/base.py", line 959, in render_annotated return self.render(context) File "/usr/local/lib/python2.7/dist-packages/django/template/loader_tags.py", line 173, in render return compiled_parent._render(context) File "/usr/local/lib/python2.7/dist-packages/django/test/utils.py", line 92, in instrumented_test_render return self.nodelist.render(context) File "/usr/local/lib/python2.7/dist-packages/django/template/base.py", line 992, in render bit = node.render_annotated(context) File "/usr/local/lib/python2.7/dist-packages/django/template/base.py", line 959, in render_annotated return self.render(context) File "/usr/local/lib/python2.7/dist-packages/django/template/loader_tags.py", line 69, in render result = block.nodelist.render(context) File "/usr/local/lib/python2.7/dist-packages/django/template/base.py", line 992, in render bit = node.render_annotated(context) File "/usr/local/lib/python2.7/dist-packages/django/template/base.py", line 959, in render_annotated return self.render(context) File "/usr/local/lib/python2.7/dist-packages/django/template/base.py", line 1043, in render output = self.filter_expression.resolve(context) File "/usr/local/lib/python2.7/dist-packages/django/template/base.py", line 709, in resolve obj = self.var.resolve(context) File "/usr/local/lib/python2.7/dist-packages/django/template/base.py", line 850, in resolve value = self._resolve_lookup(context) File "/usr/local/lib/python2.7/dist-packages/django/template/base.py", line 913, in _resolve_lookup current = current() File "/usr/local/lib/python2.7/dist-packages/django/forms/forms.py", line 281, in as_p errors_on_separate_row=True) File "/usr/local/lib/python2.7/dist-packages/django/forms/forms.py", line 180, in _html_output top_errors = self.non_field_errors() # Errors that should be displayed above all fields. File "/usr/local/lib/python2.7/dist-packages/django/forms/forms.py", line 289, in non_field_errors return self.errors.get(NON_FIELD_ERRORS, self.error_class(error_class='nonfield')) File "/usr/local/lib/python2.7/dist-packages/django/forms/forms.py", line 153, in errors self.full_clean() File "/usr/local/lib/python2.7/dist-packages/django/forms/forms.py", line 362, in full_clean self._clean_fields() File "/usr/local/lib/python2.7/dist-packages/django/forms/forms.py", line 374, in _clean_fields value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name)) File "/usr/local/lib/python2.7/dist-packages/dal_select2/widgets.py", line 61, in value_from_datadict return six.text_type(',').join(values) TypeError: can only join an iterable

ggilley commented 8 years ago

As AchilleAsh mentioned, there's a None object being passed to the join:

/usr/local/lib/python2.7/dist-packages/dal_select2/widgets.py in value_from_datadict def value_from_datadict(self, data, files, name): """Return a comma-separated list of options. This is needed because Select2 uses a multiple select even in tag mode, and the model field expects a comma-separated list of tags. """ values = super(TagSelect2, self).value_from_datadict(data, files, name) return six.text_type(',').join(values) ... ▼ Local vars Variable Value files
{'image': , 'recipe_as_image': } data
{'activetime': u'', 'cooktime': u'', 'description': u'', 'inactivetime': u'', 'ingredients': '3/4 pound butter (3 sticks)\n2 cups sugar\n9 large eggs\n1 vanilla bean or 2 t vanilla extract\n2 cups flour\n1/2 teaspoon baking powder\n1/4 teaspoon salt\n', 'name': u'9-egg Pound Cake', 'preptime': u'', 'recipeyield': u'1 loaf pan', 'steps': 'Preheat oven to 350\xc2\xb0\nCream butter and sugar in a mixer until fluffy. \nAdd eggs one at a time.\nStir in vanilla.\nStir in flour mixture.\nPour into prepared loaf pan.\nBake 1 hour.\n', 'totaltime': u''} self
<dal_select2_taggit.widgets.TaggitSelect2 object at 0xaf8c080c> values
None name
'tags'

jpic commented 8 years ago

Perhaps it would be readable with just a bit of presentational effort ?

jpic commented 8 years ago

Is it still possible to reproduce this ? Perhaps on the hosted test project ?

AchilleAsh commented 8 years ago

I ended up using a different approach and removed TagSelect2 use in my project, so I don't have the problem now. When digging around to find what was wrong, I found that dal isn't consistent with the django doc stating that the method could return None, that's why I opened an issue; but it seems to have little or no impact, except for the consistency with django api.