Как отказать пользователю одного вида в доступе к представлению другого пользователя через URL в django?

В моем проекте у меня есть разные типы пользователей, такие как:

User |-Client |-Employee |-Technical Manager |-Service Manager |-Production Manager

Ни один пользователь не может получить доступ к представлению другого пользователя url, Клиент не может получить доступ к профилю технического менеджера через URL /officer/profile который назначен для профиля технического менеджера.

Для того, чтобы сделать это, в моем Client class в models.pyЯ использовал этот фрагмент кода:

class Client(models.Model): class Meta: permissions = ( ('view_client', 'view_Client'), )

Затем для каждого представления я использовал декоратор, например так:@permission_required(lambda u: u.has_perm('authentication.view_client'))

Затем я вхожу в систему как технический менеджер и пытаюсь получить доступ с помощью этого URL:/client/profile

Тогда я получил ошибку function object is not iterable,

Я создавал своего пользователя в приложении под названием authentication, models,py выглядит так:

@python_2_unicode_compatible
class Profile(models.Model):
    user = models.OneToOneField(User)
    user_sex = (('MALE', 'Male'), ('FEMALE', 'Female'))
    sex = models.CharField(max_length=6, default='Male', choices=user_sex)
    address = models.CharField(max_length=250, null=True, blank=True)
    city = models.CharField(max_length=250, null=True, blank=True)
    state = models.CharField(max_length=250, null=True, blank=True)
    country = models.CharField(max_length=250, null=True, blank=True)
    phone = PhoneNumberField(blank=True)
    zip = models.IntegerField(null=True, blank=True)
    about = models.CharField(max_length=250, null=True, blank=True)
    email_confirmed = models.BooleanField(default=False)
    account_type = models.IntegerField(default=-1)

    class Meta:
        db_table = 'auth_profile'


class Employee(models.Model):
    user = models.OneToOneField(User)
    manager = models.ForeignKey('self', null=True, on_delete=models.SET_NULL)
    designation = models.CharField(max_length=6)

    class Meta:
        db_table = 'auth_employee'


class Client(models.Model):
    user = models.OneToOneField(User)
    class Meta:
        db_table = 'auth_client'


@receiver(post_save, sender=User)
def update_user_profile(sender, instance, created, **kwargs):
    if created:
        Profile.objects.create(user=instance)
    instance.profile.save()
    if instance.profile.account_type == 0:
        if not Client.objects.filter(user=instance).exists():
            Client.objects.create(user=instance)
            instance.client.save()
        else:
            instance.client.save()
    if instance.profile.account_type == 1 or instance.profile.account_type == 2 or instance.profile.account_type == 3:
        if not Employee.objects.filter(user=instance).exists():
            Employee.objects.create(user=instance)
            instance.employee.save()
        else:
            instance.employee.save()

'

Класс профиля довольно большой. Пожалуйста, игнорируйте это. Теперь я хотел, чтобы я назначал разрешение каждый раз, когда был создан другой пользователь любого типа.

Как устранить ошибку и как я могу это сделать, чтобы один тип пользователей не мог получить доступ к просмотру других, введя URL-адрес?

Отредактировано после комментария отsouldeux

Вот один из моих взглядов, где клиент может обновить свою контактную информацию:

@login_required(login_url='/login/')
@permission_required(lambda u: u.has_perm('authentication.view_client'))
def contact(request):
    user = request.user
    if request.method == 'POST':
        # form = ContactForm()
        form = ContactForm(request.POST)
        if form.is_valid():
            user.profile.address = form.cleaned_data.get('address')
            user.profile.city = form.cleaned_data.get('city')
            user.profile.state = form.cleaned_data.get('state')
            user.profile.country = form.cleaned_data.get('country')
            user.profile.phone = form.cleaned_data.get('phone')
            user.profile.zip = form.cleaned_data.get('zip')


            user.save()
            messages.add_message(request,
                                 messages.SUCCESS,
                                 'Your contact was successfully edited.')

    else:

        form = ContactForm(instance=user, initial={
            'address': user.profile.address,
            'city': user.profile.city,
            'state': user.profile.state,
            'country': user.profile.country,
            'phone': user.profile.phone,
            'zip': user.profile.zip,
        })
    return render(request, 'client/client_contact.html', {'form': form})

И ошибка, которую я получил:

TypeError at /client/picture

'function' object is not iterable

Request Method:     GET
Request URL:    http://127.0.0.1:8000/client/picture
Django Version:     1.11.6
Exception Type:     TypeError
Exception Value:    

'function' object is not iterable

Exception Location:     /usr/local/lib/python2.7/dist-packages/django/contrib/auth/models.py in has_perms, line 285
Python Executable:  /usr/bin/python2.7
Python Version:     2.7.12
Python Path:    

['/home/shamsad/PycharmProjects/OpenGMS',
 '/home/shamsad/PycharmProjects/OpenGMS',
 '/usr/lib/python2.7',
 '/usr/lib/python2.7/plat-x86_64-linux-gnu',
 '/usr/lib/python2.7/lib-tk',
 '/usr/lib/python2.7/lib-old',
 '/usr/lib/python2.7/lib-dynload',
 '/home/shamsad/.local/lib/python2.7/site-packages',
 '/usr/local/lib/python2.7/dist-packages',
 '/usr/lib/python2.7/dist-packages',
 '/usr/lib/python2.7/dist-packages/PILcompat',
 '/usr/lib/python2.7/dist-packages/gtk-2.0']

Server time:    Sun, 29 Oct 2017 16:21:25 +0000

1 ответ

Вместо того, чтобы передавать лямбда-функцию в permission_required декоратор, переписать тест разрешения как отдельную функцию и применить его через method_decorator это работает на dispatch метод:

https://docs.djangoproject.com/en/dev/topics/class-based-views/intro/

Как использовать allow_required декораторы в представлениях на основе классов django

Вы также можете использовать @user_passes_test украсить ваши функциональные представления. Например, возможно, есть представление, которое вы хотите видеть только тем пользователям, которые связаны с Client объект:

def user_has_client(user)
    return hasattr(user, 'Client')

@user_passes_test(user_has_client, login_url='/')
def my_protected_view(request):
    ...

Вы также можете проверить права пользователей в своем тесте: https://docs.djangoproject.com/en/1.11/ref/contrib/auth/

Другие вопросы по тегам