Django - 实例需要具有主键值才能使用多对多关系

时间:2013-04-09 22:25:17

标签: python django

据我所知,在我访问M2M字段之前,它希望我保存。我不想保存模型。我正在使用一个名为TaskSearchCriteria的模型来搜索任务。用户可以选择将标准保存到数据库以供将来搜索。但是应该可以在不保存标准的情况下进行一次性搜索。这是我的模特。

class TaskSearchCriteria(models.Model):
    name = models.CharField(max_length=256)
    task_name = models.CharField(max_length=256, blank=True, null=True)
    project = models.ForeignKey(Project, blank=True, null=True)
    sprint = models.ForeignKey(Sprint, blank=True, null=True)
    type = models.ForeignKey(TaskType, blank=True, null=True)
    priority = models.ForeignKey(Priority, blank=True, null=True)
    status = models.ForeignKey(Status, blank=True, null=True)
    description = models.CharField(max_length=1024, blank=True, null=True)
    owner = models.ForeignKey(User)
    users = models.ManyToManyField(User, related_name='a+')

    def get_param_dict(self):
        retval = dict()
        if self.task_name != None and len(self.task_name) > 0:
            retval["name__contains"] = self.task_name
        if self.project != None:
            retval["project__id"] = self.project.pk
        if self.sprint != None:
            retval["sprint__id"] = self.sprint.pk
        if self.type != None:
            retval["type__id"] = self.type.pk
        if self.priority != None:
            retval["priority__id"] = self.priority.pk
        if self.status != None:
            retval["status__id"] = self.status.pk
        if self.description != None and len(self.description) > 0:
            retval["description__contains"] = self.description
        if self.users != None and len(self.users) > 0: #**ERROR HERE**
            ids = [user.pk for user in self.users]
            retval["users__in"] = ids
        return retval

我使用模型表单来创建模型并运行get_param_dict()方法来创建用于model.object.filter()的字典。是否可以使用m2m字段而不保存到数据库?

1 个答案:

答案 0 :(得分:3)

简而言之,不,您不能在不保存模型的情况下使用m2m字段。

这就是原因。您必须记住m2m字段的工作原理。与外键不同,m2m关系需要一个中间表,该中间表有两个指向另外两个表的外键,因此允许任何一个表(在外键中)有许多行,从而允许多对多行为。因此,为了检索模型中的users,您必须查询users中间m2m表的数据库,其中TaskSearchCriteria的外键是模型实例的主键。只有这样,您才能获得与您的模型关联的用户列表。但是如果你的模型没有保存,那是不可能的,因为你还不能查询中间表。

但是,您可以通过手动向get_param_dict方法提供用户列表来提供未保存模型实例的解决方法:

def get_param_dict(self, users=[]):
    retval = dict()

    # ...

    # retreive users from the m2m relation
    if self.pk:
        ids = [user_id[0] for user_id in self.users.all().values_list('pk')]
        if ids:
            retval["users__in"] = ids

    # when model is not saved - get user ids from the parameter
    else:
        if users:
            retval["users__in"] = users

    return retval
相关问题