Как отказать пользователю одного вида в доступе к представлению другого пользователя через 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/