How to get Prefetch 'to_attr' directly without going through loop

I am working with filters and really like to idea to use and build filter using Prefetch ‘to_attr’ however I am having small issue accessing attribute name directly. So whatever ‘to_attr’ name I am setting for filter I wanted to access it directly without going through full loop.

I might not be using this correctly and there is way around to make it work, but I am wondering if someone guide me and put me into right direction. Here is my code with data model:

class Colour(models.Model):
    colour_id = models.AutoField(primary_key=True)
    title = models.CharField(max_length=10, null=True, blank=True)
    description = models.CharField(max_length=100, null=True, blank=True)

class Product(models.Model):
    product_id = models.AutoField(primary_key=True)
    sku = models.CharField(max_length=15, null=True, blank=True)
    title = models.CharField(max_length=50, null=True, blank=True)
    sub_title = models.CharField(max_length=50, null=True, blank=True)
    short_desc = models.CharField(max_length=250, null=True, blank=True)
    colour = models.ForeignKey(Colour, on_delete=models.CASCADE,
                             related_name='wkweb.Colour+')

class ProductVariant(models.Model):
    variant_id = models.AutoField(primary_key=True)
    product_id = models.ForeignKey(Product, on_delete=models.CASCADE,
                      related_name='wkweb.Product+')
    sku = models.CharField(max_length=15, null=True, blank=True)
    unit_price = models.DecimalField(max_digits=6, decimal_places=3, null=True, blank=True)
    price = models.DecimalField(max_digits=6, decimal_places=3, null=True, blank=True)
    qty = models.IntegerField(null=True, blank=True)

    product_list = ProductVariant.objects.prefetch_related("product_id")
    filter_colour = product_list.filter(Q(product_id__colour=3) | Q(product_id__colour=2))
    filter_set = ProductVariant.objects.prefetch_related( \
                    Prefetch("product_id", queryset=filter_colour, to_attr="colour"),

The filter_set return all the products along with matched colour filtered products when I run following python loop:

    for co in filter_set:
        if getattr(co, 'colour'):
            print(co.colour.price) ### I WANT THIS WITHOUT RUNNING FULL LOOP
        print(co.colour)

I really want to access ‘colour’ attribute without running full loop of filter_set.

Thank you for your help in advance.

Welcome @MunawarAlam !

Side Note: When posting code here, enclose the code between lines of three
backtick - ` characters. This means you’ll have a line of ```, then your code,
then another line of ```. This forces the forum software to keep your code
properly formatted. (I have taken the liberty of correcting your original posts.
Please remember to do this in the future.)

You posted:

It’s really a bad idea to use an _id suffix on your field names for foreign keys. When using the field within the ORM, the foreign key field is a reference to an object, not the foreign key value itself. To access the actual foreign key value, you would be accessing an attribute named product_id_id.

You posted:

If this is an accurate representation of what’s in your model, this is incorrect code. You cannot execute queries at the class level like this. It will generate invalid results. Queries need to be evaluated within functions.

These queries also don’t make sense given your model structure.
For example:

product_id is a field within ProductVariant. This means that the appropriate helper function would be select_related, not prefetch_related.

Likewise, since it is a foreign key, it’s only relating to one instance of Product. This means that for any instance of ProductVariant, e.g. product_variant, you would have direct access to the related Product as product_variant.product_id. There is no need to execute a query of any sort on this model for this relationship.

Thank you for your response.

Sorry to putting the code here without speech mark ‘’', this is my first time posting here, so I will remember to put these speech in the future for codes.

I will refactor these code and post it here again, currently I am using one instance of Product but I was building various filters options. So if I want to filter the colour(s) from Product I should get all the fields from Product and ProductVariant based on filters choices. Maybe I am over doing this, as I am thinking traditional SQL query which required to join and filter the result.

That’s a possibility. There’s a lot of this type of work that the ORM will do for you automatically. For the most part, the ORM knows what relationships exists between models and will generally do the right thing.