2017-06-04 27 views
0

我想创建简单的聊天系统,我的模型:Django的对话 - get_or_create MultipleObjectsReturned

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]) 

我想通过创建创建多对多场会话的用户连接。 当我去/ conversations/user_name get_or_create检查对话是否存在,如果没有,然后创建与当前登录的用户和用户从url的新对话。

我的问题是:

MultipleObjectsReturned at /conversations/user_name 
get() returned more than one Conversation -- it returned 2! 

我该怎么解决呢?可能它的问题与这manytomany领域..我怎么能限制users__id查找1?

+0

对话已经存在,并有对话的两个对象...这就是为什么发生错误... – zaidfazil

回答

0

get_or_create不适合这个。

此方法是原子假设使用正确,正确的数据库配置和基础数据库的正确行为。 但是,如果在数据库级别对get_or_create调用中使用的kwargs没有执行唯一性(请参阅unique或unique_together),则该方法容易出现竞争条件,从而导致多个具有相同参数的 行为同时插入。

您的表格中没有唯一的键。而且你的应用程序的本质就是无法使用唯一的密钥。与此同时,偶尔会重复聊天消息并不是什么大问题。因此,请继续创建对象,而不必检查是否存在。

还要注意,检查现有的使用选择然后做创建将是徒劳的。提到的比赛条件将会启动,你仍然会得到重复的结果。