Подтвердить что ты не робот

Просмотреть разрешения в Django

Поскольку у django admin есть три разрешения в нем: добавление, изменение, удаление! Я хочу добавить разрешение на просмотр в этом auth в панели admin.I знаю, что мне нужно настроить разрешения для добавления разрешения на просмотр в 'auth | permission\can view permission' для просмотра всех записей!

ПУТЬ:

[X] 1. Добавлен список просмотров 'default' по умолчанию

#./contrib/auth/management/init.py
def _get_all_permissions(opts):

    "Returns (codename, name) for all permissions in the given opts."
    perms = []
    for action in ('add', 'change', 'delete', 'view'):

        perms.append((_get_permission_codename(action, opts), u'Can %s %s' % (action, opts.verbose_name_raw)))

    return perms + list(opts.permissions)

[X] 2. Тестирование разрешения 'view' добавляется ко всем моделям

run manage.py syncdb

Я подтвердил, что теперь разрешено разрешение просмотра для всех таблиц в таблице auth_permissions

[X] 3. Добавьте "get_view_permission" к классу модели по умолчанию.

Добавлен get_view_permission в класс модели. Это можно найти в файле. /db/models/options.py Это используется классом admin на следующем шаге.

def get_view_permission(self):

    return 'view_%s' % self.object_name.lower()

[X] 4. Добавьте "has_view_permission" к классу admin по умолчанию

Чтобы быть последовательным, я собираюсь добавить "has_view_permission" в систему. Похоже, он должен быть где-то в contrib/admin/options.py. Убедитесь, что у пользователя есть разрешение на изменение, затем автоматически отображаются разрешения на просмотр.

# /contrib/admin/options.py
# Added has_view_permissions
def has_view_permission(self, request, obj=None):

    """
    Returns True if the given request has permission to change or view
    the given Django model instance.


    If obj is None, this should return True if the given request has
    permission to change *any* object of the given type.
    """
    opts = self.opts
    return self.has_change_permission(request, obj) or \

        request.user.has_perm(opts.app_label + '.' + opts.get_view_permission())


# modified get_model_perms to include 'view' too.
# No idea where this may be used, but trying to stay consistent
def get_model_perms(self, request):

    """
    Returns a dict of all perms for this model. This dict has the keys
    add, change, and delete and view mapping to the True/False
    for each of those actions.
    """
    return {

        'add': self.has_add_permission(request),
        'change': self.has_change_permission(request),
        'delete': self.has_delete_permission(request),
        'view': self.has_view_permission(request),

    }


# modified response_add function to return the user to the mode list
# if they added a unit and have view rights
...

    else:

        self.message_user(request, msg)

        # Figure out where to redirect. If the user has change permission,
        # redirect to the change-list page for this object. Otherwise,
        # redirect to the admin index.
        #if self.has_change_permission(request, None):
        if self.has_change_permission(request, None) or self.has_view_permission(request, None):

            post_url = '../'

        else:

            post_url = '../../../'

        return HttpResponseRedirect(post_url)

    # modified the change_view function so it becomes the details
    # for users with view permission

        #if not self.has_change_permission(request, obj):
        if not (self.has_change_permission(request, obj) or (self.has_view_permission(request, obj) and not request.POST)):

            raise PermissionDenied

        # modified the changelist_view function so it shows the list of items
        # if you have view permissions

def changelist_view(self, request, extra_context=None):

            "The 'change list' admin view for this model."
            from django.contrib.admin.views.main import ChangeList, ERROR_FLAG
            opts = self.model._meta
            app_label = opts.app_label
            #if not self.has_change_permission(request, None):
            if not (self.has_change_permission(request, None) or self.has_view_permission(request, None)):

                raise PermissionDenied

[X] 5. Обновите шаблон по умолчанию, чтобы просмотреть модели, если у пользователя есть разрешение на просмотр.

Я изменил шаблон по умолчанию в contrib/admin/templates/admin/index.html. Это также может быть выполнено путем копирования файла в каталог локальных шаблонов. Я внес изменения в оба варианта, поэтому у меня есть копия, если последующее обновление перезаписывает мои изменения.

{% for model in app.models %}

    <tr>
    {% if model.perms.change %}

        <th scope="row"><a href="{{ model.admin_url }}">{{ model.name }}</a></th>

    {% else %}

        {% if model.perms.view %}

            <th scope="row"><a href="{{ model.admin_url }}">{{ model.name }}</a></th>

        {% else %}

            <th scope="row">{{ model.name }}</th>

        {% endif %}

    {% endif %}

[X] 6. Подтвердите, что пользователь может "просматривать", но не "изменять" модель.

Найдено вкладка contrib/admin/templatetags/admin_modify.py для управления кнопками сохранения/сохранения и продолжения. Изменено поле "сохранить" по умолчанию всегда "Истина", чтобы проверить контекст и разрешения. Пользователь должен иметь возможность сохранять, если они имеют изменения или добавлять разрешения.

'show_save': (change and context['has_change_permission']) or (context['add'] and context['has_add_permission'])

[X] 7. Удалите кнопку "Сохранить и добавить другую", если пользователь просматривает элемент

Изменен вкладчик contrib/admin/templatetags/admin_modify.py. Я не знаю, что означает "save_as", поэтому, возможно, я что-то сломал, но, похоже, он работает.

#'show_save_and_add_another': context['has_add_permission'] and
# not is_popup and (not save_as or context['add']) ,
'show_save_and_add_another': not is_popup and
    (( change and context['has_change_permission']) or (context['add'] and context['has_add_permission']))
    and
    (not save_as or context['add']),

[X] 8. Измените разрешение "view", чтобы сделать форму только для чтения

Если пользователь имеет разрешение "просмотреть" и "изменить", то ничего не делать. Изменение переопределения.

Если пользователь имеет разрешение "просмотреть" без "изменения", измените формы по умолчанию и добавьте атрибуты DISABLED или READONLY в элементы формы. Не все браузеры поддерживают это, но для моих целей я могу потребовать, чтобы пользователи использовали правильный. [Отключено/пример чтения] [1]

Обнаружил, что не все браузеры чтят "readonly", поэтому он устанавливает некоторые элементы управления для чтения, а другие - отключен. Это позволяет пользователям при необходимости копировать данные из текстовых элементов.

#/django/contrib/admin/templates/admin/change_form.html


{# JavaScript for prepopulated fields #}
{% prepopulated_fields_js %}


</div>
</form></div>
{% if has_view_permission and not has_change_permission %}

    <script type="text/javascript">
    jQuery('input:text').attr('readonly', 'readonly');
    jQuery('textarea').attr('readonly', 'readonly');
    jQuery('input:checkbox').attr('disabled', true);
    jQuery('select').attr('disabled', true);
    jQuery('.add-another').hide();
    </script>

{% endif %}

ИСТОЧНИК ОТВЕТОВ: Как я могу ИЗМЕНИТЬ django для создания "view" разрешение?

Вопрос: После следующего выше ответа я сделал и могу видеть эту страницу 127.0.0.1:8000/en-us/admin/как доступную только для чтения **, но пользователи в пользователях не видны 127.0.0.1: 8000/ru-ru/admin/user. Нужна помощь! **

4b9b3361

Ответ 1

Django 2.1 добавил разрешение на просмотр к разрешениям по умолчанию. Решение ниже может работать в более ранних версиях Django. https://docs.djangoproject.com/en/2.1/releases/2.1/#model-view-permission


Это рабочее решение, протестированное в Django 1.6.2.

[X] 1. Added 'view' to default permission list: ОК
[X] 2. Test the 'view' permission is added to all models: ОК

[X] 3. Add "get_view_permission" to default model class. больше бесполезно:

def get_add_permission(self):
    """
    This method has been deprecated in favor of
    'django.contrib.auth.get_permission_codename'. refs #20642
    """
    warnings.warn(
        "'Options.get_add_permission' has been deprecated in favor "
        "of 'django.contrib.auth.get_permission_codename'.",
        PendingDeprecationWarning, stacklevel=2)
    return 'add_%s' % self.model_name

И это относится ко всем этим методам get_foo_permission

[X] 4. Add "has_view_permission" to default admin class:

def has_view_permission(self, request, obj=None):
    """
    Returns True if the given request has permission to change or view
    the given Django model instance.


    If obj is None, this should return True if the given request has
    permission to change *any* object of the given type.
    """
    opts = self.opts
    codename = get_permission_codename('view', opts)
    return self.has_change_permission(request, obj) or \
        request.user.has_perm("%s.%s" % (opts.app_label, codename))

если модель встроенная, проверьте ее правильность, поэтому необходимо знать о правильном представлении

def get_inline_instances(self, request, obj=None):

    ...

    if not (inline.has_add_permission(request) or
            inline.has_change_permission(request, obj) or
            inline.has_delete_permission(request, obj) or
            inline.has_view_permission(request, obj)):  # add the view right
        continue

    ...

Сделайте модификацию get_model_perms для включения 'view', в той же идее сделайте следующее:

def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None):

    ...

    context.update({

        ...

        'has_view_permission': self.has_view_permission(request, obj), # add the view right

        ...

    })

    ....

Разрешить "правому представлению" отображать страницу (одного объекта) и отключить "правое представление", чтобы сохранить изменения, сделанные на странице, избегать [X] 8. Modify "view" permission to make form read only

@csrf_protect_m
@transaction.atomic
def change_view(self, request, object_id, form_url='', extra_context=None):
    "The 'change' admin view for this model."
    model = self.model
    opts = model._meta

    obj = self.get_object(request, unquote(object_id))

    # addthe view right
    if not (self.has_view_permission(request, obj) or
            self.has_change_permission(request, obj)):
        raise PermissionDenied

    ...

    inline_instances = self.get_inline_instances(request, obj)
    # do not save the change if I'm not allowed to:
    if request.method == 'POST' and self.has_change_permission(request, obj):
        form = ModelForm(request.POST, request.FILES, instance=obj)

    ...

Разрешить "правильное представление" для отображения страницы (список всех объектов)

@csrf_protect_m
def changelist_view(self, request, extra_context=None):
    """
    The 'change list' admin view for this model.
    """
    from django.contrib.admin.views.main import ERROR_FLAG
    opts = self.model._meta
    app_label = opts.app_label
    # allow user with the view right to see the page
    if not (self.has_view_permission(request, None) or
            self.has_change_permission(request, None)):
        raise PermissionDenied

    ....

[X] 5. Update default template to list models if user has view permission: ОК, но во избежание изменения HTML-шаблона отредактируйте этот файл: contrib/admin/site.py

class AdminSite(object):

    @never_cache
    def index(self, request, extra_context=None):

        ...

        # add the view right
        if perms.get('view', False) or perms.get('change', False):
        try:
            model_dict['admin_url'] = reverse('admin:%s_%s_changelist' % info, current_app=self.name)
        except NoReverseMatch:
            pass

        ...

    def app_index(self, request, app_label, extra_context=None):

        ...

        # add the view right
        if perms.get('view', False) or perms.get('change', False):
            try:
                model_dict['admin_url'] = reverse('admin:%s_%s_changelist' % info, current_app=self.name)
            except NoReverseMatch:
                pass

        ...

[X] 6. Confirm user can "view" but not "change" the model и [X] 7. Remove "Save and Add another" button if user is viewing an item: должно быть в порядке, но я сделал это:

'show_save_as_new': context['has_add_permission'] and not is_popup and change and save_as,
'show_save': context['has_change_permission'],

[X] 8. Измените разрешение на "просмотр", чтобы сделать форму доступной только для чтения: хорошо, но у меня есть другое решение, см. Выше

Ответ 2

Добавление разрешения 'view' на список разрешений по умолчанию

Ваше решение работает, но, по возможности, вы действительно должны избегать редактирования исходного кода. Есть несколько способов сделать это в рамках:

1. Добавить разрешение во время post_syncdb():

В файле под именем your_app/management/

from django.db.models.signals import post_syncdb
from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.models import Permission

def add_view_permissions(sender, **kwargs):
    """
    This syncdb hooks takes care of adding a view permission too all our 
    content types.
    """
    # for each of our content types
    for content_type in ContentType.objects.all():
        # build our permission slug
        codename = "view_%s" % content_type.model

        # if it doesn't exist..
        if not Permission.objects.filter(content_type=content_type, codename=codename):
            # add it
            Permission.objects.create(content_type=content_type,
                                      codename=codename,
                                      name="Can view %s" % content_type.name)
            print "Added view permission for %s" % content_type.name

# check for all our view permissions after a syncdb
post_syncdb.connect(add_view_permissions)

Всякий раз, когда вы выдаете команду "syncdb", все типы контента могут быть проверить, есть ли у них разрешение "view", а если нет, создайте один.

2. Добавьте разрешение в параметр Мета-разрешения:

В каждой модели вы добавили бы что-то вроде этого к своим опциям Meta:

class Pizza(models.Model):
    cheesiness = models.IntegerField()

    class Meta:
        permissions = (
            ('view_pizza', 'Can view pizza'),
        )

Это будет выполняться так же, как 1, за исключением того, что вы должны вручную добавить его в каждый класс.

3. NEW в Django 1.7, добавьте разрешение на параметр Meta default_permissions:

В Django 1.7 они добавили опцию Meta default_permissions. Под каждой моделью вы должны добавить 'view' к опции default_permissions:

class Pizza(models.Model):
    cheesiness = models.IntegerField()

    class Meta:
        default_permissions = ('add', 'change', 'delete', 'view')