Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django ManyToMany relation QuerySet using custom intermediate table

I would like to use custom intermediate table for products and its attributes. I have the following model defined,

class Products(models.Model):
    name = models.CharField(max_length=600, blank=True)
    brand = models.CharField(max_length=300, blank=True) 
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)     

class Attributes(models.Model):
    name = models.CharField(max_length=600)
    product = models.ManyToManyField(Products, through="AttributesMapping", related_name="attributes")

class AttributesMapping(models.Model):
    attribute = models.ForeignKey(Attributes)
    product = models.ForeignKey(Products)
    value = models.TextField(blank=True)

in views Adding Products objects to context and from template trying to get the attributes by saying

{% for attribute in product.attributes.all %}{{ attribute.name }}: {{ attribute.value }} {% endfor %}

I am getting the name but the value doesn't showup. I tried inspecting sql statement getting executed.

SELECT `attributes`.`id`, `attributes`.`name` FROM `attributes` INNER JOIN `attributes_mapping` ON (`attributes`.`id` = `attributes_mapping`.`attribute_id`) WHERE `attributes_mapping`.`product_id` = 1

the value is in 'attributes_mapping' table, Select statement has a reference but not selecting that field.

Thanks in advance for any help or suggestions.

like image 683
San Avatar asked Nov 12 '22 09:11

San


1 Answers

Keep in mind that value is not defined on attribute, it's defined on the through table. In order to access it, you need to access the attributes mapping object:

for mapping in AttributesMapping.objects.get(product=product):
    print mapping.attribute.name, mapping.value 

Alternatively:

for attribute in product.attributes.all():
    mapping = attribute.attributemapping_set.get(product=product)
    print attribute.name, mapping.value

This is of course means you'll have to change the way you're doing things as these kind of function calls aren't supported from django templates. Without knowing a bit more about your setup, I can't really advise how best to do that.

like image 85
Hamms Avatar answered Nov 15 '22 06:11

Hamms