8

I'm overriding the init method in my form andthis is now returning an error 'TransactionForm' object has no attribute '_errors'.

I would expect this to work because I've included super in my init, however perhaps I don't understand how to use this correctly. An explanation would be appreciated. What do I need to do to get form.errors working?

Full traceback

Traceback:

File "C:\Program Files\Python36\lib\site-packages\django\core\handlers\exception.py" in inner 35. response = get_response(request)

File "C:\Program Files\Python36\lib\site-packages\django\core\handlers\base.py" in _get_response 128. response = self.process_exception_by_middleware(e, request)

File "C:\Program Files\Python36\lib\site-packages\django\core\handlers\base.py" in _get_response 126. response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "C:\py\portfolio-project\myportfolio\views.py" in add_transaction 136. return render(request, 'myportfolio/add_transaction.html', {'form': form})

File "C:\Program Files\Python36\lib\site-packages\django\shortcuts.py" in render 36. content = loader.render_to_string(template_name, context, request, using=using)

File "C:\Program Files\Python36\lib\site-packages\django\template\loader.py" in render_to_string 62. return template.render(context, request)

File "C:\Program Files\Python36\lib\site-packages\django\template\backends\django.py" in render 61. return self.template.render(context)

File "C:\Program Files\Python36\lib\site-packages\django\template\base.py" in render 175. return self._render(context)

File "C:\Program Files\Python36\lib\site-packages\django\template\base.py" in _render 167. return self.nodelist.render(context)

File "C:\Program Files\Python36\lib\site-packages\django\template\base.py" in render 943. bit = node.render_annotated(context)

File "C:\Program Files\Python36\lib\site-packages\django\template\base.py" in render_annotated 910. return self.render(context)

File "C:\Program Files\Python36\lib\site-packages\django\template\loader_tags.py" in render 155. return compiled_parent._render(context)

File "C:\Program Files\Python36\lib\site-packages\django\template\base.py" in _render 167. return self.nodelist.render(context)

File "C:\Program Files\Python36\lib\site-packages\django\template\base.py" in render 943. bit = node.render_annotated(context)

File "C:\Program Files\Python36\lib\site-packages\django\template\base.py" in render_annotated 910. return self.render(context)

File "C:\Program Files\Python36\lib\site-packages\django\template\loader_tags.py" in render 155. return compiled_parent._render(context)

File "C:\Program Files\Python36\lib\site-packages\django\template\base.py" in _render 167. return self.nodelist.render(context)

File "C:\Program Files\Python36\lib\site-packages\django\template\base.py" in render 943. bit = node.render_annotated(context)

File "C:\Program Files\Python36\lib\site-packages\django\template\base.py" in render_annotated 910. return self.render(context)

File "C:\Program Files\Python36\lib\site-packages\django\template\loader_tags.py" in render 67. result = block.nodelist.render(context)

File "C:\Program Files\Python36\lib\site-packages\django\template\base.py" in render 943. bit = node.render_annotated(context)

File "C:\Program Files\Python36\lib\site-packages\django\template\base.py" in render_annotated 910. return self.render(context)

File "C:\Program Files\Python36\lib\site-packages\django\template\base.py" in render 999. return render_value_in_context(output, context)

File "C:\Program Files\Python36\lib\site-packages\django\template\base.py" in render_value_in_context 978. value = str(value)

File "C:\Program Files\Python36\lib\site-packages\django\utils\html.py" in 371. klass.str = lambda self: mark_safe(klass_str(self))

File "C:\Program Files\Python36\lib\site-packages\django\forms\forms.py" in str 136. return self.as_table()

File "C:\Program Files\Python36\lib\site-packages\django\forms\forms.py" in as_table 279. errors_on_separate_row=False)

File "C:\Program Files\Python36\lib\site-packages\django\forms\forms.py" in _html_output 196. top_errors = self.non_field_errors() # Errors that should be displayed above all fields.

File "C:\Program Files\Python36\lib\site-packages\django\forms\forms.py" in non_field_errors 305. return self.errors.get(NON_FIELD_ERRORS, self.error_class(error_class='nonfield'))

File "C:\Program Files\Python36\lib\site-packages\django\forms\forms.py" in errors 173. if self._errors is None:

Exception Type: AttributeError at /myportfolio/add_transaction/ Exception Value: 'TransactionForm' object has no attribute '_errors'

forms

class TransactionForm(forms.ModelForm):     
    CHOICES = ((1, 'Buy'), (2, 'Sell'),)

    coin = forms.ModelChoiceField(queryset = Coin.objects.all()) 
    buysell = forms.ChoiceField(choices = CHOICES)

    field_order = ['buysell', 'coin', 'amount', 'trade_price']

    class Meta:
        model = Transactions
        fields = {'buysell', 'coin', 'amount', 'trade_price'}

    def __init__(self, coin_price = None, user = None, *args, **kwargs):

        if user:
            self.user = user
            qs_coin = Portfolio.objects.filter(user = self.user).values('coin').distinct()
            super(TransactionForm, self).__init__(self.user, *args, **kwargs)
            self.fields['coin'].queryset = qs_coin

        if coin_price:
            self.coin_price = coin_price
            super(TransactionForm, self).__init__(self.user, self.coin_price, *args, **kwargs)
            self.fields['price'] = self.coin_price

Views

def add_transaction(request):
    print(request.method)
    print("test1")

    print(request.GET)

    if request.method == "GET":
        if request.is_ajax():
            print("ajax test")

            data = {
                'test': "test1"
            }

            form = TransactionForm(request.GET, user = request.user, coin_price = GetCoin("Bitcoin").price)

            return JsonResponse(data)


    form = TransactionForm()
    if request.method == "POST":
        print("test2")
        form = TransactionForm(request.POST)
        if form.is_valid():
            print("test3")
            obj = form.save(commit = False)
            obj.user = request.user
            obj.save()
            return HttpResponseRedirect('/myportfolio/')
        else: 
            print(form.errors)

    return render(request, 'myportfolio/add_transaction.html', {'form': form})

2 Answers 2

14

Form's superclass __init__ method not called if coin_price and user not provided. That's why such form's attributes as _errors was not created. You need to rewrite form's __init__ like this:

def __init__(self, coin_price = None, user = None, *args, **kwargs):
        super(TransactionForm, self).__init__(*args, **kwargs)
        if user:
            self.user = user
            qs_coin = Portfolio.objects.filter(user = self.user).values('coin').distinct()
            self.fields['coin'].queryset = qs_coin

        if coin_price:
            self.coin_price = coin_price
            self.fields['price'] = self.coin_price

To make super.__init__() called in any cases.

Sign up to request clarification or add additional context in comments.

Comments

0

I just ran into the bug, be careful when you are coding fast, the autofill of your debbuger might propose a view instead of a form due to naming similarities.

So just make sure that you are actually calling the form and not a view !!! took me half an hour to figure out ...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.