我想创建简单的聊天系统,我的模型:
class Conversation(models.Model):
users = models.ManyToManyField(User, related_name='users')
date = models.DateTimeField(auto_now_add=True)
class Message(models.Model):
user = models.ForeignKey(User)
conversation = models.ForeignKey(Conversation, related_name='conversation')
content = models.TextField()
date = models.DateTimeField(auto_now_add=True)
和我的观点:
def conversation(request, username):
recipient = User.objects.get(username=username)
conversation, created = Conversation.objects.get_or_create(
users__in=[recipient, request.user]
)
if created:
conversation.users.add([recipient, request.user])
我希望通过与manytomany字段创建对话来创建用户连接。 当我转到/ conversations / user_name时,get_or_create检查会话是否存在,如果不存在,则从当前登录的用户和用户创建新会话。
我的问题是:
MultipleObjectsReturned at /conversations/user_name
get() returned more than one Conversation -- it returned 2!
我该如何解决?可能是这个多领域的问题..如何限制用户___查找到1?
答案 0 :(得分:0)
get_or_create并不适合这种情况。
这个方法是原子假设正确使用,正确的数据库 配置和底层数据库的正确行为。 但是,如果未在数据库级别强制执行唯一性 在get_or_create调用中使用的kwargs(请参阅unique或unique_together), 这种方法容易出现竞争条件,可能导致多重竞争 同时插入具有相同参数的行。
您的桌子上没有唯一的密钥。您的应用程序的性质使得无法使用唯一的密钥。与此同时,非常偶尔会重复的聊天消息并不重要。因此,请继续创建对象,而无需检查是否存在。
另请注意,使用select检查现有内容然后执行创建将是徒劳的。提到的竞争条件会启动,你仍然会得到重复。