2009-11-07 4 views
1

는 모델을 고려장고 : 자녀의 특성에 의해 객체를 주문하는 것은

class Author(models.Model): 
    name = models.CharField(max_length=200, unique=True) 

class Book(models.Model): 
    pub_date = models.DateTimeField() 
    author = models.ForeignKey(Author) 

지금은 모든 책, 말, 자신의 PUB_DATE를 주문한다고 가정합니다. order_by('pub_date')을 사용합니다. 그러나 가장 최근에 누가 책을 출판했는지에 따라 모든 저자 목록을 원한다면 어떻게해야합니까?

생각하면 정말 간단합니다. 그것은 본질적입니다 :

  • 가 정상에 저자는 가장 최근에 책
  • 다음 하나는 첫번째로 새로운 것이 아니다 책을 출판 하나를 게시 한 것입니다 등
  • 을에 따라서

나는 아마도 함께 해킹 할 수는 있지만, 이것이 커질 수 있기 때문에 나는 올바르게하고 있다는 것을 알아야한다.

감사합니다.

편집 : 마지막으로 각 필드에 마지막 필드의 날짜를 표시하고 전체 시간을 더 좋게 업데이트하는 옵션을 추가 할 수 있습니까?

답변

1

마지막으로, 단지를 추가하고자하는 옵션. 마지막 책의 날짜를 보여주고 전체 시간을 더 잘 업데이트 할 수 있도록 각 필드에 새로운 필드가 있습니까?

사실! 이것은 정상적인 비정규 연습과 같이 수행 할 수 있습니다

class Author(models.Model): 
    name = models.CharField(max_length=200, unique=True) 
    latest_pub_date = models.DateTimeField(null=True, blank=True) 

    def update_pub_date(self): 
     try: 
      self.latest_pub_date = self.book_set.order_by('-pub_date')[0] 
      self.save() 
     except IndexError: 
      pass # no books yet! 

class Book(models.Model): 
    pub_date = models.DateTimeField() 
    author = models.ForeignKey(Author) 

    def save(self, **kwargs): 
     super(Book, self).save(**kwargs) 
     self.author.update_pub_date() 

    def delete(self): 
     super(Book, self).delete() 
     self.author.update_pub_date() 

이 이미 제안 두 외에이 세 번째 일반적인 옵션 :

  • 조인과 SQL에 그 일을하고
  • 그룹화
  • 모든 도서를 파이썬 측에 가져오고 중복 제거하기

두 옵션 모두 t를 읽었을 때 정규화 된 데이터에서 pub_dates를 계산하도록 선택합니다 헛기침. 비정규 화는 새 데이터를 쓸 때 각 작성자에 대해이 계산을 수행합니다. 아이디어는 대부분의 웹 응용 프로그램이 쓰기보다 가장 자주 읽는 것이므로이 방법이 바람직합니다.

기본적으로 서로 다른 위치에 동일한 데이터가 있으며 동기화가 유지되어야합니다. 보통 데이터베이스 사람들을 죽음에 대해 소름 끼치게합니다. 하지만 이것은 ORM 모델을 사용하여 dat을 사용하기 전까지는 일반적으로 문제가되지 않습니다 (어쨌든 그렇게 함). Django에서는 데이터베이스를 제어하는 ​​응용 프로그램이 아니라 다른 방법으로 응용 프로그램을 제어합니다.

또 다른 (더 현실적인) 단점은 방대한 책의 업데이트를 보여준 순진한 코드는 제작자가 무엇을 상관없이 각 데이터를 업데이트하도록 ping을 수행하기 때문에 속도가 느릴 수 있다는 것입니다. 대개 update_pub_date을 일시적으로 비활성화 할 수있는 플래그를 지정하고 나중에 수동으로 호출하면 해결됩니다. 기본적으로 비정규 화 된 데이터는 정규화 된 것보다 유지 관리가 더 필요합니다.

0
def remove_duplicates(seq): 
    seen = {} 
    result = [] 
    for item in seq: 
     if item in seen: continue 
     seen[item] = 1 
     result.append(item) 
    return result 


# Get the authors of the most recent books 
query_result = Books.objects.order_by('pub_date').values('author') 
# Strip the keys from the result set and remove duplicate authors 
recent_authors = remove_duplicates(query_result.values()) 
+0

안녕하세요, 필요한 것 같습니다. 그냥 묻는다면 : 1. 작동 원리는 무엇입니까? 2. 성능면에서 어떻게됩니까? – cwj

+0

흠 실제로 죄송합니다. 작동하지 않습니다 .distinct() 호출이 목록과 상호 작용할 것입니다. – DevDevDev

+0

더 좋은 방법이있을 수 있습니다, 나는 SQL에서 이것을 할 수 있기 때문에 장고 모델을 사용하여 할 수 있다는 것을 알고 있습니다. 그러나 어떻게하면 머리 꼭대기에서 벗어날 수 있을지 생각할 수 없습니다. – DevDevDev

1

또는, 당신은 다음과 같이 놀러 수 : 이것은 당신이 장고 1.1

사용해야합니다

Author.objects.filter(book__pub_date__isnull=False).order_by('-book__pub_date')

+0

동일한 저자가있는 책이 많이있을 수 있습니다. –

+0

미안하지만 저자가 책이 없거나 책이 하나 이상 있는지에 관계없이 왜 작동하지 않습니까? – ayaz

1
from django.db.models import Max 
Author.objects.annotate(max_pub_date=Max('books__pub_date')).order_by('-max_pub_date') 

그리고 난 당신이 'related_name을 추가합니다 가정 '을 책 모델의 작성자 필드에 추가하면 Author.book_set 대신 Author.books에 의해 호출됩니다. 훨씬 더 읽기 쉽습니다. AYAZ의 솔루션에

0

빌딩 대해 : Author.objects.filter (book__pub_date__isnull = 거짓) .distinct() order_by ('- book__pub_date')

관련 문제