# Linked linked to Profile model

**URL:** <https://forum.djangoproject.com/t/linked-linked-to-profile-model/11750>\
**Category:** Using Django\
**Created:** [January 23, 2022, 5:25pm UTC](https://forum.djangoproject.com/t/linked-linked-to-profile-model/11750 "2022-01-23T17:25:45Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![TommyQuality](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/tommyquality/32/6302_2.png) [@TommyQuality](https://forum.djangoproject.com/u/TommyQuality)\
**Post date:** [January 23, 2022, 5:25pm UTC](https://forum.djangoproject.com/t/linked-linked-to-profile-model/11750/1 "2022-01-23T17:25:46Z")

</div>

Hi,

I am trying to work with different user profiles where the user can link products to there profile to display on a dashboard.

I have created 3 models:

```auto
class Product(models.Model):

    product_name = models.CharField(max_length=50, blank=False, unique=True)
    product_slug = models.CharField(max_length=50, blank=True,null=True)
    product_symbol = models.CharField(max_length=50, blank=True,null=True)
    product_price = models.FloatField(blank=True,null=True)

    def __str__ (self):
        return str(self.product_name)

```

```auto
class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    bio = models.TextField(max_length=500, blank=True)
    location = models.CharField(max_length=30, blank=True)
    birth_date = models.DateField(null=True, blank=True)
    product_list = models.ManyToManyField(Product, blank=True)
    website = models.URLField(max_length=50, blank=True)
    twitter = models.CharField(max_length=50, blank=True)
    meta = models.CharField(max_length=50, blank=True)

    def __str__ (self):
        return str(self.user

```

```auto
class Holding(models.Model):

    product_name = models.ForeignKey(Product, on_delete=models.CASCADE)
    profile = models.ForeignKey(Profile, on_delete=models.CASCADE)
    product_price = models.FloatField(max_length=50, blank=True, null=True)

    def __str__ (self):
        return str(self.product_name)

```

I’ve manually added a product to the user profile which works, but im trying to show the product price that the user paid from the `holding` model

`holdings = Holding.objects.get(profile_id=profile.id)`

```auto
    profile = Profile.objects.get(user = request.user)
    products = profile.product_list.all()

```

Is this apprach with the models the correct way? How do i retrieve the `holding` data?

Thanks

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [January 23, 2022, 6:35pm UTC](https://forum.djangoproject.com/t/linked-linked-to-profile-model/11750/2 "2022-01-23T18:35:27Z")

</div>

If you look carefully, `Holding` is actually the `through` table of a ManyToMany relationship.

You may find some operations easier to visualize and code if you construct your models to take advantage of that.

---

<div class="post-metadata">

**Author:** ![TommyQuality](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/tommyquality/32/6302_2.png) [@TommyQuality](https://forum.djangoproject.com/u/TommyQuality)\
**Post date:** [January 23, 2022, 6:44pm UTC](https://forum.djangoproject.com/t/linked-linked-to-profile-model/11750/3 "2022-01-23T18:44:20Z")

</div>

Thanks Ken.

I know we’ve been through this before, but im not sure how to work this as a through table. Would that be changing the FK?

Thanks

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [January 23, 2022, 6:46pm UTC](https://forum.djangoproject.com/t/linked-linked-to-profile-model/11750/4 "2022-01-23T18:46:01Z")

</div>

Nope. Absolutely nothing changes within the `Holding` table - it’s perfectly fine as written. All you’re doing is adding a ManyToMany field on one of the other two tables identifying `Holding` as the `through` table.

---

<div class="post-metadata">

**Author:** ![TommyQuality](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/tommyquality/32/6302_2.png) [@TommyQuality](https://forum.djangoproject.com/u/TommyQuality)\
**Post date:** [January 23, 2022, 6:54pm UTC](https://forum.djangoproject.com/t/linked-linked-to-profile-model/11750/5 "2022-01-23T18:54:12Z")

</div>

Ok, so adding `manytomany` from `Profile` using something like `product_price`  
`product_price = models.ManyToManyField(Product, blank=True)`?

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [January 23, 2022, 6:59pm UTC](https://forum.djangoproject.com/t/linked-linked-to-profile-model/11750/6 "2022-01-23T18:59:09Z")

</div>

Close. You forgot to add the [`through`](https://docs.djangoproject.com/en/4.0/topics/db/models/#extra-fields-on-many-to-many-relationships) attribute.

---

<div class="post-metadata">

**Author:** ![TommyQuality](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/tommyquality/32/6302_2.png) [@TommyQuality](https://forum.djangoproject.com/u/TommyQuality)\
**Post date:** [January 23, 2022, 7:04pm UTC](https://forum.djangoproject.com/t/linked-linked-to-profile-model/11750/7 "2022-01-23T19:04:31Z")

</div>

members = models.ManyToManyField(Person, through=‘Membership’)  
`Profile`  
`product_price = models.ManyToManyField(product_price, through=Holding)` ?

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [January 23, 2022, 7:15pm UTC](https://forum.djangoproject.com/t/linked-linked-to-profile-model/11750/8 "2022-01-23T19:15:11Z")

</div>

I don’t know what this line is about:

> [@TommyQuality](#):
>
> members = models.ManyToManyField(Person, through=‘Membership’)

But in `Profile`, you already have:

> [@TommyQuality](#):
>
> `product_list = models.ManyToManyField(Product, blank=True)`

This already defines the ManyToMany between `Profile` and `Product`.  
All you need to do is add the `through` attribute to this.

---

<div class="post-metadata">

**Author:** ![TommyQuality](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/tommyquality/32/6302_2.png) [@TommyQuality](https://forum.djangoproject.com/u/TommyQuality)\
**Post date:** [January 23, 2022, 7:18pm UTC](https://forum.djangoproject.com/t/linked-linked-to-profile-model/11750/9 "2022-01-23T19:18:31Z")

</div>

Sorry Ken, this `members = models.ManyToManyField(Person, through=‘Membership’)` was from the Django page, i pasted by mistake.

> [@TommyQuality](#):
>
> product\_list = models.ManyToManyField(Product, blank=True)

I see.  
Thanks, Ken.

Tom.

---

<div class="post-metadata">

**Author:** ![TommyQuality](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/tommyquality/32/6302_2.png) [@TommyQuality](https://forum.djangoproject.com/u/TommyQuality)\
**Post date:** [January 23, 2022, 7:27pm UTC](https://forum.djangoproject.com/t/linked-linked-to-profile-model/11750/10 "2022-01-23T19:27:45Z")

</div>

It throws this error

```auto
Cannot alter field app.Profile.product_list into app.Profile.product_list - they are not compatible types (you cannot alter to or from M2M fields, or add or remove through= on M2M fields)

```

Have i misunderstood - should i be creating a new field in Profile called `product_price`  
`product_price ... (Product, blank=True, through="Holding")`

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [January 23, 2022, 7:40pm UTC](https://forum.djangoproject.com/t/linked-linked-to-profile-model/11750/11 "2022-01-23T19:40:21Z")

</div>

No, it’s just saying that you can’t migrate from one form to the other. This needs to be done with a clean slate.

You _can_ do it by adding the new field, copying the data from the old table to the new, and then removing the old field. You just can’t switch from “non-through” to “through” by a simple `makemigrations` / `migrate`.

---

<div class="post-metadata">

**Author:** ![TommyQuality](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/tommyquality/32/6302_2.png) [@TommyQuality](https://forum.djangoproject.com/u/TommyQuality)\
**Post date:** [January 23, 2022, 8:15pm UTC](https://forum.djangoproject.com/t/linked-linked-to-profile-model/11750/12 "2022-01-23T20:15:08Z")

</div>

Thanks for your help as always Ken.

Tom

---

<div class="post-metadata">

**Author:** ![TommyQuality](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/tommyquality/32/6302_2.png) [@TommyQuality](https://forum.djangoproject.com/u/TommyQuality)\
**Post date:** [January 23, 2022, 8:29pm UTC](https://forum.djangoproject.com/t/linked-linked-to-profile-model/11750/13 "2022-01-23T20:29:35Z")

</div>

Sorry Ken, how do i retrieve values in `Holdings` via the `through`?

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [January 23, 2022, 8:31pm UTC](https://forum.djangoproject.com/t/linked-linked-to-profile-model/11750/14 "2022-01-23T20:31:41Z")

</div>

What are you starting from?

In other words, what object do you have from which you want to retrieve those values in `Holdings`?

---

<div class="post-metadata">

**Author:** ![TommyQuality](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/tommyquality/32/6302_2.png) [@TommyQuality](https://forum.djangoproject.com/u/TommyQuality)\
**Post date:** [January 23, 2022, 8:36pm UTC](https://forum.djangoproject.com/t/linked-linked-to-profile-model/11750/15 "2022-01-23T20:36:51Z")

</div>

This is my view that i am building out

```auto
@login_required
def index(request):
    profile = Profile.objects.get(user = request.user)
    products = profile.product.all()
    holdings = profile.products # Want to get price from Holding for this profile.
    return render(request, 'index.html',{'products':products})

```

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [January 23, 2022, 9:02pm UTC](https://forum.djangoproject.com/t/linked-linked-to-profile-model/11750/16 "2022-01-23T21:02:05Z")

</div>

Ok, you’re starting out from a `Profile` (`profile`)

So, the `Products` associated with _that_ profile would be `profile.product_list.all()`. Likewise, the set of `Holdings` associated with that profile would be `profile.holdings_set.all()`.

Now, if you want data from both Holdings and Products, you can retrieve the set of Holdings, and then use the `product_name` field for each Holdings to get the related Product.

Or, you can query for the `holdings_set`, and then annotate the result set with values from the related Product.

---

<div class="post-metadata">

**Author:** ![TommyQuality](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/tommyquality/32/6302_2.png) [@TommyQuality](https://forum.djangoproject.com/u/TommyQuality)\
**Post date:** [January 23, 2022, 9:31pm UTC](https://forum.djangoproject.com/t/linked-linked-to-profile-model/11750/17 "2022-01-23T21:31:08Z")

</div>

> [@KenWhitesell](#):
>
> Now, if you want data from both Holdings and Products, you can retrieve the set of Holdings, and then use the `product_name` field for each Holdings to get the related Product.

I like to list out on the dashboard the product and the price. So i think this is the way to go.

so i have `products = profile.product_list.all()` and `holdings = profile.holdings_set.all()`

but im not sure im following where to use `product_name`? and then within my template i would do

```auto
{% for item in holdings %}
{{item.product_name}} {{item.product_price}}
...

```

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [January 23, 2022, 9:40pm UTC](https://forum.djangoproject.com/t/linked-linked-to-profile-model/11750/18 "2022-01-23T21:40:12Z")

</div>

> [@TommyQuality](#):
>
> `products = profile.product_list.all()` and `holdings = profile.holdings_set.all()`

The problem with doing _this_ is that there’s no correlation between the extra fields in `holdings` and the data in `products.

You _only_ want `holdings = profile.holdings_set.all()` so that when you iterate over `holdings` using:

> [@TommyQuality](#):
>
> `{% for item in holdings %}`

you can access the related field using the `product_name` field in the `item` instance.

Just don’t lose sight of the fact that you’ve got a poor name for the references to `Products` within `Holdings`. The `product_name` field in `Holdings` is **not** the name of the product, it’s the FK reference to the `Products` object.

---

<div class="post-metadata">

**Author:** ![TommyQuality](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/tommyquality/32/6302_2.png) [@TommyQuality](https://forum.djangoproject.com/u/TommyQuality)\
**Post date:** [January 23, 2022, 10:13pm UTC](https://forum.djangoproject.com/t/linked-linked-to-profile-model/11750/19 "2022-01-23T22:13:16Z")

</div>

Thanks Ken. Works perfectly 🙂

> [@KenWhitesell](#):
>
> Just don’t lose sight of the fact that you’ve got a poor name for the references to `Products` within `Holdings` . The `product_name` field in `Holdings` is **not** the name of the product, it’s the FK reference to the `Products` object.

On that. What would be a more appropriate name?

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [January 23, 2022, 10:54pm UTC](https://forum.djangoproject.com/t/linked-linked-to-profile-model/11750/20 "2022-01-23T22:54:26Z")

</div>

`product` perhaps?  
That way, given a `holding` object, the name would be `holding.product.product_name`.

[Next page](https://forum.djangoproject.com/t/linked-linked-to-profile-model/11750.md?page=2)
