applegrew / django-select2

This is a Django integration for Select2

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

ModelSelect2TagWidget tagging new values

Mergpijp opened this issue · comments

Describe the bug
Clearly given 4 arguments but it says 5 were given..

Exception & Traceback
value_from_datadict() takes 4 positional arguments but 5 were given

values = super().value_from_datadict(self, data, files, name) at line 205

Code Snippet
From the documentation in forms.py:

class KeywordSelect2TagWidget(ModelSelect2TagWidget):
    queryset = Keyword.objects.all()

    def value_from_datadict(self, data, files, name):
        values = super().value_from_datadict(self, data, files, name)
        queryset = self.get_queryset()
        pks = queryset.filter(**{'pk__in': list(values)}).values_list('pk', flat=True)
        cleaned_values = []
        for val in values:
            if force_text(val) not in pks:
                val = queryset.create(title=val).pk
            cleaned_values.append(val)
        return cleaned_values

In forms.py:

    keywords = forms.ModelMultipleChoiceField(widget=KeywordSelect2TagWidget(
        model=Keyword,
        search_fields=['name__icontains',],
        attrs={'data-minimum-input-length': 0,},
    ),queryset=Keyword.objects.all(), required=False)
class <class 'publications.forms.KeywordSelect2TagWidget'>
data {'ISBN_number': '', 'collection_country': '', 'collection_date': '', 'collection_venue_and_city': '', 'contact_email': '', 'contact_telephone_number': '', 'contact_website': '', 'content_description': '', 'copyrights': 'unknown', 'csrfmiddlewaretoken': 'AzfnVs88SWyp5j1BO71TpD5dHBfHEbKK1dvJaSDuRGGmws0jaU3PydWitibwU5z4', 'description_of_illustration': '', 'donor': '', 'editor': '', 'extra_info': '', 'general_comments': '', 'is_a_translation': '', 'keywords': 'm', 'nr_of_pages': '', 'printed_by': '', 'publication_city': '', 'publication_date': '', 'published_by': '', 'publishing_organisation': '', 'save': 'Save', 'team_comments': '', 'title_original': '', 'title_subtitle_European': '', 'title_subtitle_transcription': '', 'title_translation': '', 'translated_from': ''}
files <MultiValueDict: {}>
name 'keywords'
self <publications.forms.KeywordSelect2TagWidget object at 0x00000287D6A72780>

To Reproduce
Add new tags or existing tags to the keywords field.

Expected behavior
Expected it to work with existing keywords but the error persists.

Hi @Mergpijp thanks for the detailed error report. This isn't a bug though. It's a simple Python mistake. You don't pass self to a super call, that is done automatically by the interpreter, same as you don't have to add self on a regular method call on an object instance.

Following your example:

values = super().value_from_datadict(data, files, name)

Dear Joe,

I tried running it without the self argument but it is still not working.
I will show you my model:

class Keyword(models.Model):
    name = models.CharField(max_length=255, blank=True)

    def __str__(self):
        return self.name

I even tried to change title to name from the given code in the documentation.

val = queryset.create(name=val).pk

It will give : invalid literal for int() with base 10: 'hey' If i put 'hey' as tag.
Referring to:

pks = queryset.filter(**{'pk__in': list(values)}).values_list('pk', flat=True)

Any idea how to get this to work?

Hi @Mergpijp do could you provide the entire traceback please? It would help me to narrow down the issue. Best Joe

Hi @codingjoe, this time i tried entering 'something' here is the traceback:

Environment:


Request Method: POST
Request URL: http://127.0.0.1:8000/publication/new/

Django Version: 2.2.10
Python Version: 3.7.3
Installed Applications:
['publications',
 'django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'bootstrap4',
 'crispy_forms',
 'django_select2',
 'countries_plus']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']



Traceback:

File "C:\Users\Emmanuel\Documents\projects\globort\lib\site-packages\django\core\handlers\exception.py" in inner
  34.             response = get_response(request)

File "C:\Users\Emmanuel\Documents\projects\globort\lib\site-packages\django\core\handlers\base.py" in _get_response
  115.                 response = self.process_exception_by_middleware(e, request)

File "C:\Users\Emmanuel\Documents\projects\globort\lib\site-packages\django\core\handlers\base.py" in _get_response
  113.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "C:\Users\Emmanuel\Documents\projects\globort\lib\site-packages\django\contrib\auth\decorators.py" in _wrapped_view
  21.                 return view_func(request, *args, **kwargs)

File "C:\Users\Emmanuel\Documents\projects\globort\lib\site-packages\django\views\generic\base.py" in view
  71.             return self.dispatch(request, *args, **kwargs)

File "C:\Users\Emmanuel\Documents\projects\globort\lib\site-packages\django\views\generic\base.py" in dispatch
  97.         return handler(request, *args, **kwargs)

File "C:\Users\Emmanuel\Documents\projects\globort\lib\site-packages\django\views\generic\edit.py" in post
  172.         return super().post(request, *args, **kwargs)

File "C:\Users\Emmanuel\Documents\projects\globort\lib\site-packages\django\views\generic\edit.py" in post
  141.         if form.is_valid():

File "C:\Users\Emmanuel\Documents\projects\globort\lib\site-packages\django\forms\forms.py" in is_valid
  185.         return self.is_bound and not self.errors

File "C:\Users\Emmanuel\Documents\projects\globort\lib\site-packages\django\forms\forms.py" in errors
  180.             self.full_clean()

File "C:\Users\Emmanuel\Documents\projects\globort\lib\site-packages\django\forms\forms.py" in full_clean
  381.         self._clean_fields()

File "C:\Users\Emmanuel\Documents\projects\globort\lib\site-packages\django\forms\forms.py" in _clean_fields
  393.                 value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name))

File "C:\Users\Emmanuel\Documents\projects\GlobalOrthodoxy\publications\forms.py" in value_from_datadict
  207.         pks = queryset.filter(**{'pk__in': list(values)}).values_list('pk', flat=True)

File "C:\Users\Emmanuel\Documents\projects\globort\lib\site-packages\django\db\models\query.py" in filter
  892.         return self._filter_or_exclude(False, *args, **kwargs)

File "C:\Users\Emmanuel\Documents\projects\globort\lib\site-packages\django\db\models\query.py" in _filter_or_exclude
  910.             clone.query.add_q(Q(*args, **kwargs))

File "C:\Users\Emmanuel\Documents\projects\globort\lib\site-packages\django\db\models\sql\query.py" in add_q
  1290.         clause, _ = self._add_q(q_object, self.used_aliases)

File "C:\Users\Emmanuel\Documents\projects\globort\lib\site-packages\django\db\models\sql\query.py" in _add_q
  1318.                     split_subq=split_subq, simple_col=simple_col,

File "C:\Users\Emmanuel\Documents\projects\globort\lib\site-packages\django\db\models\sql\query.py" in build_filter
  1251.         condition = self.build_lookup(lookups, col, value)

File "C:\Users\Emmanuel\Documents\projects\globort\lib\site-packages\django\db\models\sql\query.py" in build_lookup
  1116.         lookup = lookup_class(lhs, rhs)

File "C:\Users\Emmanuel\Documents\projects\globort\lib\site-packages\django\db\models\lookups.py" in __init__
  20.         self.rhs = self.get_prep_lookup()

File "C:\Users\Emmanuel\Documents\projects\globort\lib\site-packages\django\db\models\lookups.py" in get_prep_lookup
  210.                 rhs_value = self.lhs.output_field.get_prep_value(rhs_value)

File "C:\Users\Emmanuel\Documents\projects\globort\lib\site-packages\django\db\models\fields\__init__.py" in get_prep_value
  972.         return int(value)

Exception Type: ValueError at /publication/new/
Exception Value: invalid literal for int() with base 10: 'something'

Hi @Mergpijp,

Ok, so what you need to do here, is to remove all strings from list of possible keys:

class KeywordSelect2TagWidget(ModelSelect2TagWidget):
    queryset = Keyword.objects.all()

    def value_from_datadict(self, data, files, name):
        values = super().value_from_datadict(self, data, files, name)
        queryset = self.get_queryset()
        pks = queryset.filter(**{'pk__in': [v for v in values if v.isdigit())}).values_list('pk', flat=True)
        cleaned_values = []
        for val in values:
            if force_text(val) not in pks:
                val = queryset.create(title=val).pk
            cleaned_values.append(val)
        return cleaned_values

Hi @codingjoe ,

There was a typo in your code the list comprehension did not close. I have the following code:

class KeywordSelect2TagWidget(ModelSelect2TagWidget):
    queryset = Keyword.objects.all()

    def value_from_datadict(self, data, files, name):
        values = super().value_from_datadict(data, files, name)
        queryset = self.get_queryset()
        pks = queryset.filter(**{'pk__in': [v for v in values if v.isdigit()]}).values_list('pk', flat=True)
        cleaned_values = []
        for val in values:
            if force_text(val) not in pks:
                val = queryset.create(name=val).pk
            cleaned_values.append(val)
        return cleaned_values

Now it works when I enter black and press save the form will have black as keyword. However if then enter white and save. It will have an integer as keyword and white. If enter Orange and save. It will have 2 integers and Orange as keyword. Something is still wrong.

Honestly, at this point, you a probably best served with a debugger. Maybe use pdb and set a breakpoint in the for loop. I am sorry, I can't be of better help.

Ok installed django-pdb with breakpoint() in the code. How do I inspect variables? I am using pycharm at the moment.
EDIT
Never mind i found out how.

Hi @codingjoe,

I solved this the only downside is that you cannot use integers as tag. Here is the code:

EDIT
there is no downside..

def represent_int(s):
    try:
        int(s)
        return True
    except ValueError:
        return False


class KeywordSelect2TagWidget(ModelSelect2TagWidget):
    queryset = Keyword.objects.all()

    def value_from_datadict(self, data, files, name):
        values = super().value_from_datadict(data, files, name)
        print(values)
        queryset = self.get_queryset()
        pks = queryset.filter(**{'pk__in': [v for v in values if v.isdigit()]}).values_list('pk', flat=True)
        cleaned_values = []
        for val in values:
            if represent_int(val) and int(val) not in pks or not represent_int(val) and force_text(val) not in pks:
                val = queryset.create(name=val).pk
            cleaned_values.append(val)
        return cleaned_values

Thanks for all the help appreciate it!