2016-08-01 12 views
1

In meiner App habe ich 3 Modelle: Problem, Serie und Charakter. Das Issue-Modell hat einen Series ForeignKey und ein Character ManyToManyField. Hier sind sie vereinfacht:Django Vorlage für Schleife Iteration durch unterschiedliche Fremdschlüssel

class Character(models.Model): 
    name = models.CharField('Character name', max_length=200) 
    desc = models.TextField('Description', max_length=500) 

class Series(models.Model): 
    name = models.CharField('Series name', max_length=200) 
    desc = models.TextField('Description', max_length=500) 

class Issue(models.Model): 
    series = models.ForeignKey(Series, on_delete=models.CASCADE, blank=True) 
    name = models.CharField('Issue name', max_length=200) 
    number = models.PositiveSmallIntegerField('Issue number') 
    date = models.DateField('Cover date') 
    desc = models.TextField('Description', max_length=500) 
    characters = models.ManyToManyField(Character, blank=True) 
    cover = models.FilePathField('Cover file path', path="media/images/covers") 

Ich habe eine Zeichenvorlage, die Informationen über das Zeichen anzeigt. Ich möchte auch Ausgaben anzeigen, in denen sich der Charakter befindet, sortiert nach Serien.

{% extends "app/base.html" %} 

{% block page-title %}{{ character.name }}{% endblock page-title %} 

{% block content %} 

<div class="description"> 
    <p>{{ character.desc }}</p> 
</div> 

<div class="issues"> 
    <h3>Issues</h3> 
    {% for series in character.issue_set.all %} 
    <div> 
     <a href="{% url 'app:series' series.id %}">{{ series.name }}</a> 
     <ul> 
     {% for issue in character.issue_set.all %} 
      {% if issue.series.name == series.name %} 
      <li> 
       <a href="{% url 'app:issue' issue.id %}"><img src="/{{ issue.cover }}" alt = "{{ series.name }}" ></a> 
       <a href="{% url 'app:issue' issue.id %}"><p>Issue #{{ issue.number }}</p></a> 
      </li> 
      {% endif %} 
     {% endfor %} 
     </ul> 
    </div> 
    {% endfor %} 
</div> 

{% endblock content %} 

Offensichtlich ist die Art und Weise dies derzeit formatiert ist, dass in dem Satz für jede Ausgabe, den Titel der Serie gibt, und dann jede Ausgabe in dem Satz.

<div class="issues"> 
    <h3>Issues</h3> 
    <div> 
     <a href="/series/1">Series 1</a> 
     <ul> 
      <li> 
       <a href="/issue/1"><img src="/media/images/covers/01.jpg" alt="Series 1"></a> 
       <a href="/issue/1"><p>Issue #1</p></a> 
      </li> 
      <li> 
       <a href="/issue/2"><img src="/media/images/covers/02.jpg" alt="Series 1"></a> 
       <a href="/issue/2"><p>Issue #2</p></a> 
      </li> 
     </ul> 
    </div> 
    <div> 
     <a href="/series/1">Series 1</a> 
     <ul> 
      <li> 
       <a href="/issue/1"><img src="/media/images/covers/01.jpg" alt="Series 1"></a> 
       <a href="/issue/1"><p>Issue #1</p></a> 
      </li> 
      <li> 
       <a href="/issue/2"><img src="/media/images/covers/02.jpg" alt="Series 1"></a> 
       <a href="/issue/2"><p>Issue #2</p></a> 
      </li> 
     </ul> 
    </div> 
</div> 

Hier ist, was ich sehen möchte:

<div class="issues"> 
    <h3>Issues</h3> 
    <div> 
     <a href="/series/1">Series 1</a> 
     <ul> 
      <li> 
       <a href="/issue/1"><img src="/media/images/covers/01.jpg" alt="Series 1"></a> 
       <a href="/issue/1"><p>Issue #1</p></a> 
      </li> 
      <li> 
       <a href="/issue/2"><img src="/media/images/covers/02.jpg" alt="Series 1"></a> 
       <a href="/issue/2"><p>Issue #2</p></a> 
      </li> 
     </ul> 
    </div> 
</div> 

ich ziemlich viel auf Templating recherchiert habe, und ich sehe keinen Weg, um eine Liste zu erhalten, basierend auf unterschiedlichen Werten. Ich habe auch versucht, ein neues Set in meinem Charakter- oder Issue-Modell zu erstellen, das ich verwenden könnte, um issue_set.all zu ersetzen, aber ich muss es noch arbeiten lassen.

EDIT: Auf Anfrage von marcusshep wird die Zeichenansicht, die die allgemeine Detailview mit:

class CharacterView(generic.DetailView): 
    model = Character 
    template_name = 'app/character.html' 
+0

Kann ich Ihre Ansicht sehen, wo Sie das 'character' queryset an die Vorlage übergeben? – marcusshep

+0

@marcusshep, aktualisiert mit dem Ansichtscode. –

+0

Also, um klar zu sein, möchten Sie, dass Ihre Vorlage nur die Zeichen anzeigt, die einen eindeutigen Namen haben, richtig? – marcusshep

Antwort

1

würde ich eine Funktion basierend Ansicht verwenden, anstatt eine Klasse auf Basis generische Sicht. Grund ist, dass Ihr erforderliches Verhalten über etwas Generisches hinausgeht.

In Ihrer Funktion können Sie das gewünschte Abfrage-Set erstellen, anstatt mit dem von generic.DetailView gelieferten kämpfen zu müssen.

def my_view(request, *args, **kwargs): 
    character = Character.objects.get(id=request.GET.get("id", None)) 
    issues = character.issue_set.all().order_by("series__name") 
    return render(request, 'app/character.html', {"issues": issues}) 

Alternativ können Sie verwenden, was Sie bereits haben und die DetailView's get_queryset() method außer Kraft setzen.

class CharacterView(generic.DetailView): 
    model = Character 
    template_name = 'app/character.html' 

    def get_queryset(): 
     # return correct queryset 

Das größte Problem ist allerdings, dass es mehr Aspekte, die diesen Satz verwenden müssen. Zum Beispiel werde ich Creators, Story Arcs usw. hinzufügen, sie haben ihre eigenen Seiten und müssen verwandte Probleme anzeigen, sortiert nach Serien. Es wäre schön, eine Lösung zu haben, die von jeder dieser Vorlagen ohne viel Codewiederverwendung verwendet werden kann.

Dies ist ein sehr häufiges Problem in allen Bereichen der Programmierung. Eine sehr einfache Möglichkeit, dies zu lösen, wäre, die Logik in einer Funktion zu isolieren und diese Funktion bei Bedarf aufzurufen.

def my_issues_query(): 
    # find the objects you need 

def my_view(request, *args, **kwargs): 
    issues = my_issues_query() 

Sie können auch die Python-Decorator-Funktionen nutzen. (Welches ist meine bevorzugte Vorgehensweise.)

def has_issues(view_function): 
    def get_issues(request, *args, **kwargs): 
     # find all the issues you need here 
     # you'll only need to write this logic once. 
     issues = Issues.objects.filter(...) 
     return issues 
    return get_issues 

@has_issues 
def my_view(request, *args, **kwargs): 
    # this functions namespace now contains 
    # the variable `issues`. 
    # which allows for the use of the query ie. 
    return render(
     request, 
     "my_templates/template.html", 
     {"issues":issue} 
    ) 
+0

Das größte Problem ist jedoch, dass es mehr Aspekte geben wird, die diesen Satz verwenden müssen.Zum Beispiel werde ich Creators, Story Arcs usw. hinzufügen, sie haben ihre eigenen Seiten und müssen verwandte Probleme anzeigen, sortiert nach Serien. Es wäre schön, eine Lösung zu haben, die von jeder dieser Vorlagen ohne viel Codewiederverwendung verwendet werden kann. –

+0

Ja, schreibe einfach eine Funktion und rufe sie an, wo sie benötigt wird. Siehe aktualisierte Antwort. – marcusshep

+0

Würde das nicht nur die Ergebnisse von 'Issues' Objekten an die Vorlage übergeben ohne das 'Character' Objekt? Vielleicht ist mein Kopf noch nicht ganz da, aber in meinen Gedanken würde man der Vorlage das 'Character' als Hauptobjekt geben und dann die' Issues' Objekte durch Filtern nach 'Character' einziehen. Ich bin ziemlich neu in Django, also frage ich ehrlich! Danke für deine Hilfe bis jetzt! –