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

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

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

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

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

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


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

6 ответов


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

[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. Проверьте, что разрешение "вид" добавляется ко всем моделям

run manage.py syncdb

Я подтвердил, что разрешение view теперь добавлено для всех таблиц в таблице 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" в класс администратора по умолчанию

чтобы быть последовательным, я собираюсь добавить "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 появляется для управления кнопками save/save и continue или нет. Изменено поле "Сохранить" по умолчанию всегда True, чтобы проверить контекст и разрешения. Пользователь должен иметь возможность сохранять, если у него есть разрешения на изменение или добавление.

 '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. Изменить разрешение "просмотр", чтобы сделать форму только для чтения

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

если у пользователя есть разрешение " просмотр "без" изменения", измените формы по умолчанию и добавьте атрибуты DISABLED или 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 %}

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

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

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

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

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

и

администратор Django работает на трех разрешения: "добавить", "изменить" и "исключать." Там нет "вид, но сделать разрешение "без изменений", следовательно нет способа применить такой ограничение не делая значительное пользовательское кодирование.

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


вы можете создать разрешение "только для чтения" в своей модели и использовать код 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

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


возможность добавления полей только для чтения в представление администратора теперь включена в 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


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