Django中get_queryset与Model Manager的区别及用法有哪些?
Model Managers vs.
get_queryset() in Django: Differences & Use Cases Great question! Let’s break down the differences between using a model manager directly (like Model.objects.all()) and calling self.get_queryset()—this is a common point of confusion when working with Django views or custom managers.
Core Definitions First
- Model Managers (e.g.,
Model.objects): This is Django ORM’s official entry point to the database. Every model gets a defaultobjectsmanager (an instance ofmodels.Manager) out of the box. When you callModel.objects.all(), you’re directly invoking a method on this manager to build and return aQuerySet. get_queryset(): This is a method primarily used in class-based views (CBVs) or custom managers. Its job is to return a baseQuerySetthat the view/manager will use for subsequent operations (filtering, pagination, fetching single objects, etc.).
Key Differences & Use Cases
1. Where You’ll Use Them
Direct Manager Calls: Use this anywhere you have access to the model class—view functions, model methods, standalone scripts, even templates (though templates should keep logic minimal). It’s the go-to for straightforward, context-agnostic queries.
Example:# In a function-based view def all_posts(request): posts = Post.objects.all() return render(request, 'posts/list.html', {'posts': posts}) # In a model class method class Post(models.Model): status = models.CharField(max_length=20, choices=[('draft', 'Draft'), ('published', 'Published')]) @classmethod def get_drafts(cls): return cls.objects.filter(status='draft')get_queryset(): This shines in class-based views and custom managers. It’s designed for dynamic, context-aware queries or reusable query logic.- In CBVs: You can override it to tailor the
QuerySetto the current request (e.g., only show posts by the logged-in user). Other view methods likeget_object()will automatically use this customQuerySet, which helps with things like authorization (preventing users from accessing objects they shouldn’t see).
Example:class UserPostsListView(ListView): model = Post template_name = 'posts/user_posts.html' def get_queryset(self): # Return only posts authored by the current logged-in user return super().get_queryset().filter(author=self.request.user) - In custom managers: Define it to set a default filter for that manager. This lets you reuse the same query logic across your codebase without repeating filters.
Example:
Now, callingclass PublishedManager(models.Manager): def get_queryset(self): # Default to returning only published posts for this manager return super().get_queryset().filter(status='published') class Post(models.Model): # ... fields objects = models.Manager() # Keep the default manager published_objects = PublishedManager() # Custom managerPost.published_objects.all()will automatically return only published posts.
- In CBVs: You can override it to tailor the
2. Flexibility & Reusability
- Direct manager calls are simple but can lead to redundant code if you need the same filtered
QuerySetin multiple places. get_queryset()promotes reusability: In a CBV, once you override it, all related view operations use thatQuerySet. In a custom manager, you can reuse the filtered logic anywhere you call that manager.
3. Context Awareness
- Direct manager calls are static—they don’t have access to request context (like the current user) unless you pass it explicitly.
get_queryset()in CBVs has access toself.request,self.kwargs, etc., letting you build dynamic queries based on the current request.
Quick Summary
- Use model managers directly for simple, one-off queries in any context.
- Use
get_queryset()when you need dynamic, context-aware queries in class-based views, or when building custom managers with reusable default filters.
内容的提问来源于stack exchange,提问作者Now.Zero
相关产品推荐
相关产品推荐

