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

Как я могу изменить django для создания разрешения "view"?

Недавно я начал использовать django для администрирования большого существующего приложения, которое было органично выращено на протяжении многих лет, используя twisted.web. Я начал экспериментировать с django и его автоматическим интерфейсом администратора, и я был очень доволен результатами.

Одна вещь, которая, кажется, отсутствует в моих целях, - это способность предоставлять пользователям доступ только к данным. Например, у нас есть роль, когда людям разрешено входить в систему и создавать заказы на покупку. Они также должны иметь возможность просматривать, но не редактировать другие данные клиента или продукта.

Как мне создать разрешения "view" в администраторе django, чтобы пользователи могли изменять данные для некоторых таблиц, имея доступ только для чтения к другим?

Обновление: Django Admin, похоже, дает мне CUD интерфейса CRUD. Как получить часть только для чтения с соответствующими разрешениями и группами?

Обновление 2010-Feb-12: Django 1.2 теперь будет включать только чтение. Подробности ниже.


Я ответил на свой вопрос, я думаю. Перемещение содержимого вниз до реального ответа ниже.

4b9b3361

Ответ 1

Возможность добавления полей только для чтения в представление администратора теперь включена в Django версии 1.2.

Смотрите номер билета 342 http://code.djangoproject.com/ticket/342

См. номер набора изменений 11965 http://code.djangoproject.com/changeset/11965

См. документацию http://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.readonly_fields

Ответ 2

Вот как я изменил Django 1.0.2, чтобы добавить разрешения "view". Извините, нет никакой возможности.

[X] 1. Добавлен список "просмотра" в список разрешений по умолчанию

#./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 в элементы формы. Не все браузеры поддерживают это, но для моих целей я могу потребовать, чтобы пользователи использовали правильный. Отключено /Readonly пример

Обнаружил, что не все браузеры чтят "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 %}

Ответ 3

Этот фрагмент сделает суперпользователем единственным, у которого есть доступ на запись.

class AdminOwn(admin.ModelAdmin):
    def get_readonly_fields(self, request, obj=None):
        if request.user.is_superuser:
            return self.readonly_fields
        #get all fields as readonly
        fields = [f.name for f in self.model._meta.fields]
        return fields

Ответ 4

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

Обновление: Извините, я неправильно понял вопрос, потому что я неверно истолковал слово-представление, чтобы придать ему значение Django, а не "только для чтения". Если вы хотите читать только с помощью администратора, я думаю, вам нужно будет немного поработать. См. этот поток, где Джеймс Беннетт (менеджер выпуска Django) говорит:

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

и

Администратор Django работает на трех разрешений: "добавить", "изменить" и "Удалить". Нет "просмотра, но без изменений", следовательно нет способа применить такой ограничение без значительных пользовательское кодирование.

Дополнительная работа включает в себя добавление разрешений "только для чтения" для определенных моделей и изменение основных шаблонов администратора, чтобы проверить, имеет ли пользователь это разрешение - и если это так, отключить определенные элементы управления (например, кнопки сохранения) и сделать другие только для чтения. Это предотвратит случайное возирование, но вам также может потребоваться изменить логику на стороне сервера, чтобы проверить одно и то же разрешение, чтобы избежать каких-либо POST-сообщений, сделанных скрытым способом обхода разрешений.

Ответ 5

Вы можете создать разрешение "только для чтения" в своей модели и использовать код jasuca с модификацией:

models.py:

class MyModel(models.Model):
    name = models.CharField(max_length=100)
    description = models.CharField(max_length=256, null=True, blank=True)

    class Meta:
        permissions = (
            ('readonly_mymodel','Readonly MyModel'),
        )

admin.py:

class MyModelAdmin(admin.ModelAdmin):
    def get_readonly_fields(self, request, obj=None):
        if not request.user.is_superuser and request.user.has_perm('mymodel.readonly_mymodel'):
            return [f.name for f in self.model._meta.fields]
        return self.readonly_fields

В админере приложения вы должны разрешить пользователю "изменять" и "читать только".

Ответ 6

Вы можете создавать группы в модуле auth. Затем в admin.py на основе входа в группу пользователей установите атрибут modeladmin readonly_fields. Добавьте метод def has_add_permission (self, request), чтобы вернуть false для группы с разрешением на чтение. Дайте добавление, изменение прав доступа к группе. Они смогут читать только атрибуты модели.