Domanda

che sto cercando di fare qualcosa di simile:

limit_choices_to Modello = { 'utente': user}

con alcune differenze.

Alcuni modelli possono spiegare:

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:. La sintassi non intende necessariamente corretto, ma illustrativi

Ora, ho avuto un certo successo ad ottenere l'utente corrente, utilizzando il middleware, come alcune risposte su SO rappresentare, tuttavia, speravo che avrei potuto ottenere il lavoro corrente, tramite request.POST, in modo tale che, se il Attività sono stati salvati, sarei stato in grado di discernere il lavoro corrente, e quindi il sottoinsieme di utenti come operatori, che gira, sarebbe all'utente di impostare da scegliere nel modello di attività.

In altre parole, in base alle selezioni di un ManyToManyField nel campo padre, offrono che sub-selezione al campo bambino, o, se John, Jim, Giordania e Jesse ha lavorato su un lavoro, scegliere solo i nomi a descrivere il lavoro su un'attività, all'interno e attribuito a tale lavoro.

A proposito, ecco il mio tentativo ingenuo nel 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)

e il modello di attività:

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

Grazie.

È stato utile?

Soluzione

Ok, io odio di gettare una chiave inglese nei tuoi lavori, ma sul serio non c'è bisogno di utilizzare threadlocals hack.

L'utente è nell'oggetto richiesta che significa che non v'è alcuna necessità di estrarre utilizzando il middleware. E 'passato come argomento ad ogni punto di vista.

Il trucco per limitare le scelte di forma è quindi quello di cambiare dinamicamente il set di query utilizzata nella forma in contrapposizione a fare una scelta limite nel modello.

Quindi, la vostra forma è simile al seguente:

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

e la vostra vista sarà simile a questa:

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

Questa è solo un rapido schizzo, ma dovrebbe darvi l'idea generale.

Se vi state chiedendo come evitare threadlocals in admin, si prega di leggere Gli utenti e la amministratore di James Bennett.

Modifica utili trucchi di modulo in Django di Collin Grady mostra anche un esempio di impostazione dinamicamente il set di query nel metodo __init__ modulo, che è più pulito rispetto al mio esempio di cui sopra.

Altri suggerimenti

Ma per quanto riguarda i campi si definisce con list_filter? Rispettano solo limit_choices_to. Quindi, se si desidera limitare le scelte dei filtri Django Admin è necessario utilizzare limit_choices_to e alcuni Middleware di filtrarli in base all'utente corrente. O c'è una soluzione più semplice?

scimmia Chiavi benvenuto amico!

Mi piacerebbe anche trovato un altro modo, anche se sembra meno diretta:

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',)  

Credo che le tue vie è meglio! Grazie cumuli!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top