2013-03-16 2 views
3

나는 다소 복잡해 보이지 않는 것으로 막혔습니다. 여기 내 모델 :Django에서 일대 다 많은 관계를 모델링하고 표현하는 우아한 방법이 있습니까?

class Team(models.Model): 
    name = models.CharField('team name', max_length=200, unique=True) 

class QualityStream(models.Model): 
    name = models.CharField('quality stream name', max_length=200, unique=True) 
    team = models.ManyToManyField(Team) 

class Milestone(models.Model): 
    name = models.CharField('milestone name', max_length=200) 
    quality_stream = models.ForeignKey(QualityStream) 
    team = models.ForeignKey(Team) 

당신이 볼 수 있듯이, 팀은 몇 가지 미리 정의 된 품질 스트림이 있고, 여러 가지 이정표 수 실제로는 품질 스트림에 속한다는 것을 얻을 수 있습니다. 여기

내보기 :

아이디어는 팀을 표시하는 것입니다
<p>{{team.name}}</p> 

{% for stream in team.qualitystream_set.all %} 
    <p>{{stream.name}}</p> 
    {% for milestone in team.milestone_set.all %} 

     {% if milestone.quality_stream.id == stream.id %} 
      <p>{{milestone.name}}</p>    
     {% endif %} 

    {% endfor %}  
{% endfor %} 

, 품질 스트림에 의해 그룹화 된 팀과 각 이정표에 관련된 품질 스트림 : 코드는 잘 작동

Team 

    Quality Stream 1 
    Milestone 1 for Quality Stream 1 
    Milestone 2 for Quality Stream 1 
    Quality Stream 2 
    Milestone 1 for Quality Stream 2 
    Milestone 2 for Quality Stream 2 

, 그러나 각 품질 흐름에 대한 모든 이정표를 반복함으로써 너무 편안하지는 않습니다. 나는 이것을 달성하는 더 좋은 방법이 있어야한다고 생각합니다. 어떤 아이디어?

답변

2

하는 데 도움이됩니다.

@Pathetique가 지적한 바와 같이, 다음 링크는 수행중인 쿼리의 수를 최소화하는 방법을 보여줍니다

https://docs.djangoproject.com/en/1.5/topics/db/optimization/#retrieve-everything-at-once-if-you-know-you-will-need-it

링크의 하이라이트는 ForeignKeys에서만 작동 select_relatedprefetch_related입니다 ManyToManyFields에서만 작동합니다.

"이 팀에 관련된 모든 데이터를 보여주고 싶습니다."라는 관점에서이 문제에 접근 했으므로 Team부터 사용 가능한 최적화를 사용할 수 없습니다 ForeignKeys 또는 ManyToManyFields이 없습니다.

대신 "팀별로 그룹화 한 다음 품질 스트림별로 모든 이정표를 표시하고 싶습니다."와 같은 문제에 접근 할 수 있습니다. Milestone 클래스는 필요한 모든 데이터에 액세스 할 수 있으므로 쿼리 세트를 매우 쉽게 작성하고 단일 쿼리 만 생성합니다.

def my_view(request): 
    queryset = Milestone.objects.select_related(
     'team', 'quality_stream' 
    ).order_by(
     'team__name', 'quality_stream__name' 
    ) # a single query to fetch all teams + streams + milestones 

    return render_to_response('/your/template.html', 
     { 'milestones':queryset }, 
     context_instance=RequestContext(request) 
    ) 

이제 템플릿이 생성 된 방식대로 작동하지 않게됩니다. 이것은 내가 전에 언급 한 문제의 정의가 들어오는 곳입니다. 당신은 모든 이정표를 가졌지 만, 당신은 팀에 의해 그리고 그 다음에 질적 인 흐름에 의해 그들을 그룹화하기를 원합니다. 우리가 모든 이정표를 반복 할 수 있고 우리가 새로운 팀 또는 새로운 품질의 스트림에 이르기까지 있는지 확인할 수 있기 때문에 우리 쿼리 세트의 주문은 지금 우리에게 도움이됩니다.

# your template 
{% for milestone in milestones %} 
    {% ifchanged %} <p> {{ milestone.team.name }} </p> {% endifchanged %} 
    {% ifchanged %} <p> {{ milestone.quality_stream.name }} </p> {% endifchanged %} 
    <p> {{ milestone.name }} </p> 
{% endfor %} 

위의 템플릿은이 목적을 위해 정확하게 설계된 것 같다 ifchanged 템플릿 태그를 사용합니다.

2

잘못된 것은 당신이 무엇을하고 있는지에 없습니다 만, 특히) (select_related 사용하여보기에서 쿼리를 수행하여 일부 데이터베이스 최적화가있을 수 있습니다 : 또한

https://docs.djangoproject.com/en/1.5/topics/db/optimization/#retrieve-everything-at-once-if-you-know-you-will-need-it

, 당신의 모델이 있었다면 필드의 무리 그러나 당신은 당신이 단지() 또는 defer()를 사용할 수있는 것들만 필요로했습니다. 큰 필드를 피하기 위해 지연을 사용하여 상당한 성능 향상을 보았습니다.

https://docs.djangoproject.com/en/1.5/ref/models/querysets/#defer

귀하의 모델 그래서 난 그냥 select_related 사용하여 생각이 너무 복잡하지 않는 것()는 당신을 위해 작동합니다 : 전용 (은) 연기의 단지 역()입니다. 최적화 결정을 내릴 때 Django debug toolbar을 사용하는 것이 좋습니다. 디버그 도구 모음에는 실제 select 문과 각각에 대해 걸린 시간이 표시됩니다. 너무 많은 시간을 소비하기 전에 실제로 문제가 있는지를 아는 것이 좋습니다. 당신은 여러 하강 당신이 가지고있는 것처럼, 당신은 반대쪽에서 문제에 접근 할 수 있는지 여부에 대해 생각 루프를해야 할 생각 할 때마다

희망이

+1

좋은 대답은 올바른 문서와 연결되어 있지만 템플릿으로 전달되는보기 내에서 적절한 쿼리 세트를 만드는 방법을 보여주는 코드 스 니펫을 포함해야합니다. –

+0

감사합니다. Josh, 저를 이길 것 같습니다 +1 – Fiver

+0

haha ​​sorry mate, 코드를 적어서 답을 수정하려고했지만 주제가 더 많았습니다. –

관련 문제