Django技术疑问:get()方法是否为惰性执行?以及Django是否知晓各模型的实例数量?
Great questions—let's tackle them one by one to clear up the confusion!
1. Why does Model.objects.get(pk=1) throw DoesNotExist immediately, even when just assigning to a variable?
You're totally right that regular Django QuerySets are lazy—methods like filter() or exclude() just build up a query plan without hitting the database until the QuerySet is evaluated (like looping over it, converting to a list, or printing it). But get() is different: it's not designed to return a QuerySet. Instead, its job is to fetch a single matching instance right away.
Under the hood, get() works by:
- Creating a filtered QuerySet (like
Model.objects.filter(pk=1)) - Immediately evaluating that QuerySet to check for results
- If no matches are found, it raises the
DoesNotExistexception you saw - If multiple matches exist, it raises
MultipleObjectsReturnedinstead
Since get() has to return an actual model instance (not just a query plan), it can't be lazy. The database query happens the moment you call get()—even if you're just assigning the result to a variable. That's why you see the exception immediately when the record doesn't exist.
2. Does Django automatically know the number of instances for each model?
Short answer: No, Django doesn't track instance counts in real-time or keep a cached total by default. But there are easy, efficient ways to get this number when you need it:
- Use
Model.objects.count(): This executes a lightweightSELECT COUNT(*)SQL query directly against the database, which is much faster than loading all instances into memory (likelen(Model.objects.all())would do). It's the recommended way to get the total number of instances for a model. - For frequent count checks (and if your data doesn't change constantly): You can cache the count using Django's built-in caching framework, or add a custom counter field to your model (e.g.,
instance_count). Then use Django signals (post_saveandpost_delete) to increment/decrement this field whenever an instance is created or deleted. This lets you avoid hitting the database for a count every time.
内容的提问来源于stack exchange,提问作者Omar AlHadidi

