Django ORM查询外部数据库hotel_reviews表时报未知列id错误
问题根源
Django ORM 有强制规则:每个模型必须存在一个主键字段。如果模型没有显式标记任何字段为primary_key=True,Django会自动生成一个隐式的id自增主键,对应数据库表的id列。
你的
HotelInfo表能正常查询,是因为显式指定了hotel_id为主键,Django不会额外生成id字段;而HotelReviews模型没有任何字段标记为主键,触发了自动生成id的逻辑,查询时就会去拉取数据库里不存在的hotel_reviews.id列,抛出1054错误。
另外你的HotelReviews模型还有笔误:重复定义了两次tag_n4字段,会导致字段映射错误,需要删掉重复行。
解决方案
先确认hotel_reviews表的现有唯一非空字段,根据实际结构选择对应修改:
情况1:表中UUID列本身就是唯一非空的主键
直接给uuid字段加primary_key=True,移除多余的blank=True, null=True(主键本身要求非空唯一),同时删掉重复的tag_n4行,修改后的模型示例:
class HotelReviews(models.Model): uuid = models.CharField(db_column='UUID', primary_key=True, max_length=36) hotel_id = models.CharField(max_length=32, blank=True, null=True) review_title = models.TextField(blank=True, null=True) review_url = models.TextField(blank=True, null=True) review_score = models.DecimalField(max_digits=5, decimal_places=2, blank=True, null=True) review_date = models.DateField(blank=True, null=True) reviewer_name = models.TextField(blank=True, null=True) hash_reviewer_name = models.CharField(max_length=200, blank=True, null=True) reviewer_location = models.CharField(max_length=100, blank=True, null=True) posting_conts = models.IntegerField(blank=True, null=True) positive_content = models.TextField(blank=True, null=True) negative_content = models.TextField(blank=True, null=True) tag_n1 = models.TextField(blank=True, null=True) tag_n2 = models.TextField(blank=True, null=True) tag_n3 = models.TextField(blank=True, null=True) tag_n4 = models.TextField(blank=True, null=True) tag_n5 = models.TextField(blank=True, null=True) staydate = models.TextField(blank=True, null=True) class Meta: managed = False db_table = 'hotel_reviews' verbose_name_plural = "Reviews"
情况2:表中没有单列唯一主键,需要用联合字段做主键
如果是多字段联合唯一(比如uuid + hotel_id + review_date的组合唯一),Django 5.0及以上版本支持原生复合主键,可在Meta类中定义:
from django.db.models import CompositeKey class HotelReviews(models.Model): # 其余字段和上面一致,不需要单独设置单个主键 class Meta: managed = False db_table = 'hotel_reviews' verbose_name_plural = "Reviews" # 替换成你实际的联合唯一字段组合 primary_key = CompositeKey('uuid', 'hotel_id', 'review_date')
如果是Django 5.0以下的旧版本,不支持原生复合主键,可选择一个尽量唯一的字段(比如uuid,即使数据库层面没设为主键,只要值唯一),显式标记为primary_key=True即可避免Django自动生成id字段。
注意事项
- 因为你的模型设置了
managed = False,Django不会修改数据库表结构,所有修改仅适配现有表结构,不会对原有数据库造成影响。 - 修改完成后重启Django服务再测试查询即可。
内容的提问来源于stack exchange,提问作者Marcos
相关产品推荐
相关产品推荐

