I’m designing an application in Django where I have an Item model with numerous attributes for each item. I’m experiencing very poor performance in my application and I’m wondering if there are flaws in my setup that could be causing this issue. I am relatively new to Django, so any pointers would be greatly appreciated.
Currently, I have around 200 attribute models, each with optional one-to-one fields linked to an item via a foreign key as follows:
Attribute models:
class AttrBase(models.Model):
prev_value = models.CharField(max_length=250, null=True, blank=True)
edited_by = models.ForeignKey(
Account, on_delete=models.CASCADE, null=True, blank=True
)
edited_on = models.DateTimeField(null=True, blank=True)
options = None
class Meta:
abstract = True
class ID(AttrBase):
item = models.OneToOneField(Item, on_delete=models.CASCADE)
value = models.CharField(max_length=250, null=True, blank=True)
name = "ID"
tooltip = "..."
group = "..."
class Height(AttrBase):
item = models.OneToOneField(Item, on_delete=models.CASCADE)
value = models.IntegerField(null=True, blank=True)
name = "Height"
tooltip = "..."
group = "..."
...more
I am also using a generic relationship to link to all of the groups, as follows:
class AttributeGroup(models.Model):
content_type = models.ForeignKey(
ContentType,
on_delete=models.CASCADE,
limit_choices_to={"app_label": "attributes"},
)
name = models.CharField(max_length=250, null=True, blank=True)
description = models.CharField(
max_length=1000, default="TODO", null=True, blank=True
)
def __str__(self):
return str(self.content_type)
def save(self, *args, **kwargs):
self.name = self.content_type.name
super(AttributeGroup, self).save(*args, **kwargs)
This is my Item model:
class Item(models.Model):
"""
An item with related attributes.
"""
program = models.ForeignKey(Program, on_delete=models.CASCADE)
# part_number = models.CharField(max_length=25, db_index=True, unique=True)
item_number = models.CharField(max_length=50, db_index=True)
valid = models.BooleanField(default=True)
leaf = models.BooleanField(default=False)
def __str__(self):
return f"{self.program.program_code}-{self.part_number}"
def get(self):
"""
Return the item and all of its attributes.
"""
# TODO: tune this?
attributes_dict = {}
attribute_groups = self.program.attribute_groups.all()
attr_model_names = ["Name", "Type", "Identifier", "Level"]
# Iterate over each attribute type
for model_name in attr_model_names:
model = apps.get_model("attributes", model_name)
attr_instances = model.objects.filter(
part=self, part__program__attribute_groups__in=attribute_groups
)
for attr_instance in attr_instances:
attributes_dict[f"{model_name}"] = attr_instance.value
return attributes_dict
@classmethod
def load(cls, program, part_number, attribute_vals=None):
...
Loading, creating, and reading part data is extremely slow. I have tried directly indexing all attributes, since (to my understanding) that should run in O(1)
time, but CRUD operations on part data are still extremely slow.
Josh is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.