jon.s
jon.s

Reputation: 175

Django: AttributeError: "Object has no attribute"

I'm trying to get a property calculated in one class into another class. And I'm stuck...

In the class "Reward", I need to subtract "deductible" from "pledge_level". In class "Pledge", I need to subtract the "not_taxable" from "amount" to return "decuctible_total".

This works fine when accessing it in my template:

(${{ reward.deductible}} is tax deductible or ${{ reward.not_taxable }} is not tax deductible)

When run on the server, I get an internal server error: [Django] ERROR (EXTERNAL IP): Internal Server Error: /projects/fund/billing/1000

Here's the Traceback:

Internal Server Error: /projects/fund/billing/1000/
Traceback (most recent call last):
File "/var/venv/website/lib/python2.7/site-packages/django/core/handlers/base.py", line 132, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/var/sites/proj/payments/views.py", line 98, in pledge_billing
html = template.render(c)
File "/var/venv/website/lib/python2.7/site-packages/django/template/backends/django.py", line 74, in render
return self.template.render(context)
File "/var/venv/website/lib/python2.7/site-packages/django/template/base.py", line 209, in render
return self._render(context)
File "/var/venv/website/lib/python2.7/site-packages/django/template/base.py", line 201, in _render
return self.nodelist.render(context)
File "/var/venv/website/lib/python2.7/site-packages/django/template/base.py", line 903, in render
bit = self.render_node(node, context)
File "/var/venv/website/lib/python2.7/site-packages/django/template/base.py", line 917, in render_node
return node.render(context)
File "/var/venv/website/lib/python2.7/site-packages/django/template/loader_tags.py", line 135, in render
return compiled_parent._render(context)
File "/var/venv/website/lib/python2.7/site-packages/django/template/base.py", line 201, in _render
return self.nodelist.render(context)
File "/var/venv/website/lib/python2.7/site-packages/django/template/base.py", line 903, in render
bit = self.render_node(node, context)
File "/var/venv/website/lib/python2.7/site-packages/django/template/base.py", line 917, in render_node
return node.render(context)
File "/var/venv/website/lib/python2.7/site-packages/django/template/loader_tags.py", line 65, in render
result = block.nodelist.render(context)
File "/var/venv/website/lib/python2.7/site-packages/django/template/base.py", line 903, in render
bit = self.render_node(node, context)
File "/var/venv/website/lib/python2.7/site-packages/django/template/base.py", line 917, in render_node
return node.render(context)
File "/var/venv/website/lib/python2.7/site-packages/django/template/base.py", line 957, in render
output = self.filter_expression.resolve(context)
File "/var/venv/website/lib/python2.7/site-packages/django/template/base.py", line 647, in resolve
obj = self.var.resolve(context)
File "/var/venv/website/lib/python2.7/site-packages/django/template/base.py", line 787, in resolve
value = self._resolve_lookup(context)
File "/var/venv/website/lib/python2.7/site-packages/django/template/base.py", line 825, in _resolve_lookup
current = getattr(current, bit)
File "/var/sites/proj/projects/models.py", line 81, in deductible_total
return self.get_deductible_total()
File "/var/sites/proj/projects/models.py", line 77, in get_deductible_total
return (self.amount - self.not_taxable)
AttributeError: 'Pledge' object has no attribute 'not_taxable'    

models.py

class Pledge(models.Model):
    project = models.ForeignKey('Project')
    amount = models.DecimalField(decimal_places=2,max_digits=10,
        default=D('0.00'))
    reward = models.ForeignKey('Reward',blank=True,null=True,
        on_delete=models.SET_NULL)

    objects = PledgeManager()

    def get_deductible_total(self):
        return (self.amount - self.not_taxable) 

    @property
    def deductible_total(self):
        return self.get_deductible_total()


class Reward(models.Model):
    project = models.ForeignKey('Project')
    title = models.CharField(max_length=255)
    pledge_level = models.DecimalField(decimal_places=2, max_digits=10)
    deductible = models.DecimalField(decimal_places=2, max_digits=10)
    description = models.TextField(blank=True)

    def get_not_taxable(self):
        return (self.pledge_level - self.deductible)

    @property
    def not_taxable(self):
        return self.get_not_taxable()

Because I was editing the models.py file in the projects app, I did migrations on projects. Maybe the payments app also needs to have migrations run on it due to the change in projects?

Thanks so much for the effort to help!

Upvotes: 2

Views: 22666

Answers (1)

wanaryytel
wanaryytel

Reputation: 3492

Change the method like this:

def get_deductible_total(self):
    return (self.amount - self.reward.not_taxable) 

BTW usually there's really no point in separating properties and methods, you can do calculations inside the properties as well. You could just have

@property
def deductible_total(self):
    return (self.amount - self.not_taxable) 

But some reasons to have them separated:
1) Properties do not raise errors, so if you call it somewhere else where you need the exceptions, then it makes sense to separate them.
2) If for some reason you need a method (or a function, basically a callable) that returns the result, then you also need to separate them. Probably not the case and can be combatted using lambdas.
Just FYI.

Upvotes: 3

Related Questions