2010-06-20 3 views
2

외래 키당 하나의 개체 만 반환하는 쿼리 세트를 반환 할 수 있습니까?Django : 외래 키당 하나의 필터링 된 개체 반환

예를 들어 django_comments에서 최신 코멘트를 얻으 려하지만 객체 당 하나의 주석 (최신 코멘트) 만 필요합니다. 즉, 객체에 대한 최신 코멘트 만 반환하고 그 이전 코멘트를 모두 제외하십시오 목적. 나는 이것이 django_comments.content_type과 django_comments.object_pk의 SQL group_by와 비슷하다고 생각한다.

++ ADDED 정보 ++

는 최종 목표는 그 주제에 최근에 의해 나열되어 표준 토론 게시판처럼, 가장 최근의 코멘트를 갖고있는 스레드에 의해 주문 표시 활성 코멘트 "스레드"/ 목록을 만드는 것입니다 활동.

가장 좋은 방법은 최신 주석을 얻은 다음 콘텐츠 형식 및 object_pk별로 정렬하거나 그룹화하여 관련 콘텐츠 개체 당 하나의 주석 (최신)이 반환되도록하는 것입니다. 그런 다음 그 주석을 사용하여 필요한 모든 정보를 얻을 수 있습니다. 그래서 나는 정말로 주석을 붙잡고 그것을 따르는 단어이므로 느슨하게 사용됩니다.

MODEL은 django_threadedcomments로서 django_comments를 확장하여 나무, 자식 및 부모에 대해 몇 가지 추가 필드를 추가합니다.

보기 :

...이 부모

comments = ThreadedComment.objects.all().exclude(is_public='0').order_by("-submit_date") 

의 모든 인스턴스를 포함하여 모든 코멘트를 반환 ...이 이상적입니다

comments = ThreadedComment.objects.all().exclude(is_public='0').order_by("submit_date").[plus sorting logic to exclude multiple instances of the same object_pk and content_type] 

TEMPLATE :

{% for comment in comments %} 

TITLE: {{comment.content_object.title}} 

STARTED BY : {{comment.content_object.user}} 

MOST RECENT REPLY : {{comment.user}} on {{comment.submit_date}} 

{% endfor %} 

다시 한번 감사드립니다!

+1

는 기본적으로, 당신은 SQL'LIMIT를 원하는 1' ('[0]'장고 쿼리),하지만 당신은 스레드 당 있다는 싶어? 장고 쿼리가 어떻게 생겼는지 보여줄 수 있습니까? 그래서 우리는 어떻게 변경하는지 보여 줄 수 있습니까? –

+0

제 질문을 고맙게 생각했습니다. – jnh

+0

distinct를 사용하십시오. 이 대답을보십시오 http://stackoverflow.com/a/14293530/632182 – Christoffer

답변

2

SQL에서 수행하는 작업은 매우 어렵습니다. 당신은 아마 ORM을 통해 그것을 할 수 없을 것입니다.

이 경우 GROUP BY를 사용할 수 없습니다. 이것은 집계 항목을 그룹화하는 방법을 SQL에 알려주는 데 사용됩니다. 여기에서하는 일은 아닙니다. "SELECT x, y FROM table GROUP BY x"는 y 값이 의미가 없으므로 잘못된 SQL입니다. 마음에 명확한 스키마이에서

살펴 보자 :

CREATE TABLE objects (id INTEGER PRIMARY KEY, name VARCHAR); 
CREATE TABLE comments (object_id INTEGER REFERENCES objects (id), text VARCHAR NOT NULL, date TIMESTAMP NOT NULL); 

INSERT INTO objects (id, name) VALUES (1, 'object 1'), (2, 'object 2'); 
INSERT INTO comments (object_id, text, date) VALUES 
    (1, 'object 1 comment 1', '2010-01-02'), 
    (1, 'object 1 comment 2', '2010-01-05'), 
    (2, 'object 2 comment 1', '2010-01-08'), 
    (2, 'object 2 comment 2', '2010-01-09'); 

SELECT * FROM objects o JOIN comments c ON (o.id = c.object_id); 

내가이 일을 위해 본 중에 가장 우아한 방법은 PostgreSQL을 8.4의 윈도우 기능입니다.

SELECT * FROM (
    SELECT 
     o.*, c.*, 
     rank() OVER (PARTITION BY object_id ORDER BY date DESC) AS r 
    FROM objects o JOIN comments c ON (o.id = c.object_id) 
) AS s 
WHERE r = 1; 

각 개체의 첫 번째 메모를 최신 날짜순으로 선택합니다. 이것이 무엇을하는지 보지 못하면 자체 SELECT를 실행하고 rank()를 생성하는 방법을 관찰하십시오.

나는 Postgresql을 사용하여이 작업을 수행하는 다른 방법을 알고 있지만 다른 데이터베이스에서이 작업을 수행하는 방법을 알지 못합니다.

동적으로 계산하려고하면 심각한 문제가 발생할 수 있으며 복잡한 쿼리가 원활하게 수행되도록하려면 많은 작업이 필요합니다.이 간단한 작업을 수행하는 것이 더 나을 것입니다. 각 객체에 대해 last_comment_id 필드를 저장하고 주석을 추가하거나 삭제할 때이를 업데이트하여 조인하고 정렬 할 수 있습니다. 이 업데이트를 자동으로 처리하기 위해 SQL 트리거를 사용할 수 있습니다.

-1

어딘가에 (예 : 부모 개체 테이블에서) 마지막 게시물을 외래 키로 저장하는 것이 좋습니다. 메시지가 게시되거나 삭제 될 때마다이 키를 업데이트하십시오.

예, 중복되었지만 고려해 볼 가치가 있습니다. 각 요청 (특히 색인 페이지)에 대해 복잡한 쿼리를 실행하면 응용 프로그램 성능이 저하 될 수 있습니다. 이는 성능 저하없이 원하는 효과를 얻는 실용적인 방법입니다.

0

고마워 글렌과 vdboor. 합의한 바에 따르면 제안 된 아이디어는 SQL의 복잡성을 크게 높이고 성능에 심각한 영향을 미칩니다.

last_comment_id 제안은 매우 좋지만, 내 특별한 상황에서 가장 좋은 방법은 ID와 함께 주석 처리 된 원본 개체의 content_type 및 object_pk를 저장하는 별도의 "THREAD"모델을 만드는 것이라고 생각합니다. 객체의 마지막 주석의 타임 스탬프. 이렇게하면 단순한 콘텐츠 개체 조회와 연대순으로 필터링 된 쿼리 세트가 허용되며 후드에서 발생하는 상황을 프론트 엔드 프레젠테이션을보다 가깝게 반영 할 수 있습니다. 이는 후세에게 좋은 아이디어 일 것입니다. :)

건배,

jnh