Django中外键自动生成_id后缀字段的原因及查询集使用疑问
_id Suffix Field for Foreign Keys, and Which One to Use in Querysets? Hey there! Let's unpack this question step by step—this is a super common point of confusion when starting out with Django models, so you're not alone.
First: Why the user_id Field Exists
When you define a foreign key like user = models.ForeignKey(User, ...) in your Post model, Django is doing two key things under the hood:
- It creates a model-level field (
user) that acts as an object reference. This lets you directly work with the associatedUserinstance—for example, you can dopost.user.usernameto get the user's username without writing extra queries. - It creates a database-level field (
user_id) that stores the actual integer value of the linked User's primary key (usuallyid). Databases don't understand "object references"—they just store raw values, so this is the field that gets saved to your database table.
Django hides the user_id field by default in most model operations, but it's always there handling the low-level storage work.
Which Field to Use in Your Queryset
The short answer: it depends on what you're trying to do, but in most cases, you'll use the model-level field (user) rather than user_id. Here's a breakdown of common scenarios:
1. Filtering by the linked object itself
If you have a User instance (like self.request.user in a class-based view), you can filter directly using the user field. Django will automatically translate this to a user_id lookup in the database:
def get_queryset(self): # Get all posts belonging to the current user return Post.objects.filter(user=self.request.user)
2. Filtering by the raw primary key value
If you only have the user's ID (a number like 5), you can use user_id directly for a more explicit lookup. This works exactly the same as the example above, but skips resolving the User instance:
def get_queryset(self): # Get all posts where the linked user has ID 5 return Post.objects.filter(user_id=5)
3. Filtering by a property of the linked object
When you need to filter based on a field in the User model (like username or is_active status), use Django's double-underscore syntax with the model-level user field. Django will handle joining the two tables for you:
def get_queryset(self): # Get all posts from active users return Post.objects.filter(user__is_active=True)
4. Accessing the linked object's data
When you want to retrieve data from the linked User (like displaying the username in a template or serializer), always use the user field. You can optimize this with select_related to avoid extra database queries:
# In a view or serializer for post in queryset: print(post.user.username) # Directly access the User's username
Quick Summary
- Use
user(the model-level foreign key field) when working with the linked User object, filtering by its properties, or accessing its data. - Use
user_idonly when you need to work directly with the raw primary key value of the linked user.
Django is designed to make object-oriented database work easy, so leaning on the model-level user field will cover 90% of your use cases.
内容的提问来源于stack exchange,提问作者WISAM

