# Object level permissions with relations

**URL:** <https://forum.djangoproject.com/t/object-level-permissions-with-relations/21204>\
**Category:** Getting Started\
**Created:** [May 27, 2023, 11:16am UTC](https://forum.djangoproject.com/t/object-level-permissions-with-relations/21204 "2023-05-27T11:16:11Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![ogreyard](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/ogreyard/32/13914_2.png) [@ogreyard](https://forum.djangoproject.com/u/ogreyard)\
**Post date:** [May 27, 2023, 11:16am UTC](https://forum.djangoproject.com/t/object-level-permissions-with-relations/21204/1 "2023-05-27T11:16:11Z")

</div>

Imagine I have an app with following models:

Project

- owner
- field\_proj\_a
- field\_proj\_b

Dataset

- usecase (ForeignKey)
- derived\_owner (a calculated property, reflecting the owner field of the Project, readonly)
- field\_data\_a
- field\_data\_b

and the regular django “User”.

Of course the example above is minimal. I got a few more models, with a range of different relations to other fields, where the hierarchy is derived from the Project “downwards”. Hope that makes sense.

I’ve read through the usual sources in the net. What I thought of so far was:

- Creating the owner from the logged-in user on Project creation (in perform\_create of Project view)
- Filtering Querysets to owner of respective model (therefore adding the calculated property “derived\_owner”, based on Project ownership)
- Setting an “IsOwner” permission as standard additionally to “IsAuthenticated”, checking the “derived\_owner” or “owner” of the respective model.

Now when a user creates a Dataset, the user chooses the project it is referring to. How do I make sure the objects referred to via ForeignKey (and other relational field types) are checked for having the logged-in user as the owner (of the referred Project) in a POST/WRITE (to Dataset) request?  
With the setup described above, a non-friendly user could still “attach” his new Dataset to a project he does not have access to (e.g. by guessing the FK). How do I mitigate this?

---

<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:** [May 27, 2023, 11:46am UTC](https://forum.djangoproject.com/t/object-level-permissions-with-relations/21204/2 "2023-05-27T11:46:58Z")

</div>

> [@ogreyard](#):
>
> How do I make sure the objects referred to via ForeignKey (and other relational field types) are checked for having the logged-in user as the owner (of the referred Project) in a POST/WRITE (to Dataset) request?

The easiest way to do _that_ is to either leverage the `clean` function within your forms, or set the `queryset` attribute for the ChoiceField being used.

(And yes, a comprehensive object-level permissions system can get incredibly intricate.)

---

<div class="post-metadata">

**Author:** ![ogreyard](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/ogreyard/32/13914_2.png) [@ogreyard](https://forum.djangoproject.com/u/ogreyard)\
**Post date:** [May 27, 2023, 1:20pm UTC](https://forum.djangoproject.com/t/object-level-permissions-with-relations/21204/3 "2023-05-27T13:20:19Z")

</div>

Thanks for the prompt reply, Ken.

I forgot to mention I am using DRF. Does your proposed solution work with DRF as well?

---

<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:** [May 27, 2023, 2:03pm UTC](https://forum.djangoproject.com/t/object-level-permissions-with-relations/21204/4 "2023-05-27T14:03:38Z")

</div>

Absolutely.

Physically, a “Form”, is a Python object in the server. _One_ of its functions is its ability to create an HTML form - but that HTML is _not_ the “Form”.

Another function is to bind data to the form fields. Yes, in the typical / common case, that data comes from an HTML form post submission. (e.g. `my_form = MyForm(request.POST)`)

If you look at [`request.POST`](https://docs.djangoproject.com/en/4.2/ref/request-response/#django.http.HttpRequest.POST), you’ll see it’s represented internally as a [“dict-like” object.](https://docs.djangoproject.com/en/4.2/ref/request-response/#querydict-objects)

So what this means is that you can bind any dict to a form. See the examples at [The Forms API | Django documentation | Django](https://docs.djangoproject.com/en/4.2/ref/forms/api/)

---

<div class="post-metadata">

**Author:** ![ogreyard](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/ogreyard/32/13914_2.png) [@ogreyard](https://forum.djangoproject.com/u/ogreyard)\
**Post date:** [June 4, 2023, 3:22pm UTC](https://forum.djangoproject.com/t/object-level-permissions-with-relations/21204/5 "2023-06-04T15:22:17Z")

</div>

Thanks for the continued support, Ken.  
I have been looking at the docs a bit deeper.  
While the approach via `Form` appears to be viable, I found the Django Rest Framework [Validator](https://www.django-rest-framework.org/api-guide/validators/) features quite helpful for my use case, so I use that in combination with a custom [FilterBackend](https://www.django-rest-framework.org/api-guide/filtering/) and a default permission.

Thanks again, since your very prompt reply led me in the right direction.
