Как ограничить доступ к UpdateView объекта создателю этого объекта

Django и нуб-программист здесь. Я сделал приложение, которое хотел бы развернуть, но мне нужно выяснить, как ограничить доступ к UpdateView создателю этого объекта, и я в тупике.

В настоящее время пользователь может использовать CreateView .../universities/create/ для создания объекта университета, но затем любой пользователь может использовать .../universities/update/ для редактирования этого объекта. Я хочу настроить это так, чтобы только пользователь, который является создателем (любой пользователь с атрибутом ManytoMany «администратор») этого университета, имел доступ к UpdateView для своего университетского объекта.

Любой совет будет принят во внимание. Я потратил на это несколько дней и не добился большого успеха... спасибо, что прочитали.

models.py

class University(models.Model):
    name = models.CharField(max_length=100)
    about = models.TextField()
    administrators = models.ManyToManyField(User)
    profile_picture = models.FileField(upload_to=get_upload_file_name, blank=True)

    def __unicode__(self):
        return unicode(self.name)

    def get_absolute_url(self):
        return reverse('university_detail', kwargs={'pk': str(self.id)})

views.py

class UniversityCreateView(CreateView):
    model = University
    form_class = UniversityForm
    template_name = 'university_create.html'

    def form_valid(self, form):
        f = form.save(commit=False)
        f.save()
        return super(UniversityCreateView, self).form_valid(form)

class UniversityUpdateView(UpdateView):
    model = University
    form_class = UniversityForm
    template_name='university_form.html'

person Mitch Downey    schedule 28.08.2013    source источник
comment
возможный дубликат Django: ограничение UpdateView для каждого пользователя   -  person Paulo Almeida    schedule 28.08.2013
comment
Я вижу, что это было помечено как дубликат, но я не понимаю, как этот пост мне помогает. Я не пытаюсь отобразить страницу, на которой пользователь может получить список университетов, для которых он является администратором. Я пытаюсь запретить любому, кто не является администратором университета, получать доступ к UpdateView для этого университета.   -  person Mitch Downey    schedule 28.08.2013
comment
Если я неправильно понимаю, и эта ссылка «возможный дубликат» на самом деле дает мне нужное мне решение, я был бы признателен за объяснение того, как это работает.   -  person Mitch Downey    schedule 28.08.2013
comment
Это не было помечено как дубликат, я сделал это предложение, потому что человек, задавший этот другой вопрос, похоже, хотел того же (ограничить UpdateView объектами, созданными вошедшим в систему пользователем). Согласно документации, метод get_queryset в UpdateView возвращает набор запросов, который будет использоваться для получения объекта, который будет отображаться в этом представлении. Поэтому, если вы ограничиваете пользователя набора запросов, объекты, созданные другими пользователями, не должны отображаться.   -  person Paulo Almeida    schedule 28.08.2013
comment
Ах, хорошо, спасибо за объяснение, get_queryset, по крайней мере, похоже на то, что мне скоро понадобится для другой функции моего UpdateView. Я буду продолжать пытаться увидеть, решит ли это эту текущую проблему с разрешениями.   -  person Mitch Downey    schedule 28.08.2013


Ответы (3)


вам нужно будет включить декораторы разрешений в свои представления, дополнительная информация находится здесь https://docs.djangoproject.com/en/dev/topics/auth/ , & https://docs.djangoproject.com/en/dev/topics/auth/default/#topic-authorization

поэтому, если вы хотите ограничить свое обновление для любого пользователя с атрибутом «администратор» ManytoMany, вам нужно будет сделать что-то вроде этого:

views.py

from appname.users.decorators import requiresGroup
from django.contrib.auth.decorators import login_required



class UniversityUpdateView(UpdateView):
    model = University
    form_class = UniversityForm
    template_name='university_form.html'

    @method_decorator(requiresGroup("groupname" , login_url='/accounts/login/'))
    def dispatch(self, request, *args, **kwargs):
    return super(UniversityUpdateView, self).dispatch(request, *args, **kwargs)

также, если вы еще этого не сделали, вам нужно включить следующее в верхнюю часть ваших моделей.py

from django.contrib.auth.modes import user

хотя я предполагаю, что он там, поскольку вы определили своих администраторов с моделью пользователя

затем перейдите к настройкам группы в администраторе django (должен быть URL-адрес, например localhost/admin/auth/group, добавьте свое специальное имя группы администраторов, затем перейдите в раздел пользователя администратора (localhost/admin/auth/user), затем сделайте уверен, что они были помещены в группу администраторов

затем замените «имя группы» в декораторе @requiresGroup на фактическое имя группы пользователей.

декоратор @requiresGroup не является стандартным декоратором, поэтому его нужно написать

сделайте путь к папке и файл, например appname/users.decorators.py, затем в decorators.py напишите

from functools import update_wrapper , wraps
from django.utils.decorators import available_attrs
from django.http import HttpResponse, HttpResponseRedirect


def requiresGroup(groupname):
    def decorator(view_function):
        def _wrapped_view(request,*args,**kwargs):
            if request.user.groups.filter(name=groupname).count()!=1:
                return HttpResponseRedirect("/")
            else:
                return view_function(request,*args,**kwargs)
        return wraps(view_function,assigned=available_attrs(view_function))(_wrapped_view)
    return decorator

надеюсь, это помогло

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

person Aesthete    schedule 29.08.2013

Вы можете использовать UserPassesTestMixin как написано в документации:

ограничить доступ на основе определенных разрешений или какого-либо другого теста

просто реализуйте test_func(self), который возвращает True, если пользователь должен войти в представление.

Вы можете написать такой код:

class UniversityUpdateView(UserPassesTestMixin,UpdateView):
    def test_func(self):
        return self.request.user.administrators_set.filter(pk=self.get_object().pk).exists()
    model = University
    form_class = UniversityForm
    template_name='university_form.html'
person ahmedakef    schedule 26.01.2018

Вы можете переопределить метод get вашего представления на основе класса (в данном случае UniversityUpdateView). Затем в методе проверьте, есть ли у пользователя права на доступ к странице, и если нет, вызовите исключение или перенаправьте пользователя на другую страницу. Если у пользователя достаточно прав для доступа к странице, просто продолжайте нормальное поведение.

class UniversityUpdateView(UpdateView):
    model = University
    form_class = UniversityForm
    template_name='university_form.html'

    def get(self, request, *args, **kwargs):
        if request.user.groups.filter(name=groupname).count()!=1:
                return HttpResponseRedirect("/")
        return super().get(request, *args, **kwargs)
person therealak12    schedule 20.04.2020