Django对话 - get_or_create MultipleObjectsReturned

时间:2017-06-04 13:08:49

标签: django django-models

我想创建简单的聊天系统,我的模型:

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?

1 个答案:

答案 0 :(得分:0)

get_or_create并不适合这种情况。

  

这个方法是原子假设正确使用,正确的数据库   配置和底层数据库的正确行为。   但是,如果未在数据库级别强制执行唯一性   在get_or_create调用中使用的kwargs(请参阅unique或unique_together),   这种方法容易出现竞争条件,可能导致多重竞争   同时插入具有相同参数的行。

您的桌子上没有唯一的密钥。您的应用程序的性质使得无法使用唯一的密钥。与此同时,非常偶尔会重复的聊天消息并不重要。因此,请继续创建对象,而无需检查是否存在。

另请注意,使用select检查现有内容然后执行创建将是徒劳的。提到的竞争条件会启动,你仍然会得到重复。