78

I have quite a simple problem to solve. I have Partner model which has >= 0 Users associated with it:

class Partner(models.Model):
    name = models.CharField(db_index=True, max_length=255)
    slug = models.SlugField(db_index=True)
    user = models.ManyToManyField(User)

Now, if I have a User object and I have a Partner object, what is the most Pythonic way of checking if the User is associated with a Partner? I basically want a statement which returns True if the User is associated to the Partner.

I have tried:

users = Partner.objects.values_list('user', flat=True).filter(slug=requested_slug)
if request.user.pk in users:
    # do some private stuff

This works but I have a feeling there is a better way. Additionally, would this be easy to roll into a decorator, baring in mind I need both a named parameter (slug) and a request object (user).

halfer
  • 19,824
  • 17
  • 99
  • 186
Darwin Tech
  • 18,449
  • 38
  • 112
  • 187

2 Answers2

108
if user.partner_set.filter(slug=requested_slug).exists():
     # do some private stuff
Peter DeGlopper
  • 36,326
  • 7
  • 90
  • 83
  • Awesome. I knew there was some less verbose way. Thank you. – Darwin Tech May 23 '13 at 20:20
  • How to raise http403 in else? Return HttpResponseForbidden throws error – pythad May 27 '15 at 22:20
  • I'm guessing, since I can't see your full context, but it looks like you're trying to return the class. Instead, you have to instantiate it: `return HttpResponseForbidden()`. – Peter DeGlopper May 27 '15 at 22:23
  • where is the filtering by a specific partner here? – Alex78191 Oct 29 '19 at 02:40
  • @Alex78191 - the OP's example has the desired partner identified by the `slug` attribute. If instead you have EG the partner's ID, `user.partner_set.filter(id=requested_id).exists()` works too. The point is that you can `filter` the user's `partner_set` manager as needed, then use `exists()`. – Peter DeGlopper Oct 29 '19 at 02:43
  • what is `partner_set`? – Alex78191 Oct 29 '19 at 02:55
  • 1
    @Alex78191 - it's the auto-created reverse relationship accessor. Because `Partner` has a relationship to `User`, `User` instances have an accessor attribute `partner_set`. See the docs for details: https://docs.djangoproject.com/en/2.2/topics/db/queries/#related-objects – Peter DeGlopper Oct 29 '19 at 14:40
  • What happens to reverse accessor if several relationships with one class are defined? – Alex78191 Oct 29 '19 at 14:58
  • You have to define a `related_name` attribute in the relationship field to disambiguate in that case. See for instance this answer: https://stackoverflow.com/questions/543377/how-can-i-have-two-foreign-keys-to-the-same-model-in-django/543406 – Peter DeGlopper Oct 29 '19 at 15:02
7

If we just need to know whether a user object is associated to a partner object, we could just do the following (as in this answer):

if user in partner.user.all():
    #do something
Anupam
  • 14,950
  • 19
  • 67
  • 94