简体   繁体   English

如何测试mptt模型?

[英]How to test mptt model?

There is my first steps in django testing. Django测试是我的第一步。

What I testing in current case: 我在当前情况下测试的内容:

I use MPTT in my project and when new instance created - it's parent instance obtaining new value of date field. 我在项目中使用MPTT,并在创建新实例时使用它-它的父实例获得date字段的新值。

What is a problem: 有什么问题:

after creating instances in setUp method in TestCase, TreeNode.objects.get() can't find a created instance or django don't see three or I don't know what happens, but creating new child described in TreeNode.save() in bottom not works. 在TestCase的setUp方法中创建实例后,TreeNode.objects.get()无法找到已创建的实例,或者django看不到三个实例,或者我不知道会发生什么,但是在TreeNode.save()中创建了新的子对象在底部不起作用。

For exapmple after 例如之后

TreeNode.objects.create(id=4, parent_id=1)

TreeNode.objects.get(id=4).level (autofield in mptt) equals None but must be 0 if instance have no parent or parent.level+1 if parent exists. TreeNode.objects.get(id = 4).level(在mptt中为autofield)等于None,但如果实例没有父对象,则必须为0;如果有父对象,则必须为parent.level + 1。 Sometimes TreeNode.objects.get(id=4) simply can't find the object that has been created by TreeNode.objects.create(id=4). 有时TreeNode.objects.get(id = 4)根本找不到由TreeNode.objects.create(id = 4)创建的对象。

goal: define OK method for creating a child Node that takes contract_date, id and parent as attributes and after TreeNode.objects.create running save() as is. 目标:定义确定方法,以创建一个以contract_date,id和parent为属性的子节点,并在TreeNode.objects.create之后按原样运行save()。

There are a lot of questions and I would like to get answers for part of them. 有很多问题,我想部分回答。 Main questions are: 主要问题是:

How to create TreeNode object in test (or in model, if I do anything wrong)? 如何在测试中(或在模型中,如果我做错任何事情)创建TreeNode对象? How to correctly define object as a child element of another TreeNode? 如何正确地将对象定义为另一个TreeNode的子元素?

My code: 我的代码:

Tests: 测试:

# method for creating a newbie. 
def instantiate_treenode(uid, contract_date, parent_id=None):
TreeNode.objects.create(id=uid,
                                 contract_date=contract_date,
                                 date_of_birth=date.today(),
                                 account_id=uid,
                                 identity_expire_date=date.today(),
                                 parent=TreeNode.objects.get(id=parent_id) if parent_id else None,)


class BigTestTree(TestCase):
#
#
#
#       #
#####   #
def setUp(self):
    instantiate_treenode(uid=1, contract_date=date(2014, 1, 1))

    instantiate_treenode(uid=2, contract_date=date(2014, 1, 2), parent_id=1)

    instantiate_treenode(uid=3, contract_date=date(2014, 1, 3), parent_id=2)

    instantiate_treenode(uid=4, contract_date=date(2014, 1, 4), parent_id=3)
    instantiate_treenode(uid=5, contract_date=date(2014, 1, 5), parent_id=3)

    instantiate_treenode(uid=6, contract_date=date(2014, 1, 6), parent_id=4)
    instantiate_treenode(uid=7, contract_date=date(2014, 1, 7), parent_id=4)
    instantiate_treenode(uid=8, contract_date=date(2014, 1, 8), parent_id=4)
    instantiate_treenode(uid=9, contract_date=date(2014, 1, 9), parent_id=4)

    for i in range(1, 10):
        self.assertEqual(TreeNode.objects.get(id=i).paid_income, 0)

def test_add_newbies_to_fourth_line(self):

    instantiate_treenode(uid=11, contract_date=date(2014, 1, 10), parent_id=5)

    self.assertEqual(TreeNode.objects.get(id=1).expected_income, 5 * 550)
    self.assertEqual(TreeNode.objects.get(id=2).paid_income, 5 * 1000)

    for i in range(3, 10):
        self.assertEqual(TreeNode.objects.get(id=i).paid_income, 0)

    self.assertEqual(TreeNode.objects.get(id=7).is_parent_rewarded(3), True)
    self.assertEqual(TreeNode.objects.get(id=7).is_parent_rewarded(1), False)

    instantiate_treenode(uid=10, contract_date=date(2014, 1, 10), left=13, right=14, lvl=4,
                         parent_id=4)

    self.assertEqual(TreeNode.objects.get(id=1).paid_income, 5 * 550)
    self.assertEqual(TreeNode.objects.get(id=2).paid_income, 5 * 1000)
    self.assertEqual(TreeNode.objects.get(id=3).paid_income, 5 * 3500)
    self.assertEqual(TreeNode.objects.get(id=4).paid_income, 5 * 5400)

    for i in range(5, 10):
        self.assertEqual(TreeNode.objects.get(id=i).paid_income, 0)

MPTT Model MPTT模型

class TreeNode(MPTTModel):

    account = models.OneToOneField(User, unique=True, verbose_name='Аккаунт')

    # contract
    id = models.CharField(verbose_name='ID', max_length=10, primary_key=True)
    parent = TreeForeignKey('self', verbose_name='ID пригласившего', null=True, blank=True, related_name='child')
    contract_date = models.DateField(null=False, blank=False)  

    invite_period_expire_date = models.DateField(null=True, blank=True)

    def is_parent_rewarded(self, line):
        return getattr(self, self.rewarded_parents_fields[line - 1]) if line else self

    def get_parent_of_level(self, level):
        if self.get_level() - level >= 0:
            return self.get_ancestors().get(level=self.get_level() - level)
        return None

    def get_relative_level(self, level, newbies_only):
        result = self.get_descendants().filter(level=self.get_level() + level)
        if newbies_only:
            result = filter(lambda x: not x.is_parent_rewarded(level), result)
        return result

    def pay_to_parent(self, line, five_per_period):
        parent = self.get_parent_of_level(line)
        if parent:
            from payments.models import CompanyToClientPayment

            if line == 1:
                payment = CompanyToClientPayment.objects.create(client=parent, use_date=self.contract_date,
                                                                total=prices[0][1]
                                                                if five_per_period
                                                                else prices[0][0])
            elif line == 2:
                payment = CompanyToClientPayment.objects.create(client=parent, use_date=self.contract_date,
                                                                total=prices[1][1]
                                                                if five_per_period
                                                                else prices[1][0])
            elif line == 3:
                payment = CompanyToClientPayment.objects.create(client=parent,
                                                                use_date=self.contract_date
                                                                if self.contract_date.day <= 5
                                                                else next_fifth_day_of_month(self.contract_date),
                                                                total=prices[2])
            elif line == 4:
                payment = CompanyToClientPayment.objects.create(client=parent,
                                                                use_date=self.contract_date
                                                                if self.contract_date.day <= 5
                                                                else next_fifth_day_of_month(self.contract_date),
                                                                total=prices[3])
            else:

                raise ValueError('Invalid line to pay for invite')

            #print('paymentID' + str(payment.id))
        setattr(self, self.rewarded_parents_fields[line - 1], True)
        self.save()
        parent.save()
        # print getattr(self, self.rewarded_parents_fields[line-1])

    def close_invite_period(self, expired):
        for child in filter(lambda x: x.contract_date <= self.invite_period_expire_date,
                            self.get_relative_level(level=1, newbies_only=True)):
            child.pay_to_parent(1, five_per_period=not expired)

            if child.get_parent_of_level(2):
                child.pay_to_parent(2, five_per_period=not expired)

        self.invite_period_expire_date = None
        self.save()

    def start_invite_period(self, start_date):
        if self.invite_period_expire_date:
            raise ReopeningInvitePeriodException
        self.invite_period_expire_date = start_date + invite_period
        self.save()

    def save(self, *args, **kwargs):

        if self.get_parent_of_level(1) and TreeNode.objects.filter(id=self.id).exists():
            if not self.get_parent_of_level(1).invite_period_expire_date:
                self.get_parent_of_level(1).start_invite_period(self.contract_date)
            elif self.get_parent_of_level(1).invite_period_expire_date <= self.contract_date:
                self.get_parent_of_level(1).close_invite_period(expired=True)
                self.get_parent_of_level(1).start_invite_period(self.contract_date)

            newbie_brothers = self.get_parent_of_level(1).get_relative_level(level=1, newbies_only=True)

            if len(newbie_brothers) == 5:
                self.get_parent_of_level(1).close_invite_period(expired=False)

            if self.get_parent_of_level(3):
                newbie_brothers = self.get_parent_of_level(3).get_relative_level(level=3, newbies_only=True)
                if len(newbie_brothers) == 5:
                    for newbie in newbie_brothers:
                        newbie.pay_to_parent(3, five_per_period=False)

                if self.get_parent_of_level(4):
                    newbie_brothers = self.get_parent_of_level(4).get_relative_level(level=4, newbies_only=True)
                    if len(newbie_brothers) == 5:
                        for newbie in newbie_brothers:
                            newbie.pay_to_parent(4, five_per_period=False)
        super(TreeNode, self).save(*args, **kwargs)

So, my problem was that I thought that instance.save() makes 'update' query if object already exists. 所以,我的问题是我认为如果对象已经存在, instance.save()会进行“更新”查询。 I was wrong. 我错了。 For calling 'update' query instance.update(*kwargs) method should be called. 为了调用“更新”查询,应调用instance.update(*kwargs)方法。 I'm sorry. 对不起。 I'm a teapot. 我是茶壶

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM