简体   繁体   中英

Not able to access related model data using foreign key in Django

models.py

class products(models.Model):
    name = models.CharField(max_length=100)
    sku = models.CharField(max_length=50)
    vendor = models.CharField(max_length=50)
    brand = models.CharField(max_length=50)
    price = models.FloatField()
    product_status = models.BooleanField()
    quantity = models.IntegerField()

    def __str__(self):
        return self.name


# categories
class categories(models.Model):
    category_name = models.CharField(max_length=50)
    parent_id = models.IntegerField()


# product categories
class product_categories(models.Model):
    product = models.ForeignKey(products, on_delete=models.CASCADE)
    category = models.ForeignKey(categories, on_delete=models.CASCADE)

    def __str__(self):
        return self.category
  1. I can access 'category' table data(inside django shell) using
data = products.objects.all()
data.values('product_categories__category__category_name')
output: <QuerySet [{'product_categories__category__category_name': 'xxxx'}}]>
  1. If I put this(inside django shell)
data.product_categories.category
output: 'QuerySet' object has no attribute 'product_categories'

How do I get a queryset(can be passed to html) which includes data from "categories" table along with the data of "products" table

There are a couple of issues happening here. First, data is a queryset, which is kind of like a list of objects, even though here there's just one object in the list. What you want is to get an attribute off of the item in the list, so you need something like a data.first() to get to that object before you start dotting into its attributes.

Secondly, the way Django handles reverse FK relationships requires that you refer to the FK by the standard name of, in your case, product_categories_set , OR you set your own related_name attribute on the FK. Something like:

# product categories
class product_categories(models.Model):
    product = models.ForeignKey(products, on_delete=models.CASCADE, related_name='product_categories')
    category = models.ForeignKey(categories, on_delete=models.CASCADE, related_name='product_categories')

    def __str__(self):
        return self.category

so that you can refer to your product_categories model from both the product and categories using just data.product_categories .

Thirdly, when accessing a reverse FK relationship, just like in point (1) above, you will get a related manager, from which you can get a queryset of items. Thus, to get the category name, you need to indicate which item you want the category name for. Assuming it's just the first item for everything, it would look something like:

data = products.objects.all()
product_category = data.product_categories.all()
category_name = product_category.category.category_name

Of course once you have more data, you'll not always want to just pick the first item, so you'll need to add filtering logic into the query to make sure you get the item you're looking for.

ETA, I do agree with the comment by Jorge above - a MTM would make this a bit simpler and would, in essence, create your product_categories table for you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM