Difference between has_perm and has_module_perms - django

While creating a custom user model I saw these two methods:
has_perm()
has_module_perms()
Also I encountered these two methods when I tried to create Custom Permsion in django-rest-framework.
Could someone please help me understand what they are and exactly where or how can I use them?

These methods are covered in the Django docs.
has_perm checks whether the user has a specific permission, for example:
user.has_perm('polls.can_vote')
has_module_perm checks whether the user has any permissions for that app, for example:
user.has_module_perm('polls')

Related

Confusion about the django permission and group model?

For example I create permission like this:
Permission.objects.create(name='Can add',codename='can_add',content_type=1)
Now if I want to apply this permission in some view I need to use permission_required decorator like this
#permission_required('app.can_add', raise_exception=True)
def some_view(request):
...
Here I need to exactly match the permission code_name in the decorator in order to apply the permission .
But what if admin(not developer) created new permission with different codename than the codename which is used in a view? We should go manually to the code and edit the codename ? Or is there any better solutions?How can admin apply the newly created permission in the view without manually going in the code?
I am thinking it from the normal user perspective, after we gave the project to the client.How can he/she manage such things?
Note:I am not using django default admin panel
Simple answer: creating custom permissions via the admin doesn't make any sense indeed since the code won't know anything about those permissions (and the permissions don't know anything about your code either FWIW).
If your app needs custom permissions, you create them via code (ie in a migration), and deploy them together with the code that uses them. Then the admins can assign those permissions to selected users or groups as they see fit.

How does viewset aligns with rest methods

I am relatively new to DRF, but found viewsets an amazing abstraction technique for writing RESTful API. I am having a hard time correlating Viewsets with REST methods though. Let's say I have a viewset for Userprofiles and somebody new creates a profile on client.
Should this send a PUT or a POST ?
Which url should this request go to, http://user or http://user/new_id ?
If I want this profile only accessible to the user or admin(all CRUD operations), then where should I handle the code for making it inaccessible to others ?
Should I create a new permission ? If yes, should I handle rest methods in has_permission/has_object_permission ?
I have gone through the tutorial, and know how permissions/mixins works, but I am not able to connect these dots here.
1/ In general, POST is for creating new, PUT is for updating. See the docs on the SimpleRouter to show how the various types of Http methods align with various actions in your Django backend.
2/ You'll find that different situations call for different routing methods. If yours is standard, you may want to use a SimpleRouter like the example above. In that case, creating a new user would be a POST request to /user/ and updating a user would be a PUT request to /user/{{user_id}}/.
3/ To limit access to various API methods, you want to use Permissions. It's possible that you could use one of DRF's Custom Permissions. I've found that in general, if you want only the user to access his/her own profile, it's easier to either use conditional logic within a view (i.e., return a DRF PermissionDenied exception in the view logic if the request.user.pk is not the pk of that REST url. More often than not, I've used the UserPassesTestMixin from Django Braces, that works pretty well to filter user permissions.
4/ I guess the Django Braces mixin above answers this question. You should include a test_func method if you're using Django Braces that returns True if you want to grant the user access, and False otherwise.
Hope this helps! I agree that these are difficult parts of DRF and perhaps some of these could more effectively get incorporated into the source. Good luck!

exclude object from queryset in many to many relation in django

so i have a many to many relation between my own Role model and the django auth permission model, the thing is, i tried to get all permissions associated with a specific role like this role.permisos (permisos being the many to many atribute), it works ok.
Now, im looking forward to add that queryset to a form, but before that i tried to filter some permissions i don't want the user to see
i did role1.permisos.exclude(name="Can change somethings") (being role1 an instance of role) but it just dosn't work
If you're working with a template, add it to your context. If it's a class-based view, override the get_context_data method.
You can also do it overriding the get_initial_data method.

Django admin particular data for particular user

I am using django admin site to let people manage database easier.
For some reason, I want to hide some data from some user.
Let's say I have a model named Book and there are a lot of books in database. I want different user has the different scope of books he can view.
How would I do that?
I am thinking about permission. Is that possible to set the permission to filter the data?
I know how to create permission according to a specified model. However, after that, how do I suppose to use that permission? I believe I may need to override part of "changelist_view" method under BookAdmin class, right?
Any help would works.
Thanks in advance
Use the queryset method on your admin model. Something like:
class BookAdmin(admin.ModelAdmin):
def queryset(self, request):
return super(BookAdmin, self).queryset(request).filter(owner=request.user)
Obviously the filter will vary depending on your book model, but this is the general idea.

How can I show a list in admin of ALL products so I can enable and disable view to live site? [duplicate]

This question already has answers here:
Django - specify which model manager Django admin should use
(4 answers)
Closed 8 years ago.
I need to add a way to view all products entered into the site. Right now they are filtered by being enabled=True and this only shows the products enabled. I'd like to be able to list ALL products and enable and disable them in the admin. Thanks in advance!
Model:
class ProductManager(models.Manager):
"""
Filters enabled product
"""
def get_query_set(self):
return super(ProductManager, self).get_query_set().filter(is_enabled=True)
The Django docs are quite explicit on this. Especially if you're new to the world of Django, you should be wrapping yourself up in the docs like a warm blanket. Read through them if you have time (try to make time), but if you can't, just search Google with "django" and whatever the issue you have is. 99% of the time, the first result is a page from the Django documentation and contains exactly the info you need.
That said, the docs say on this issue:
If you use custom Manager objects, take note that the first Manager Django encounters (in the order in which they're defined in the model) has a special status. Django interprets the first Manager defined in a class as the "default" Manager, and several parts of Django (including dumpdata) will use that Manager exclusively for that model. As a result, it's a good idea to be careful in your choice of default manager in order to avoid a situation where overriding get_query_set() results in an inability to retrieve objects you'd like to work with. (emphasis mine)
That's exactly what you're experiencing. Look again at the first sentence of the quote above. Django uses the first manager it encounters as the "default" manager for various parts of its machinery, including the admin. So the solution is to simply add a non-filtered manager before your custom manager. The best way to do that is to simply use the standard manager that Django adds automatically if you don't provide your own.
objects = models.Manager()
product_manager = ProductManager()
Done. The admin will now list all products because it will use the first, standard manager as the default.