0

I created a simple app where you can create poll, after login and see your polls in view. The problem is that I can't align logged in user to my object. It worked fine when I had separate forms to create question and choice, but I want to do dynamic form and have these two forms in one view. I came up with that:

forms.py

class CreateChoiceForm(forms.ModelForm):

    choice_0 = forms.CharField(required=True)
    choice_1 = forms.CharField(required=True)

    class Meta:
        model = Question
        fields = ['question_text']

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        choice = Choice.objects.filter(
            question=self.instance
        )
        for i in range(len(choice) + 1):
            field_name = 'choice_%s' % (i,)
            self.fields[field_name] = forms.CharField(required=False)
            try:
                self.initial[field_name] = choice[i].choice
            except IndexError:
                self.initial[field_name] = ""
            field_name = 'choice_%s' % (i+1,)
            self.fields[field_name] = forms.CharField(required=False)

    def save(self, commit=True):
        question = self.instance
        question.question_text = self.cleaned_data['question_text']
        question.choice_set.all().delete
        question.save()
        for i in range(2):
            choice = self.cleaned_data['choice_%i' % (i)]
            Choice.objects.create(question=question, choice_text=choice)

    def get_interest_fields(self):
        for field_name in self.fields:
            if field_name.startswith('choice_'):
                yield self[field_name]

but now I get this error:

    Environment:


    Request Method: POST
    Request URL: http://127.0.0.1:8000/polls/createPoll/

    Django Version: 2.2.5
    Python Version: 3.6.10
    Installed Applications:
    ['django.contrib.admin',
     'django.contrib.auth',
     'django.contrib.contenttypes',
     'django.contrib.sessions',
     'django.contrib.messages',
     'django.contrib.staticfiles',
     'bootstrap3',
     'pollapp']
    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\MaineKomputere\Anaconda3\envs\MyDjangoEnv\lib\site-packages\django\db\backends\utils.py" in _execute
      84.                 return self.cursor.execute(sql, params)

    File "C:\Users\MaineKomputere\Anaconda3\envs\MyDjangoEnv\lib\site-packages\django\db\backends\sqlite3\base.py" in execute
      383.         return Database.Cursor.execute(self, query, params)

    The above exception (NOT NULL constraint failed: pollapp_question.author_id) was the direct cause of the following exception:

    File "C:\Users\MaineKomputere\Anaconda3\envs\MyDjangoEnv\lib\site-packages\django\core\handlers\exception.py" in inner
      34.             response = get_response(request)

    File "C:\Users\MaineKomputere\Anaconda3\envs\MyDjangoEnv\lib\site-packages\django\core\handlers\base.py" in _get_response
      115.                 response = self.process_exception_by_middleware(e, request)

    File "C:\Users\MaineKomputere\Anaconda3\envs\MyDjangoEnv\lib\site-packages\django\core\handlers\base.py" in _get_response
      113.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

    File "C:\Users\MaineKomputere\Anaconda3\envs\MyDjangoEnv\lib\site-packages\django\views\generic\base.py" in view
      71.             return self.dispatch(request, *args, **kwargs)

    File "C:\Users\MaineKomputere\Anaconda3\envs\MyDjangoEnv\lib\site-packages\django\contrib\auth\mixins.py" in dispatch
      52.         return super().dispatch(request, *args, **kwargs)

    File "C:\Users\MaineKomputere\Anaconda3\envs\MyDjangoEnv\lib\site-packages\django\views\generic\base.py" in dispatch
      97.         return handler(request, *args, **kwargs)

    File "C:\Users\MaineKomputere\Anaconda3\envs\MyDjangoEnv\lib\site-packages\django\views\generic\edit.py" in post
      172.         return super().post(request, *args, **kwargs)

    File "C:\Users\MaineKomputere\Anaconda3\envs\MyDjangoEnv\lib\site-packages\django\views\generic\edit.py" in post
      142.             return self.form_valid(form)

    File "H:\conda\INZ\pollapp\views.py" in form_valid
      71.         poll = form.save(commit=False)

    File "H:\conda\INZ\pollapp\forms.py" in save
      51.         question.save()

    File "C:\Users\MaineKomputere\Anaconda3\envs\MyDjangoEnv\lib\site-packages\django\db\models\base.py" in save
      741.                        force_update=force_update, update_fields=update_fields)

    File "C:\Users\MaineKomputere\Anaconda3\envs\MyDjangoEnv\lib\site-packages\django\db\models\base.py" in save_base
      779.                 force_update, using, update_fields,

    File "C:\Users\MaineKomputere\Anaconda3\envs\MyDjangoEnv\lib\site-packages\django\db\models\base.py" in _save_table
      870.             result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)

    File "C:\Users\MaineKomputere\Anaconda3\envs\MyDjangoEnv\lib\site-packages\django\db\models\base.py" in _do_insert
      908.                                using=using, raw=raw)

    File "C:\Users\MaineKomputere\Anaconda3\envs\MyDjangoEnv\lib\site-packages\django\db\models\manager.py" in manager_method
      82.                 return getattr(self.get_queryset(), name)(*args, **kwargs)

    File "C:\Users\MaineKomputere\Anaconda3\envs\MyDjangoEnv\lib\site-packages\django\db\models\query.py" in _insert
      1186.         return query.get_compiler(using=using).execute_sql(return_id)

    File "C:\Users\MaineKomputere\Anaconda3\envs\MyDjangoEnv\lib\site-packages\django\db\models\sql\compiler.py" in execute_sql
      1335.                 cursor.execute(sql, params)

    File "C:\Users\MaineKomputere\Anaconda3\envs\MyDjangoEnv\lib\site-packages\django\db\backends\utils.py" in execute
      99.             return super().execute(sql, params)

    File "C:\Users\MaineKomputere\Anaconda3\envs\MyDjangoEnv\lib\site-packages\django\db\backends\utils.py" in execute
      67.         return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)

    File "C:\Users\MaineKomputere\Anaconda3\envs\MyDjangoEnv\lib\site-packages\django\db\backends\utils.py" in _execute_with_wrappers
      76.         return executor(sql, params, many, context)

    File "C:\Users\MaineKomputere\Anaconda3\envs\MyDjangoEnv\lib\site-packages\django\db\backends\utils.py" in _execute
      84.                 return self.cursor.execute(sql, params)

    File "C:\Users\MaineKomputere\Anaconda3\envs\MyDjangoEnv\lib\site-packages\django\db\utils.py" in __exit__
      89.                 raise dj_exc_value.with_traceback(traceback) from exc_value

    File "C:\Users\MaineKomputere\Anaconda3\envs\MyDjangoEnv\lib\site-packages\django\db\backends\utils.py" in _execute
      84.                 return self.cursor.execute(sql, params)

    File "C:\Users\MaineKomputere\Anaconda3\envs\MyDjangoEnv\lib\site-packages\django\db\backends\sqlite3\base.py" in execute
      383.         return Database.Cursor.execute(self, query, params)

    Exception Type: IntegrityError at /polls/createPoll/
    Exception Value: NOT NULL constraint failed: pollapp_question.author_id

and when i change `author = models.ForeignKey(User, on_delete=models.CASCADE, null=False)`to `author = models.ForeignKey(User, on_delete=models.CASCADE, null=True)` i've got this error:

Environment:


Request Method: POST
Request URL: http://127.0.0.1:8000/polls/createPoll/

Django Version: 2.2.5
Python Version: 3.6.10
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'bootstrap3',
 'pollapp']
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\MaineKomputere\Anaconda3\envs\MyDjangoEnv\lib\site-packages\django\core\handlers\exception.py" in inner
  34.             response = get_response(request)

File "C:\Users\MaineKomputere\Anaconda3\envs\MyDjangoEnv\lib\site-packages\django\core\handlers\base.py" in _get_response
  115.                 response = self.process_exception_by_middleware(e, request)

File "C:\Users\MaineKomputere\Anaconda3\envs\MyDjangoEnv\lib\site-packages\django\core\handlers\base.py" in _get_response
  113.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "C:\Users\MaineKomputere\Anaconda3\envs\MyDjangoEnv\lib\site-packages\django\views\generic\base.py" in view
  71.             return self.dispatch(request, *args, **kwargs)

File "C:\Users\MaineKomputere\Anaconda3\envs\MyDjangoEnv\lib\site-packages\django\contrib\auth\mixins.py" in dispatch
  52.         return super().dispatch(request, *args, **kwargs)

File "C:\Users\MaineKomputere\Anaconda3\envs\MyDjangoEnv\lib\site-packages\django\views\generic\base.py" in dispatch
  97.         return handler(request, *args, **kwargs)

File "C:\Users\MaineKomputere\Anaconda3\envs\MyDjangoEnv\lib\site-packages\django\views\generic\edit.py" in post
  172.         return super().post(request, *args, **kwargs)

File "C:\Users\MaineKomputere\Anaconda3\envs\MyDjangoEnv\lib\site-packages\django\views\generic\edit.py" in post
  142.             return self.form_valid(form)

File "H:\conda\INZ\pollapp\views.py" in form_valid
  72.         poll.author = self.request.user

Exception Type: AttributeError at /polls/createPoll/
Exception Value: 'NoneType' object has no attribute 'author'

Here is the rest of my code:

models.py

User = auth.get_user_model()

class Question(models.Model):
    question_text = models.CharField(max_length=200)
    author = models.ForeignKey(User, on_delete=models.CASCADE, null=True)


    def __str__(self):
        return self.question_text

class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)
    def __str__(self):
        return self.choice_text

class User(auth.models.User, auth.models.PermissionsMixin):

    def __str__(self):
        return "@{}".format(self.username)

views.py

class CreatePoll(LoginRequiredMixin, generic.CreateView):
    form_class = forms.CreateChoiceForm
    template_name = 'polls/createPoll.html'
    success_url = reverse_lazy('pollapp:index')

    def form_valid(self, form):
        poll = form.save(commit=False)
        poll.author = self.request.user
        poll.save()
        return super().form_valid(form)

    def get_form(self, form_class=None):
        form = super().get_form(form_class)
        form.request = self.request
        return form

    def get_success_url(self):
        return reverse('pollapp:myPolls', kwargs={'pk': self.object.pk})
marc_s
  • 675,133
  • 158
  • 1,253
  • 1,388
NoName
  • 31
  • 4
  • Does this answer your question? https://stackoverflow.com/questions/1395807/proper-way-to-handle-multiple-forms-on-one-page-in-django –  Mar 06 '20 at 23:21
  • I don't think that's it. Everything works fine when i try to submit it without user. But when i try to allign user to question that's when i have that problem. I probably messed up with save() method, but i'm not sure why. – NoName Mar 07 '20 at 20:31

1 Answers1

0

Ok i found out where was the problem. The problem was that i wrote my own implementation of save() that ignored commit=false argument. Here is the working code for someone from google ;P views.py

class CreatePoll(LoginRequiredMixin, generic.CreateView):
form_class = forms.CreateChoiceForm
template_name = 'polls/createPoll.html'
success_url = reverse_lazy('pollapp:index')

def get_form_kwargs(self):
    kwargs = super(CreatePoll, self).get_form_kwargs()
    kwargs.update({'request': self.request})
    return kwargs

def get_form(self, form_class=None):
    form = super().get_form(form_class)
    form.request = self.request
    return form

def get_success_url(self):
    # return reverse('pollapp:myPolls', kwargs={'pk': self.object.pk})
    return reverse('pollapp:index')

forms.py

class CreateChoiceForm(forms.ModelForm):

    choice_0 = forms.CharField(required=True)
    choice_1 = forms.CharField(required=True)

    class Meta:
        model = Question
        fields = ['question_text',]

    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop('request')
        super(CreateChoiceForm, self).__init__(*args, **kwargs)

        choice = Choice.objects.filter(
            question=self.instance
        )
        for i in range(len(choice) + 1):
            field_name = 'choice_%s' % (i,)
            self.fields[field_name] = forms.CharField(required=False)
            try:
                self.initial[field_name] = choice[i].choice
            except IndexError:
                self.initial[field_name] = ""
            field_name = 'choice_%s' % (i+1,)
            self.fields[field_name] = forms.CharField(required=False)

    def save(self, commit=True):
        question = self.instance
        question.question_text = self.cleaned_data['question_text']
        question.author = self.request.user
        question.choice_set.all().delete
        question.save()
        for i in range(2):
            choice = self.cleaned_data['choice_%i' % (i)]
            Choice.objects.create(question=question, choice_text=choice)

    def get_interest_fields(self):
        for field_name in self.fields:
            if field_name.startswith('choice_'):
                yield self[field_name]
NoName
  • 31
  • 4