5๐
You could do this, but I would recommend against it.
You should be using the user_passes_test()
or the permission_required()
decorators on the views that implement App1
and App2
.
This would be achieved by adding something like this:
def in_group_a(user):
return user.groups.filter(name="Group A").exists()
def in_group_b(user):
return user.groups.filter(name="Group B").exists()
@user_passes_test(in_group_a)
def app1_view(request):
...
@user_passes_test(in_group_b)
def app2_view(request):
...
In order to acheive this as asked (with a single check based on the url prefix) you would have to have a single view per application, that was accessed via a url pattern like:
url(r'^app1/(?P<remaining_url>.*)$', 'app1.views.app1`)
Your view would then have to run user_passes_test()
as above, and manually parse the remaining_url
parameter to work out what to do next:
@user_passes_test(in_group_a)
def app1(request, remaining_url):
# parse remaining_url and work out what to do
But that parsing and dispatching operation is exactly what the urlconf in Django is for.
In theory, you could create another app-specific urlconf (not referenced from your main urls.py
) and manually use its API to re-dispatch remaining_url
to a set of views.
7๐
Given this answer,
Here is the code for adding all existing permissions of an app under a Group.
For exemple if you have App1 and App2, and you want to automatically create 2 groups named app1 and app2 containing permissions to the models of each app (respectively), try this :
For App1 on apps.py :
from django.apps import AppConfig
from django.db.models.signals import post_migrate
class App1Config(AppConfig):
name = 'app1'
def ready(self):
from .signals import populate_models
post_migrate.connect(populate_models, sender=self)
Create a signals.py file that contains :
def populate_models(sender, **kwargs):
from django.apps import apps
from .apps import App1Config
from django.contrib.auth.models import Group, Permission
from django.contrib.contenttypes.models import ContentType
group_app, created = Group.objects.get_or_create(name=App1Config.name)
models = apps.all_models[App1Config.name]
for model in models:
content_type = ContentType.objects.get(
app_label=App1Config.name,
model=model
)
permissions = Permission.objects.filter(content_type=content_type)
group_app.permissions.add(*permissions)
Do the same for App2
Then assign users to their groups.
For usage :
Create a file called permissions.py on each app and add :
from .apps import App1Config
def is_in_group_app1(user):
return user.groups.filter(name=App1Config.name).exists()
In views.py use :
from django.contrib.auth.decorators import login_required, user_passes_test
from .permissions import is_in_group_app1
@login_required(login_url='where_to_redirect')
@user_passes_test(is_in_group_app1)
def myview(request):
# Do your processing
For CBV :
@method_decorator(user_passes_test(is_in_group_app1), name='dispatch')
class LogListView(ListView):
""" Displays all logs saved on App1 """
model= Logger.objects.order_by('-date_created')
Create a folder named templatestag and subfolder app1 and a has_perms.py file :
from django import template
from app1.permissions import is_in_group_app1
register = template.Library()
@register.filter
def has_perms(user):
return is_in_group_app1(user)
In your template :
{% load has_perms %}
{% if request.user|has_perms %}
<li class="nav-item">
<a href="{% url 'app1:log' %}" class="nav-link">
<i class="icon-history"></i>
<span data-i18n="nav.dash.main">App1 Log</span>
</a>
</li>
{% endif %}
It took me a while to find all this process, so if it can help others :
Enjoy ๐ !
- [Django]-Django template for loop and display first X matches
- [Django]-Displaying pyqtgraph and pyqt widgets on web
- [Django]-Django User M2M relationship