Reputation: 43
I'm developing my first Django project for practice, and I'm running to a problem with self-referential foreign keys.
I have an app called "units" in which there is a models.py:
from django.db import models
class Unit(models.Model):
name = models.CharField(
'Unit',
max_length=255,
blank=True
)
quantity_per = models.DecimalField(
'Quantity Per',
max_digits=10,
decimal_places=5,
default=1
)
subunit = models.ForeignKey(
'self',
blank=True,
null=True,
on_delete=models.SET_NULL,
related_name='+',
verbose_name="subunit"
)
abbreviation = models.CharField(
'Abbreviation',
max_length=255,
blank=True
)
def unit_factor(self):
return self.subunit.quantity_per * self.quantity_per
def __str__(self):
return self.name
And this is referred to in my rudimentary index template as so:
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'units/style.css' %}"/>
{% if unit_list %}
<ul>
{% for unit in unit_list %}
<li>{{ unit.name }} - {{ unit.subunit }} - {{ unit.subunit.quantity_per }} - {{ unit.unit_factor }}</li>
{% endfor %}
</ul>
{% else %}
<p>No units are available.</p>
{% endif %}
When I runserver and navigate to the "units" url, I get the following error:
'NoneType' object has no attribute 'quantity_per'
I think this has something to do with me creating the method within the same class as the self-referential foreignkey and the child instance not being completely instantiated yet? But I'm sure my lack of programming knowledge is showing. How can I perform operations like this correctly within this relationship?
UPDATE I'm marking this solved, but I wanted to add my view as per @alexandre-cox request:
from django.template import loader
from django.views import generic
from .models import Unit
class IndexView(generic.ListView):
template_name = 'units/index.html'
def get_queryset(self):
return Unit.objects.order_by('name')
Thanks for your patience in answering this!
Upvotes: 1
Views: 509
Reputation: 88569
The exception raises because of your Unit
instance does not have any child and your code tries to access child's quantity_per
attribute.
So, change unit_factor()
method as below,
def unit_factor(self):
if hasattr(self, 'subunit') and hasattr(self.subunit, 'quantity_per'):
return self.subunit.quantity_per * self.quantity_per
return 0 # Default Value
Refer the python builtin function hasattr()
Upvotes: 2