假設我有一個像這樣的 Post 模型:
class Post(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
text_content = models.CharField()
@property
def comment_count(self):
return self.comments.count()
假設我需要獲取 ID 為 3 的帖子的所有資料。我知道我可以在一個查詢中檢索用戶和帖子,通過執行Post.objects.select_related('user').get(pk=3),允許我保存查詢。但是,有沒有辦法自動獲取comment_count?
我知道我可以使用Post.objects.annotate(comment_count=Count('comments'))(這將需要我洗掉屬性或更改注釋的名稱,因為會有AttributeError),但是是否可以讓 ORM 自動執行該部分,因為該屬性是在模型中宣告的?
雖然我可以只添加.annotate,但是當需要在多個位置獲取多個屬性和外鍵時,這會變得非常乏味。
uj5u.com熱心網友回復:
也許這對您來說不是一個完美的解決方案,但您可能會找到類似的方法。您可以添加自定義物件管理器,請參閱檔案
然后你可以添加一個像with_comment_count(). 或者如果你總是想注釋,那么你可以修改初始查詢集。
class PostManager(models.Manager):
def with_comment_count(self):
return self.annotate(
comment_count=Count('comments')
)
# Or this to always annotate
def get_queryset(self):
return super().get_queryset().annotate(
comment_count=Count('comments')
)
class Post(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
text_content = models.CharField()
objects = PostManager()
然后你可以這樣查詢。
post = Post.objects.get(pk=1).with_comment_count()
post.comment_count
uj5u.com熱心網友回復:
感謝Felix Ekl?f我設法讓它作業!正如問題中所指定的,這是在有多個屬性/外鍵需要預取的情況下,因此需要“鏈接”預取的能力。通過鏈接PostManager方法這是不可能的,因為它們不回傳 a PostManagerbut a QuerySet,但是我想出了一個函式來快取它要求一次快取的所有內容,避免需要鏈接方法:
class PostManager(models.Manager):
def caching(self, *args):
query = self.all()
if 'views' in args:
query = query.annotate(view_count=Count('views'))
if 'comments' in args:
query = query.annotate(comment_count=Count('comments'))
if 'user' in args:
query = query.select_related('user')
if 'archives' in args:
query = query.prefetch_related('archives')
return query
class Post(models.Model):
objects = PostManager()
...
# caching can then be added by doing, this, for instance:
Post.objects.caching('views', 'user', 'archives').get(id=3)
請注意,要使其正常作業,我還必須更改@property為@cached_property,從而允許 ORM 替換該值,并允許使用相同名稱進行正確快取。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/343434.html
標籤:姜戈 奥姆 django-queryset
