Mar*_*tin 9 python django django-templates django-models django-views
我是Django的新手,到目前为止我的能力给我留下了深刻的印象.我正在玩更复杂的模型,我有问题正确使用它们.使用Django 1.3,我正在尝试编写一个摘要页面,它将使用以下结构显示下面的三个模型.换句话说,列出他们的目的地和活动的旅行.
楷模
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)Run Code Online (Sandbox Code Playgroud)
我正在尝试编写一个视图,该视图将生成具有上述结构的页面.我现在面临的主要问题是显示特定旅行和目的地的活动.正如您在下面的代码中看到的,我正在构建一个字典,我怀疑这是正确的做法.此外,视图变为
视图
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,
})Run Code Online (Sandbox Code Playgroud)
模板
{% 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 %}
Run Code Online (Sandbox Code Playgroud)
简而言之,有人可以帮助我得到所有旅行和活动的摘要吗?实现这一目标的最佳方法是什么?模型是否正确?
谢谢!
ast*_*vic 19
还有很大的改进空间.通过在ManyToManyField上使用through,您可以明确定义连接表,我们可以方便地将其视为在特定旅行期间对城市的单次访问.在那次访问期间我们有活动,所以活动应该有一个外国访问.
对于表中的每个外键,Django将为关系的另一侧的对象集添加API便利管理器.Destination会有visit_set,但也会Trip.同样,因为visit在ForeignKey的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)
Run Code Online (Sandbox Code Playgroud)
然后让我们改变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
Run Code Online (Sandbox Code Playgroud)
最后是改进的模板:
{% 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 %}
Run Code Online (Sandbox Code Playgroud)
还有一些改进的改进空间.注意我使用了select_related.这将在获取访问时预取所有目标,以便visit.destination.city_name不会招致另一个db调用.但是,这不适用于反向ManyToMany关系(在我们的例子中是activity_set的所有成员).Django 1.4将推出名为prefetch_related的新方法,该方法也将解决这个问题.
与此同时,请阅读有效的反向查找,了解如何进一步减少数据库命中数.在评论中,也提到了几个现成的解决方案.
| 归档时间: |
|
| 查看次数: |
15106 次 |
| 最近记录: |