Pergunta

Eu estou olhando para fazer algo como isto:

Modelo limit_choices_to = { 'usuário': user}

com algumas diferenças.

Alguns modelos podem explicar:

class Job(models.Model):
    name = models.CharField(max_length=200)
    operators = models.ManyToManyField(User)

class Activity(models.Model):
    job = models.ForeignKey(Job)
    job_operators = models.ManyToManyField(User, limit_choices_to={user: Job.operators} blank=True, null=True)

Nota:. A sintaxe não pretende necessariamente correto, mas ilustrativo

Agora, eu tenho tido algum sucesso em conseguir o usuário atual, utilizando middleware, como algumas respostas sobre SO retratam, no entanto, eu estava esperando que eu poderia começar o trabalho atual, via request.POST, de tal forma que, se o atividade foram salvos, eu seria capaz de discernir o trabalho atual e, portanto, o subconjunto de usuários como operadores, que por sua vez, seria o conjunto de usuário para escolher no modelo de actividade.

Em outras palavras, com base nas seleções de um ManyToManyField no campo pai, oferta que sub-seleção para o campo filho, ou, se John, Jim, Jordânia e Jesse trabalhou em um trabalho, escolha apenas os nomes a descrever o trabalho em uma atividade, dentro e atribuído a esse trabalho.

BTW, aqui está a minha tentativa ingênua em middleware:

# threadlocals middleware
try:
    from threading import local
except ImportError:
    from django.utils._threading_local import local

_thread_locals = local()
def get_current_user():
    return getattr(_thread_locals, 'user', None)

def get_current_job():
    return getattr(_thread_locals, 'job', None)

class ThreadLocals(object):
    """Middleware that gets various objects from the
    request object and saves them in thread local storage."""
    def process_request(self, request):
        _thread_locals.user = getattr(request, 'user', None)
        _thread_locals.job = getattr(request.POST["job"], 'job', None)

eo modelo Atividade:

operators = modes.ManyToManyField(User, limit_choices_to=dict(Q(User.objects.filter(job==threadlocals.get_current_job)))

Obrigado.

Foi útil?

Solução

Ok, eu odeio jogar uma chave de macaco em suas obras, mas a sério não precisa usar threadlocals hacks.

O usuário está no objeto de solicitação que significa que não há necessidade de extraí-lo usando middleware. É passado como um argumento para cada exibição.

O truque para limitar suas escolhas de formulário é, portanto, alterar dinamicamente o queryset usado na forma em oposição a fazer um limite de opções no modelo.

Assim, seus formulário esta aparência:

# forms.py
from django import forms
from project.app.models import Activity
class ActivityForm(forms.ModelForm):
    class Meta:
        model Activity

e sua visão será parecido com este:

# views.py
...
form = ActivityForm(instance=foo)
form.fields['job_operators'].queryset = \
    User.objects.filter(operators__set=bar)
...

Este é apenas um esboço rápido, mas deve dar-lhe a idéia geral.

Se você está se perguntando como evitar threadlocals na administração, leia Usuários e administrador por James Bennett.

Editar: forma útil truques em Django por Collin Grady também mostra um exemplo de configuração dinamicamente o queryset no método de formulário __init__, que é mais limpo do que o meu exemplo acima.

Outras dicas

Mas o que sobre os campos que definem com list_filter? Eles só respeitar limit_choices_to. Então, se você quiser limitar as escolhas de Django admin filtra você tem que usar limit_choices_to e alguns Middleware para filtrá-los com base no usuário atual. Ou há uma solução mais fácil?

chaves de macaco acolher amigo!

Eu também tinha encontrado uma outra maneira, embora pareça menos direta:

class ActivityForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(ActivityForm, self).__init__(*args, **kwargs)

        if self.initial['job_record']:
            jr = JobRecord.objects.get(pk=self.initial['job_record'])
            self.fields['operators'].queryset = jr.operators

    class Meta:
        model = Activity
        exclude = ('duration',)  

Eu acho que os seus caminhos é melhor! Graças montes!

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