考虑模型:
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')
。但是,如果我想要根据最近出版的书籍订购的所有作者的列表怎么办?
当你想到它时,它真的很简单。它基本上是:
我可能会在一起破解某些东西,但由于这可能会变大,我需要知道我做得对。
帮助表示赞赏!
编辑:最后,是否可以选择只为每个字段添加一个新字段以显示上一本书的日期,只是更新整个时间更好?
答案 0 :(得分:1)
或者,你可以玩这样的东西:
Author.objects.filter(book__pub_date__isnull=False).order_by('-book__pub_date')
答案 1 :(得分:1)
from django.db.models import Max
Author.objects.annotate(max_pub_date=Max('books__pub_date')).order_by('-max_pub_date')
这要求你使用django 1.1
我假设您将在Book模型中向作者字段添加'related_name',因此它将由Author.books而不是Author.book_set调用。它更具可读性。
答案 2 :(得分: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()
除了已经提出的两个选项之外,这是你拥有的第三个常用选项:
这两个选项都选择在读取时从标准化数据计算pub_dates。非规范化在您编写新数据时为每个作者执行此计算。这个想法是大多数网络应用程序读取的次数最多,而不是写入,所以这种方法更可取。
其中一个明显的缺点是,基本上你在不同的地方有相同的数据,它要求你保持同步。它通常会使数据库人员死亡:-)。但是,在使用ORM模型处理dat之前,这通常不是问题(您可能无论如何都要这样做)。在Django中,它是控制数据库的应用程序,而不是相反。
另一个(更现实的)缺点是,我已经展示了大量书籍的天真代码更新可能会慢一些,因为他们会ping作者,无论如何更新每次更新的数据。这通常通过使用一个标志暂时禁用调用update_pub_date
并在之后手动调用它来解决。基本上,非规范化数据需要比标准化更多的维护。
答案 3 :(得分: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())
答案 4 :(得分:0)
在ayaz的解决方案的基础上,如何: Author.objects.filter(book__pub_date__isnull =假).distinct()ORDER_BY( ' - book__pub_date')。