Albina
Albina

Reputation: 25

How to store the default value for a Django form in the database?

I have a page with bookmarks and I want to implement several types of sorting for them. The user chooses the type of sorting and it's stored in the database. He/she sees the chosen type of sorting as the default value for the select-menu.

I wrote this:

class BookmarksSortingForm(forms.Form):

    SORTING_CHOICES =   [(1, "новым"),
                        (2, "имени"),
                        (3, "звёздам -"),
                        (4, "звёздам +")]

    bm_sorting = forms.ChoiceField(SORTING_CHOICES)

    # https://stackoverflow.com/questions/6325681/passing-a-user-request-to-forms
    # In your view: form = MyForm(..., request=request)
    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop("request", None)
        super().__init__(*args, **kwargs)
        self.fields['bm_sorting'].initial = BookmarksSortingForm.SORTING_CHOICES[self.get_current_sorting() - 1][1]

    def get_current_sorting(self):
        user = User.objects.get(username=self.request.user)
        return user.profile.bookmarks_sorting # small integer, default = 1

But I get "TypeError: init() takes 1 positional argument but 2 were given" at the line with bm_sorting. How could I fix this? Django version is 3.2.4.

Upd: Traceback

Traceback (most recent call last):
  File "/home/gamecoach/.virtualenvs/django3/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/home/gamecoach/.virtualenvs/django3/lib/python3.8/site-packages/django/utils/deprecation.py", line 116, in __call__
    response = self.process_request(request)
  File "/home/gamecoach/.virtualenvs/django3/lib/python3.8/site-packages/django/middleware/common.py", line 53, in process_request
    if self.should_redirect_with_slash(request):
  File "/home/gamecoach/.virtualenvs/django3/lib/python3.8/site-packages/django/middleware/common.py", line 70, in should_redirect_with_slash
    if not is_valid_path(request.path_info, urlconf):
  File "/home/gamecoach/.virtualenvs/django3/lib/python3.8/site-packages/django/urls/base.py", line 153, in is_valid_path
    return resolve(path, urlconf)
  File "/home/gamecoach/.virtualenvs/django3/lib/python3.8/site-packages/django/urls/base.py", line 24, in resolve
    return get_resolver(urlconf).resolve(path)
  File "/home/gamecoach/.virtualenvs/django3/lib/python3.8/site-packages/django/urls/resolvers.py", line 556, in resolve
    for pattern in self.url_patterns:
  File "/home/gamecoach/.virtualenvs/django3/lib/python3.8/site-packages/django/utils/functional.py", line 48, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/home/gamecoach/.virtualenvs/django3/lib/python3.8/site-packages/django/urls/resolvers.py", line 598, in url_patterns
    patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
  File "/home/gamecoach/.virtualenvs/django3/lib/python3.8/site-packages/django/utils/functional.py", line 48, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/home/gamecoach/.virtualenvs/django3/lib/python3.8/site-packages/django/urls/resolvers.py", line 591, in urlconf_module
    return import_module(self.urlconf_name)
  File "/home/gamecoach/.virtualenvs/django3/lib/python3.8/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
    <source code not available>
  File "<frozen importlib._bootstrap>", line 991, in _find_and_load
    <source code not available>
  File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked
    <source code not available>
  File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
    <source code not available>
  File "<frozen importlib._bootstrap_external>", line 783, in exec_module
    <source code not available>
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
    <source code not available>
  File "/home/gamecoach/Seearo/Seearo/urls.py", line 23, in <module>
    re_path('account/?', include('account.urls')),
  File "/home/gamecoach/.virtualenvs/django3/lib/python3.8/site-packages/django/urls/conf.py", line 34, in include
    urlconf_module = import_module(urlconf_module)
  File "/home/gamecoach/.virtualenvs/django3/lib/python3.8/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
    <source code not available>
  File "<frozen importlib._bootstrap>", line 991, in _find_and_load
    <source code not available>
  File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked
    <source code not available>
  File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
    <source code not available>
  File "<frozen importlib._bootstrap_external>", line 783, in exec_module
    <source code not available>
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
    <source code not available>
  File "/home/gamecoach/Seearo/account/urls.py", line 2, in <module>
    from account.views import AccountView, AchievementsView, AddToBookmarksView, \
  File "/home/gamecoach/Seearo/account/views.py", line 8, in <module>
    from account.forms import SettingsForm, UploadPhotoForm
  File "/home/gamecoach/Seearo/account/forms.py", line 6, in <module>
    class BookmarksSortingForm(forms.Form):
  File "/home/gamecoach/Seearo/account/forms.py", line 13, in BookmarksSortingForm
    bm_sorting = forms.ChoiceField(SORTING_CHOICES)

Exception Type: TypeError at /account/bookmarks.html
Exception Value: __init__() takes 1 positional argument but 2 were given

Upd2: The answer below helped:

bm_sorting = forms.ChoiceField(choices=SORTING_CHOICES)

and I also had to change a bit this line:

self.fields['bm_sorting'].initial = BookmarksSortingForm.SORTING_CHOICES[self.get_current_sorting() - 1]

and it started to show my form.

Upvotes: 0

Views: 39

Answers (1)

Alexandr Tatarinov
Alexandr Tatarinov

Reputation: 4034

You must pass a keyword argument instead of positional to the forms.ChoiceField.

bm_sorting = forms.ChoiceField(choices=SORTING_CHOICES)

Here is how the ChoiceField is defined in Django. Notice the * after self - this denotes that only keyword arguments will be accepted.

class ChoiceField(Field):
    def __init__(self, *, choices=(), **kwargs):
        super().__init__(**kwargs)
        self.choices = choices

Upvotes: 1

Related Questions