Django DoesNotExist异常:同id_lbc不同User的Scraper被覆盖问题
Django 同一id_lbc关联不同User被覆盖的问题解决
嘿,这问题我之前也踩过坑!你想实现同一个id_lbc能和不同User绑定,生成独立的Scraper对象,但现在第二个对象直接覆盖第一个,核心问题出在你的模型主键设置上。
问题分析
你把id_lbc设置成了primary_key=True,而数据库的主键是全局唯一的——也就是说整个Scraper表中,id_lbc的值只能出现一次,不管关联的user是谁。所以当你给Paul创建id_lbc=1234567的对象时,数据库会认为你是要更新Nico那条已有的记录,而不是新建一条。
解决方案
分三步调整,就能完美解决:
- 移除
id_lbc的主键属性
让Django自动生成默认的自增主键id,把模型里的id_lbc字段改成普通的IntegerField:
class Scraper(models.Model): id_lbc = models.IntegerField() # 删掉primary_key=True lbc_name = models.CharField(max_length=300) lbc_url = models.URLField(max_length=300) lbc_image = models.URLField( max_length=300, default='http://****/****/nothing.jpg') lbc_price = models.IntegerField(blank=True, null=True) lbc_price_meter = models.IntegerField(blank=True, null=True) lbc_city = models.CharField(max_length=300) lbc_date = models.DateTimeField(auto_now=False) user = models.ForeignKey(User, on_delete=models.CASCADE) token_url = models.ForeignKey( Url_lbc, to_field='token', on_delete=models.CASCADE) is_emailed = models.BooleanField(default=False) customer = models.ForeignKey(Customer, on_delete=models.CASCADE) has_phone = models.BooleanField(default=False) def __str__(self): return self.lbc_name
- 添加联合唯一约束
我们需要确保同一个user+id_lbc的组合是唯一的,这样不同用户可以有相同的id_lbc,但同一个用户不能重复创建。根据你的Django版本选择:
- 如果你用的是Django 2.2及以上(推荐用这个):
class Scraper(models.Model): # 所有字段定义... class Meta: constraints = [ models.UniqueConstraint(fields=['id_lbc', 'user'], name='unique_scraper_user') ]
- 旧版Django(低于2.2):
class Scraper(models.Model): # 所有字段定义... class Meta: unique_together = ('id_lbc', 'user')
- 优化查询逻辑(可选但推荐)
你原来的try-catch逻辑没问题,但Django提供了更简洁的get_or_create方法,自动处理“查询-不存在则创建”的流程,不需要手动save:
a, created = Scraper.objects.get_or_create( id_lbc=ids, user=user, defaults={ 'lbc_name': title, 'lbc_url': url, 'lbc_image': image, 'lbc_price': price, 'lbc_date': date, 'lbc_city': city, 'lbc_price_meter': price_meter, 'token_url': token, 'customer': customer, 'has_phone': phone, } ) # created是个布尔值,True表示刚创建了新对象,False表示查询到了已存在的对象
效果验证
调整后,你就能创建Scraper1(id_lbc=1234567,user=Nico)和Scraper2(id_lbc=1234567,user=Paul)两个独立对象,不会再出现覆盖的情况,同时还能防止同一个用户重复创建相同id_lbc的记录。
内容的提问来源于stack exchange,提问作者Neeko
相关产品推荐
相关产品推荐

