无外键时Django ORM关联查询:关联Postreply与Userinfo
嘿,这个需求用Django ORM就能轻松搞定,我给你两种可行的方案,看哪种更适合你的场景:
方案1:给模型添加显式外键(推荐)
你的现有模型里Postreply和Userinfo之间没有定义外键关联,虽然managed=False(不会让Django自动管理表结构),但我们可以手动加上外键,让ORM能更优雅地处理跨表查询:
修改Postreply模型,添加到Userinfo的外键:
class Postreply(models.Model): replyuid = models.BigAutoField(db_column='ReplyUID', primary_key=True) postuid = models.BigIntegerField(db_column='PostUID') # 新增外键关联Userinfo,因为是已存在的表,所以用DO_NOTHING避免删除关联时出错 useruid = models.ForeignKey( Userinfo, on_delete=models.DO_NOTHING, db_column='UserUID', related_name='replies' ) content = models.TextField(db_column='Content') registerdate = models.DateTimeField( db_column='RegisterDate', default=datetime.datetime.today().strftime("%Y-%m-%dT%H:%M:%S")) class Meta: managed = False db_table = 'postreply'
之后就可以用select_related来一次性拉取关联的用户数据(避免N+1查询问题),代码如下:
# 过滤postuid=3的回复,并关联获取对应用户信息 target_replies = Postreply.objects.filter(postuid=3).select_related('useruid') # 遍历结果输出你要的格式 for reply in target_replies: print(f"postuid = {reply.postuid} useruid ={reply.useruid.useruid} replyuid= {reply.replyuid} username = '{reply.useruid.username}'")
这样就能得到你期望的结果,而且代码可读性和性能都更好。
方案2:不修改模型,直接跨表查询
如果不想改动现有模型,也可以直接用ORM的跨表查询或者原生SQL来实现:
用ORM跨表查询
from django.db.models import F # 通过values指定要获取的字段,同时关联Userinfo的username reply_data = Postreply.objects.filter(postuid=3).values( 'postuid', 'useruid', 'replyuid', username=F('userinfo__username') ).select_related('userinfo') # 遍历输出 for item in reply_data: print(f"postuid = {item['postuid']} useruid ={item['useruid']} replyuid= {item['replyuid']} username = '{item['username']}'")
用原生SQL(如果ORM关联有问题时用)
# 直接写SQL语句做关联查询 reply_data = Postreply.objects.raw(""" SELECT pr.PostUID AS postuid, pr.UserUID AS useruid, pr.ReplyUID AS replyuid, ui.UserName AS username FROM postreply pr INNER JOIN userinfo ui ON pr.UserUID = ui.UserUID WHERE pr.PostUID = %s """, [3]) # 遍历输出 for item in reply_data: print(f"postuid = {item.postuid} useruid ={item.useruid} replyuid= {item.replyuid} username = '{item.username}'")
小提示
- 优先选方案1,显式的外键关联能让你的代码更清晰,后续维护也更方便,而且不会改变你的数据库结构(因为
managed=False)。 select_related是用来优化一对一/多对一关联查询的,能把两个表的查询合并成一次JOIN操作,比多次查询性能好很多。
内容的提问来源于stack exchange,提问作者Adam
相关产品推荐
相关产品推荐

