我了解它要我在访问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字段而不保存到数据库?
最佳答案
简而言之,不,您必须在不保存模型的情况下使用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