求助:如何在Django中实现SQLite的auth_user与自定义输入表关联查询
Hey there! 我完全懂你现在的处境——大学项目卡关真的让人头大,别慌,咱们一步步把这个Django关联查询的问题搞定。
首先,咱们得先把模型的关系理清楚,因为Django的ORM是围绕模型关联来做的。假设你自己创建的输入表叫WaistRecord(用来存腰围数据的),你需要在这个模型里加一个外键关联Django自带的auth_user表,这样ORM才能知道两张表怎么关联。
第一步:完善模型关联
打开你的models.py,修改你的输入表模型,加上外键字段:
from django.db import models from django.contrib.auth.models import User class WaistRecord(models.Model): # 关联auth_user表,on_delete=models.CASCADE表示如果用户被删除,对应的腰围数据也跟着删 # related_name是给反向查询用的,方便从User对象找到对应的腰围记录 user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='waist_records') waist_size = models.FloatField(verbose_name="腰围") # 你的腰围字段,类型根据实际调整 created_at = models.DateTimeField(auto_now_add=True, verbose_name="记录时间") # 可选,用来记录数据录入时间 def __str__(self): return f"{self.user.username} - {self.waist_size}cm"
如果这个表之前已经创建了(也就是你已经执行过migrate),那现在需要更新数据库:
python manage.py makemigrations python manage.py migrate
注意:如果你的表已经有数据,migrate的时候可能会提示你给
user字段设置默认值,你可以暂时设为1(对应admin用户),之后再手动把数据关联到正确的用户上。
第二步:实现关联查询
现在模型关联好了,就可以用Django的ORM来实现你要的查询逻辑了,分两种常见场景:
场景1:查询单个用户的所有腰围数据
比如你要获取当前登录用户的腰围记录,可以这么写:
# 在你的views.py里 from django.contrib.auth.decorators import login_required from django.shortcuts import render from .models import WaistRecord @login_required # 确保用户登录才能访问 def user_waist_list(request): # 方法一:用反向查询(因为模型里设置了related_name='waist_records') waist_records = request.user.waist_records.all() # 方法二:正向查询,效果一样 # waist_records = WaistRecord.objects.filter(user=request.user) return render(request, 'waist_list.html', {'records': waist_records})
然后在模板waist_list.html里展示数据:
{% for record in records %} <div> <span>用户名:{{ record.user.username }}</span> <span>腰围:{{ record.waist_size }}cm</span> <span>记录时间:{{ record.created_at|date:"Y-m-d H:i" }}</span> </div> {% empty %} <p>还没有录入腰围数据哦</p> {% endfor %}
场景2:查询所有用户及其对应的腰围数据(比如每个用户最新的一条)
如果你要像SQL那样,把每个用户和他们的腰围数据关联起来(比如只取每个用户最新的一条),可以用annotate和Subquery来实现:
from django.contrib.auth.models import User from django.db.models import Max, Subquery, OuterRef from .models import WaistRecord # 获取每个有腰围数据的用户,以及他们最新的腰围记录 latest_waist = WaistRecord.objects.filter(user=OuterRef('pk')).order_by('-created_at') users_with_waist = User.objects.annotate( latest_waist_size=Subquery(latest_waist.values('waist_size')[:1]), latest_record_time=Subquery(latest_waist.values('created_at')[:1]) ).filter(latest_waist_size__isnull=False)
这样users_with_waist里的每个User对象就多了latest_waist_size和latest_record_time两个属性,直接用就行。
如果你已经有SQL语句,怎么对应到ORM?
假设你的SQL语句是这样的:
SELECT auth_user.username, waist_record.waist_size FROM auth_user JOIN waist_record ON auth_user.id = waist_record.user_id;
对应的Django ORM查询就是:
combined_data = WaistRecord.objects.select_related('user').values( 'user__username', 'waist_size', 'user__id' )
select_related('user')是用来优化查询的,避免多次查询数据库(也就是解决N+1问题),values()用来指定你要获取的字段,返回的是一个字典列表。
最后补个小提醒
如果你的旧数据还没关联到用户,你可以用Django的shell来批量处理:
python manage.py shell
然后在shell里执行:
from django.contrib.auth.models import User from .models import WaistRecord # 假设你的WaistRecord里有个username字段对应auth_user的用户名,批量关联 for record in WaistRecord.objects.all(): user = User.objects.filter(username=record.username).first() if user: record.user = user record.save()
放心,按照这个步骤来,你肯定能搞定这个关联查询的,加油!
内容的提问来源于stack exchange,提问作者J.Kidd

