OdooV8 - 为什么在 'res_partner' 中创建记录需要这么长时间

OdooV8 - Why does it take so long to create a record in 'res_partner' in my case

我最近开始使用odoo8进行开发,但遇到了一个问题。

我的问题是我有两个 class:'helpdesk''res_partner'我不知道为什么当我在 'res_partner' 中创建新记录时,我的代码会卡住很长时间,但是当我评论这段代码(如下)时,我的代码运行良好。

self.env['res.partner'].create({
    'name': nameFmt,
    'firstname': self.firstNameOfUser.strip().lower().title(),
    'lastname': self.lastNameOfUser.strip().upper(),
    'birthdate': newDateFmt,
    'birth_place': self.pBirthOfUser,
    'is_company': False
})

'helpdesk' class 有几个字段和方法来获取信息,并根据用户输入计算它们。一旦信息计算出来,我就创建了我的记录,这是一个新的合作伙伴。

我是如何尝试解决我的问题的:

有关更多信息,这是我的整个方法定义:

@api.one
def addPartnerInDB(self):
    if (not self.firstNameOfUser or
        not self.lastNameOfUser or
        not self.dobOfUser or
        not self.pBirthOfUser):
        raise ValidationError(u"Tous les champs sp\u00E9cifi\u00E9s pour "
                              u"cette demande doivent \u00EAtre remplis !")
    # Avoid concurrent drop-down
    self.dropDownList1 = False
    self.dropDownList3 = False
    # Get every partners
    listOfPartners = self.env['res.partner'].search(
        [
            ('is_company', '=', False)
        ]
    )
    # Avoid useless compute for each iteration
    newDateFmt = u"".join(datetime.datetime\
                          .strptime(str(self.dobOfUser), "%Y-%m-%d")\
                          .strftime("%d/%m/%Y"))
    newFNameFmt = self.firstNameOfUser.strip().replace(" ", "-").lower()
    newLNameFmt = self.lastNameOfUser.strip().replace(" ", "-").lower()
    newBPFmt = self.pBirthOfUser.strip().replace(" ", "-").lower()
    matchedPartners = []
    # Fetch partner specified by the user
    for p in listOfPartners:
        if (newFNameFmt == p.firstname.strip().replace(" ", "-").lower() and
            newLNameFmt == p.lastname.strip().replace(" ", "-").lower()):
            matchedPartners.append(p)
    partnerAlreadyExist = False
    # If the list is not empty, then the fetch is enhance
    if (matchedPartners):
        for m in matchedPartners:
            partnerDOB = False
            partnerBP = False
            if (not isinstance(m.birthdate, bool)):
                if (newDateFmt == m.birthdate):
                    partnerDOB = True
            if (not isinstance(m.birth_place, bool)):
                if ((newBPFmt
                     == m.birth_place.strip().replace(" ", "-").lower())):
                    partnerBP = True
            # If one of them it's true, the user already exist
            if (partnerDOB or partnerBP):
                partnerAlreadyExist = True
                # Avoid useless iteration
                break
    # If the user specified doesn't exist he's created
    if (not partnerAlreadyExist):
        # Encode the string to avoid UnicodeError and further string errors
        nameFmt = (self.lastNameOfUser.strip().upper(),
                   + u" "
                   + self.firstNameOfUser.strip().lower().title())
        self.env['res.partner'].create(
            {
                'name': nameFmt,
                'firstname': self.firstNameOfUser.strip().lower().title(),
                'lastname': self.lastNameOfUser.strip().upper(),
                'birthdate': newDateFmt,
                'birth_place': self.pBirthOfUser,
                'is_company': False
            }
        )
    else:
        raise ValidationError(u"L'utilisateur renseign\u00E9 "
                              u"existe d\u00E9j\u00E0 !")

编辑

在多次尝试使用 pdb 调试我的代码后,我注意到在比较名字和姓氏时 for 语句中出现了问题:

for p in listOfPartners:
    if (newFNameFmt == p.firstname.strip().replace(" ", "-").lower()
            and newLNameFmt == p.lastname.strip().replace(" ", "-").lower()):
       # Append element

确实,在 for 语句的每次启动时,pdb 都会阻塞(2/3 秒),然后才会将手还给我。

例如:

(pdb) ->if (newFNameFmt == p.firstname.strip().replace(" ", "-").lower() and # stuck 2-3 seconds (pdb) -> newLNameFmt == p.lastname.strip().replace(" ", "-").lower()):

这种行为在 for 语句的第一次迭代中持续,在这个迭代次数之后,这种行为不再被用于其余的迭代。一旦我到达 create 语句(使用 pdb),创建记录就奇迹般地解锁并且代码工作。

我仍然不知道为什么会出现这个问题,我仍然不知道如何解决它。

你遇到这个问题是因为你可能比较了两种不同的类型!在您的情况下,您可能会尝试比较 res_partner 对象和字符串类型或其他类型!那应该是 res.partner(2973,).id 或 res.partner(2973,).name ....

我找到了问题的答案,我想知道问题出在哪里。

Where was my problem

所以问题来自我的第一个 for 语句,它是:

   listOfPartners = self.env['res.partner'].search(
        [
            ('is_company', '=', False)
        ]
    )

    for p in listOfPartners:
        if (newFNameFmt == p.firstname.strip().replace(" ", "-").lower()
             and newLNameFmt == p.lastname.strip().replace(" ", "-").lower()):
            matchedPartners.append(p)

从理论上讲,forsearch 语句不会有任何问题,因为它们做了我想做的事情。但问题是,程序在此 for 中执行的每次迭代都是 'n' 发送到 PostgresSQL 服务器的查询(其中 n 对应于 p 的次数在每次迭代中使用。在我的例子中 n = 2)。这个问题迅速升级,因为 search 返回给我大约一千个合作伙伴(由 res.partner 中保存的与 search 查询匹配的每条记录的 id 表示)。所以在 for 这对应于我在很短的时间内向 PostgreSQL 服务器发送了数千个查询,而且这个服务器似乎无法在很短的时间内处理这么多的请求。

所以问题不在于他的代码,而是我给他的行为。该行为的结果为 PostgreSQL 提供了另一种行为,用于我将通过 Odoo 提供的进一步查询,例如 create.

How I solved it

我的解决方案是使用 psycopg2 模块。该模块允许与 postgreSQL 服务器通信。在我的例子中,两者之间的主要区别是 Odoo 与 PostgreSQL 服务器保持通信,即使我使用 search 只获取我想要的值。虽然 psycopg2 给了我一个 list(属于 tuples),它只包含 "real" 个值,而不是像 Odoo 给我的 search 那样的 id

再一次,我不知道我选择的解决方案是否是最好的,或者问题是否像我上面所说的那样来自那里,但这个解决方案对我来说效果很好,我希望它能帮助其他陷入困境的用户相同行为的问题。