2012-02-26 44 views
3

我是Django的新手,至今我的能力給我留下了深刻的印象。我正在玩更復雜的模型,我有問題正確使用它們。使用Django 1.3,我正在嘗試編寫一個摘要頁面,它將使用以下結構呈現下面的三個模型。換句話說,一個旅行目的地和活動的列表。Django和具有多個外鍵的模型

  • 旅行1
    • 目的地1
    • 目的地2
    • 活動1
  • 旅行2
    • 目的地1
    • 活動2

模型

  • 旅行< - > TripDestination < - >目標(一個行程可以有多個目的地)
  • 活動 - >跳閘,活動 - >目標(一個活動是定義爲在特定位置/目的地旅行)
class Destination(models.Model): 
     city_name=models.CharField() 

    class Trip(models.Model): 
     departing_on=models.DateField() 
     returning_on=models.DateField() 
     destinations=models.ManyToManyField(Destination) 

    class Activity(models.Model): 
     destination=models.ForeignKey(Destination, null=False) 
     trip=models.ForeignKey(Trip, null=False)

我正在嘗試編寫一個視圖,該視圖將生成具有上述結構的頁面。我現在面臨的主要問題是顯示特定行程和目的地的活動。正如你在下面的代碼中看到的,我正在建立一本字典,我懷疑這是正確的做法。此外,角度的

查看

def list_trip(request, template_name = 'trip-list.html'): 
    trips = Trip.objects.all() 

    # Build a dictionary for activities -- Is this the right thing to do? 
    activities = Activity.objects.filter(trip__in=trips) 
    activities_by_trips = dict() 
    for activity in activities: 
     if activity.trip_id not in activities_by_trips: 
      activities_by_trips[activity.trip_id] = dict() 

     if activity.destination_id not in activities_by_trips[activity.trip_id]: 
      activities_by_trips[activity.trip_id][activity.destination_id] = [] 

     activities_by_trips[activity.trip_id][activity.destination_id].append(activity) 

    return render_to_response(template_name, { 
     'page_title': 'List of trips', 
     'trips': trips, 
     'activities_by_trips': activities_by_trips, 
    })

模板


{% block content %} 
    {% for trip in trips %} 
     {{ trip.id }} - {{ trip.name }} 

     {% for destination in trip.destinations.all %} 
      {{ destination.city_name }} 

      ** This is terrible code -- How to fix that ** 
      {% for key, value in activities_by_trips|dict_lookup:trip.id %} 
       {% if value %} 
        {% for key_prime, value_prime in value|dict_lookup:destination.id %} 
         {{ value_prime.description }} 
        {% endfor %} 
       {% endif %} 
      {% endfor %} 
     {% endfor %} 
    {% endfor %} 
{% endblock %} 

簡單地說,有人可以幫我把所有的行程和活動的總結?什麼是最好的方式來實現這一目標?模型是否正確?

謝謝!

回答

13

有很大的改進空間。通過在ManyToManyField上使用through,您可以明確定義連接表,我們可以方便地將它視爲在特定旅程中對城市的單次訪問。在那次訪問期間我們有活動,所以活動應該有一個外地訪問。

對於表中的每個外鍵,Django都會爲關係對面的對象集添加API便利管理器。 Destination將有visit_set,但Trip也會有。同樣,由於visit外鍵在Activity每次訪問將有一個activity_set

首先開始與型號:

from django.db import models 

# Create your models here. 
class Destination(models.Model): 
    city_name=models.CharField(max_length=50) 

class Trip(models.Model): 
    departing_on=models.DateField() 
    returning_on=models.DateField() 
    destinations=models.ManyToManyField(Destination, through='Visit') 

class Visit(models.Model): 
    destination=models.ForeignKey(Destination) 
    trip=models.ForeignKey(Trip) 

class Activity(models.Model): 
    name=models.CharField(max_length=50) 
    visit=models.ForeignKey(Visit) 

然後讓變化list_trip了一下,加print_trip什麼是模板回事清晰:

def list_trip(request, template_name = 'trip-list.html'): 
    return render_to_response(template_name, { 
     'page_title': 'List of trips', 
     'trips': Trip.objects.all(), 
     }) 

def print_trips(): 
    for trip in Trip.objects.all(): 
     for visit in trip.visit_set.select_related().all(): 
      print trip.id, '-', visit.destination.city_name 
      for act in visit.activity_set.all(): 
       print act.name 

最後改進的模板:

{% block content %} 
    {% for trip in trips %} 
     {{ trip.id }} - {{ trip.name }} 

     {% for visit in trip.visit_set.select_related.all %} 
      {{ visit.destination.city_name }} 

      {% for act in visit.activity_set.all %} 
       {{ act.name }} 
      {% endfor %} 
     {% endfor %} 
    {% endfor %} 
{% endblock %} 

還有一些提升空間性能明智。注意我使用了select_related。這將在訪問訪存時預取所有目標,以便visit.destination.city_name不會引發另一個數據庫調用。但是,這不適用於反向ManyToMany關係(在我們的例子中是activity_set的所有成員)。 Django 1.4將推出一種名爲prefetch_related的新方法,它也可以解決這個問題。

與此同時,請閱讀Efficient reverse lookups瞭解如何進一步減少數據庫命中數。在評論中,也提到了幾種現成可用的解決方案。

+0

謝謝digivampire!這正是我所期待的。 – Martin 2012-02-27 22:08:03