Pergunta

Recentemente, comecei a usar o Django para administrar um grande aplicativo existente que foi cultivado organicamente ao longo dos anos usando Twisted.Web. Comecei a experimentar o Django e sua interface de administração automática e fiquei muito satisfeito com os resultados.

Uma coisa que parece estar faltando para meus propósitos é a capacidade de dar aos usuários apenas acesso ao acesso aos dados. Por exemplo, temos uma função em que as pessoas podem fazer login e criar pedidos de compra. Eles também precisam ser capazes de visualizar, mas não editar outros dados do cliente ou do produto.

Como eu criaria permissões de "visualização" no administrador do Django para que os usuários possam modificar os dados para algumas tabelas, enquanto tenham acesso apenas a outras pessoas?

ATUALIZAÇÃO: O DJANGO Admin parece me dar o CUD de uma interface CRUD. Como obtenho a parte de leitura apenas com permissões e grupos associados?

ATUALIZAÇÃO 2010-FEB-12: O Django 1.2 agora incluirá somente leitura. Detalhes abaixo.


Eu respondi minha própria pergunta, eu acho. Movendo o conteúdo para uma resposta real abaixo.

Foi útil?

Solução 5

A capacidade de adicionar campos somente leitura à visualização do administrador agora está incluída no Django versão 1.2.

Veja o ingresso número 342http://code.djangoproject.com/ticket/342

Veja o número de alterações 11965http://code.djangoproject.com/cheset/11965

Veja a documentaçãohttp://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.modeladmin.readonly_fields

Outras dicas

Foi assim que mudei o Django 1.0.2 para adicionar permissões de 'visualização'. Desculpe, não há diferenças disponíveis.

X] 1. Adicionado 'View' à lista de permissão padrão

#./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. Teste a permissão 'View' é adicionada a todos os modelos

run manage.py syncdb

Confirmei que a permissão de visualização agora é adicionada para todas as tabelas na tabela Auth_Permissions

X] 3. Adicione "get_view_permission" à classe de modelo padrão.

Adicionado get_view_permission à classe Model. Você pode encontrar isso no arquivo ./db/models/options.py Isso é usado pela classe Admin na próxima etapa.

def get_view_permission(self):
    return 'view_%s' % self.object_name.lower()

X] 4. Adicione "has_view_permission" à classe de administrador padrão

Só para ser consistente, vou adicionar "has_view_permission" ao sistema. Parece que deveria estar em algum lugar em contrib/admin/options.py. Certifique -se de que, se o usuário possui permissão de alteração, as permissões de visualização estão implícitas automaticamente.

# /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. Atualize o modelo padrão para listar modelos se o usuário tiver permissão de visualização

Modifiquei o modelo padrão em contrib/admin/modaplates/admin/index.html. Isso também pode ser tratado copiando o arquivo para o diretório de modelos locais. Eu fiz alterações em ambos, então tenho uma cópia se um atualização posterior substituir minhas alterações.

 {% 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. Confirme o usuário pode "visualizar", mas não "alterar" o modelo

Encontrado contrib/admin/templateTags/admin_modify.py parece controlar os botões Salvar/salvar e continuar aparecendo ou não. Campo "Salvar" alterado do padrão de sempre verdadeiro, para verificar se há contexto e permissões. O usuário deve poder salvar se tiver alteração ou adicionar permissões.

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

X] 7. Remova "Salvar e adicione outro botão" se o usuário estiver visualizando um item

Contrib/admin/templateTags modificado/admin_modify.py novamente. Eu não sei o que 'Save_as' significa, então talvez eu quebre alguma coisa, mas parece funcionar.

    #'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. Modifique a permissão "View" para fazer apenas o formulário de leitura

Se o usuário tiver permissão "Visualizar" e "alterar" a permissão, não faça nada. Alterar substituir a visualização.

Se o usuário tiver a permissão "View" sem "alteração", altere os formulários padrão e adicione atributos desativados ou readonamente para os elementos do formulário. Nem todos os navegadores suportam isso, mas para meus propósitos, posso exigir que os usuários usem o certo. Exemplo desativado / readonly

Descobriram que nem todos os navegadores honram "ReadOnly", por isso define alguns controles para ReadOnly, outros para deficientes. Isso permite que os usuários copam dados dos controles de texto, se necessário.

#/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 %}

Este snippet fará do SuperUser o único com acesso à gravação.

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

Está bem ali no administrador. Você pode definir permissões para usuários e grupos no administrador para adicionar, alterar e excluir modelos específicos.

Atualizar: Desculpe, entendi mal a pergunta porque interpretei mal a visão da palavra para dar o significado do django em vez de "somente leitura". Se você deseja apenas leitura usando o administrador, acho que precisará fazer um pouco de trabalho. Ver este tópico, onde James Bennett (gerente de lançamento do Django) diz:

Como você encontrará pesquisando os arquivos desta lista, isso não é algo que a interface administrativa do Django foi projetada para suportar e, portanto, qualquer solução precisará vir inteiramente de você escrever seu próprio código.

e

O administrador do Django opera em três permissões: "Adicionar", "Alterar" e "Excluir". Não há permissão de "visualização, mas não faça modificações", portanto, não há como aplicar essa restrição sem fazer codificação personalizada significativa.

O trabalho adicional envolverá você adicionar uma permissão "readnicamente" para determinados modelos e alterar os modelos de administrador básicos para verificar se o usuário tem essa permissão - e se assim for, desativando certos controles (como salvar botões) e fazer com que outras pessoas sejam leituras somente leitura . Isso impedirá a ajuste casual, mas você também pode precisar modificar a lógica do lado do servidor para verificar a mesma permissão, para evitar as postagens feitas de uma maneira sorrateira para contornar as permissões.

Você pode criar uma permissão "leitura" em seu modelo e usar o código de Jasuca com uma modificação:

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

No administrador da aplicação, você deve dar permissão de "mudança" e "readonly" ao usuário.

Você pode criar grupos no módulo de autenticação. Em seguida, no admin.py, com base no login do grupo de usuários, defina o atributo readonly_fields do ModelAdmin. Adicione o método def has_add_permission (self, solicitação) para retornar false para o grupo com permissão de leitura. Dê o add, modifique as permissões para o grupo. Eles poderão ler apenas os atributos do modelo.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top