4

I'm currently learning python/django As a Tutorial for myself I have done that:

  • create user --> ok
  • login user created --> ok
  • create a new model called 'Article' with title and content as a properties --> ok
  • create several 'Article' instances --> ok
  • I display all the articles at the root of the webapp -->
  • Last step is: in order to manipulate permission, only display some article depending on which user is logged with permissions. like if user A: then display only the article with odd ids (that doesn't make any sence but it's for learning)

It seems to be very complicated to do 'permission by instance' by hand right ?

Cheers

BenNG
  • 531
  • 1
  • 4
  • 12
  • Not that complicated, you just need to check whether the current login user has the permission to access that particular view. `user.has_perm('myapp.can_view_odd_ids')`. For your own tutorial, I will share you the [reference](https://docs.djangoproject.com/en/1.8/topics/auth/default/#topic-authorization), without answer, so you can try it yourself. Don't forget to create the permission instance, (can use shell or as data migration)... Let me know if you want to see how I do it (of course after u tried), then I will create it as a new answer. **All the best for your tutorial. Good Luck :)** – Yeo May 10 '15 at 21:42
  • great ! I will work on it and let you know :) cheers – BenNG May 11 '15 at 09:18
  • hi again I have planned to do these steps: * create 2 permissions can_view_odd_ids and can_view_even_ids * save the new permissions in the DB (do I have to create a new Model ?) * create new attribute 'permission' on the User * set permissions randomly on the user instances * in the view check if the user has the permission with user.has(myapp.can_view_odd_ids) and give him the good list. what do you think ?does that make sence ? – BenNG May 11 '15 at 15:29
  • if you're using `django.controb.auth`, you don't need to create a new model, just use the [`auth.Permission`](https://github.com/django/django/blob/1.8/django/contrib/auth/models.py#L40-L84) as the model. No need to add an attribute to the `User`, the default `auth.User` already has [inherit](https://github.com/django/django/blob/1.8/django/contrib/auth/models.py#L378-L381) from [`PermissionMixin`](https://github.com/django/django/blob/1.8/django/contrib/auth/models.py#L303-L307). You can assign permission of different user according to how you want it to be, (randomly sounds weird, but ok,..) – Yeo May 11 '15 at 17:31
  • ok great ! randomly lol I mean whatever the user I just need to two of them and each has different permission ! thanks ! – BenNG May 11 '15 at 18:08
  • I did not know where to put the code Permission creation. I have the feeling I cheat a bit by using the shell. Is there a better way to proceed ? a better place to put the code related to Permission bacause the problem is we have to execute that only once. could you show the migrations variation please and other things if you want to . thanks a lot :) https://gist.github.com/BenNG/12f17c4f0f280f192e2d – BenNG May 14 '15 at 09:23
  • Apologize for what I said earlier. Apparently Django has plan this very well. [**See this document**](https://docs.djangoproject.com/en/1.8/topics/auth/customizing/#custom-permissions). In short, we neither have to create the permission object manually nor writing the migration script manually. Instead we just have to specify the [`Model.Meta.permissions`](https://docs.djangoproject.com/en/1.8/ref/models/options/#django.db.models.Options.permissions) and Django will automatically create the object when you do the normal migration flow (`makemigrations` and `migrate`). Good Lucks!! :D – Yeo May 14 '15 at 15:52

2 Answers2

9

First we have to create our 2 permissions

from django.db import models

class Article(models.Model):
    title = models.TextField()
    content = models.TextField()

    class Meta:
        permissions = (
            ('can_view_odd_ids', 'can_view_odd_ids'),
            ('can_view_even_ids', 'can_view_even_ids'),
        )

    def __str__(self):
        return self.title

after running the migration, we can manually apply the permission to our users using the shell

odd_even = Permission.objects.get(name='can_view_even_ids')
user_yui = User.objects.get(username='yui')
user_yui.user_permissions.add(odd_even)
user_yui.save()

and then test in the view the permission on our users (something like that)

def my_view(request):
    data = {}
    if request.user.is_authenticated():
        count = Article.objects.all().count()
        if request.user.has_perm("account.can_view_odd_ids"):
            data = {'articles': Article.objects.all()[1::2]})
        elif request.user.has_perm("account.can_view_even_ids"):
            data = {'articles': Article.objects.all()[0::2]})
    return render(request, 'index.html', data)
BenNG
  • 531
  • 1
  • 4
  • 12
  • Give a more meaningful verbose such as `('can_view_odd_ids', 'Can View odd ID'),` – Yeo May 15 '15 at 18:46
  • Please take note about the changes or refactoring that I made on your answer. – Yeo May 15 '15 at 19:34
  • Also to query odd or even article, you can use the following: `Article.objects.all()[1::2]` **without the count**, or you also try [this one](http://stackoverflow.com/q/30267460/764592) :p especially using regex. – Yeo May 15 '15 at 20:08
  • 1
    thanks for all ! I think I will keep the [1::2] syntax because it's shorter :) – BenNG May 16 '15 at 12:31
  • what is the diff can_view_odd_ids' vs 'Can View odd ID ???????????????????/ –  Mar 30 '18 at 11:16
  • then code `odd_even = Permission.objects.get(name='can_view_even_ids')` gave me a object not found error. I guess the `name` has to be replaced by `codename` ?? – rammanoj Nov 18 '18 at 05:58
-2

When you say 'I need permission by instance' probably you mean 'I need to use django-guardian' https://django-guardian.readthedocs.org/en/stable/

phoenix
  • 7,988
  • 6
  • 39
  • 45
Fanis Despoudis
  • 362
  • 1
  • 7