Как я могу изменить django для создания разрешения "view"?
Недавно я начал использовать django для администрирования большого существующего приложения, которое было органично выращено на протяжении многих лет, используя twisted.web. Я начал экспериментировать с django и его автоматическим интерфейсом администратора, и я был очень доволен результатами.
Одна вещь, которая, кажется, отсутствует в моих целях, - это способность предоставлять пользователям доступ только к данным. Например, у нас есть роль, когда людям разрешено входить в систему и создавать заказы на покупку. Они также должны иметь возможность просматривать, но не редактировать другие данные клиента или продукта.
Как мне создать разрешения "view" в администраторе django, чтобы пользователи могли изменять данные для некоторых таблиц, имея доступ только для чтения к другим?
Обновление: Django Admin, похоже, дает мне CUD интерфейса CRUD. Как получить часть только для чтения с соответствующими разрешениями и группами?
Обновление 2010-Feb-12: Django 1.2 теперь будет включать только чтение. Подробности ниже.
Я ответил на свой вопрос, я думаю. Перемещение содержимого вниз до реального ответа ниже.
Ответы
Ответ 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 для группы с разрешением на чтение. Дайте добавление, изменение прав доступа к группе. Они смогут читать только атрибуты модели.