Domanda

Devo eseguire una query filtrata all'interno di un modello django, per ottenere una serie di oggetti equivalenti al codice Python in una vista:

queryset = Modelclass.objects.filter(somekey=foo)

Nel mio modello vorrei fare

{% for object in data.somekey_set.FILTER %}

ma non riesco proprio a scoprire come scrivere FILTER.

È stato utile?

Soluzione

Non puoi farlo, che è di progettazione. Gli autori del framework Django intendevano una rigorosa separazione del codice di presentazione dalla logica dei dati. Il filtro dei modelli è la logica dei dati e l'output dell'HTML è la logica di presentazione.

Quindi hai diverse opzioni. Il più semplice è fare il filtro, quindi passare il risultato a render_to_response. Oppure potresti scrivere un metodo nel tuo modello in modo da poter dire {% for object in data.filtered_set %}. Infine, potresti scrivere il tuo tag modello, anche se in questo caso specifico lo sconsiglio.

Altri suggerimenti

Aggiungo solo un tag modello aggiuntivo come questo:

@register.filter
def in_category(things, category):
    return things.filter(category=category)

Quindi posso fare:

{% for category in categories %}
  {% for thing in things|in_category:category %}
    {{ thing }}
  {% endfor %}
{% endfor %}

Mi imbatto in questo problema su base regolare e utilizzo spesso il " aggiungi un metodo " soluzione. Tuttavia, ci sono sicuramente casi in cui & Quot; aggiungi un metodo & Quot; oppure " calcolarlo nella vista " non funziona (o non funziona bene). Per esempio. quando si memorizzano nella cache frammenti di modello e sono necessari alcuni calcoli DB non banali per produrlo. Non vuoi far funzionare il DB a meno che non sia necessario, ma non saprai se devi farlo fino a quando non sarai profondamente nella logica del modello.

Alcune altre possibili soluzioni:

  1. Usa {% expr < espressione > come < var_name > %} tag modello trovato in http://www.djangosnippets.org/snippets/9/ L'espressione è qualsiasi espressione Python legale con il contesto del modello come ambito locale.

  2. Cambia il tuo processore modello. Jinja2 ( http://jinja.pocoo.org/2/ ) ha una sintassi quasi identica a il linguaggio modello Django, ma con la piena potenza di Python disponibile. È anche più veloce. Puoi farlo all'ingrosso, o potresti limitarne l'uso ai modelli su cui stai , ma usa il & Quot di Django; più sicuro & Quot; modelli per pagine gestite da designer.

Questo può essere risolto con un tag di assegnazione:

from django import template

register = template.Library()

@register.assignment_tag
def query(qs, **kwargs):
    """ template tag which allows queryset filtering. Usage:
          {% query books author=author as mybooks %}
          {% for book in mybooks %}
            ...
          {% endfor %}
    """
    return qs.filter(**kwargs)

L'altra opzione è che se hai un filtro che vuoi sempre applicare, aggiungere un gestore personalizzato sul modello in questione che applica sempre il filtro ai risultati restituiti.

Un buon esempio di questo è un Event modello, in cui per il 90% delle query che fai sul modello vorrai qualcosa come Event.objects.filter(date__gte=now), cioè normalmente sei interessato a Events che sono imminente. Questo sarebbe simile:

class EventManager(models.Manager):
    def get_query_set(self):
        now = datetime.now()
        return super(EventManager,self).get_query_set().filter(date__gte=now)

E nel modello:

class Event(models.Model):
    ...
    objects = EventManager()

Ma ancora una volta, questo applica lo stesso filtro a tutte le query predefinite fatte sul modello <=> e quindi non è così flessibile alcune delle tecniche sopra descritte.

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