对ForeignKey约束的测试失败

2024-05-14 20:09:54 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在Django应用程序中创建一个自定义的“upload from csv”函数,使用一个自定义的model.Manager方法来接收对csv数据应用csv.DictReader的结果。我在普通模型上的测试还可以,但是在具有ForeignKey约束的模型上却失败了。你知道吗

相关源代码如下

models.py

class PledgeManager(models.Manager):
    """Custom manager for model Pledge."""

    def from_upload(self, data):
        """Process data from Pledge upload."""
        for obj in data:
            try:
                # get the prospect & fund by natural key
                obj['prospect'] = Prospect.objects.get_by_natural_key(
                    obj['prospect'])
                obj['pledge_fund'] = Fund.objects.get_by_natural_key(
                    obj['pledge_fund'])
                obj['pledge_date'] = datetime.strptime(
                    obj['pledge_date'], r'%d/%m/%Y')
                try:
                    with transaction.atomic():
                        self.create(**obj)
                    ccall_log.debug('Created Pledge object: %s', obj)
                except IntegrityError:
                    ccall_log.error('Cannot create Pledge object: %s', obj)
            except Prospect.DoesNotExist:
                # no prospect
                ccall_log.error(
                    'Cannot create Pledge object, no Prospect: %s', obj)
            except Fund.DoesNotExist:
                # no fund
                ccall_log.error(
                    'Cannot create Pledge object, no Fund: %s', obj)
            except BaseException as exc_:
                ccall_log.exception(exc_)
                ccall_log.error(
                    'Exception encountered during processing: %s', obj)

class Pledge(models.Model):
    """Model for a Pledge."""
    objects = PledgeManager()

    pledge_amount = models.DecimalField(
        verbose_name='Pledge amount', decimal_places=2,
        max_digits=12, validators=[MinValueValidator(0)])
    pledge_fund = models.ForeignKey(Fund, on_delete=models.CASCADE)
    pledge_date = models.DateField(verbose_name='Pledge date')
    prospect = models.ForeignKey(Prospect, on_delete=models.CASCADE)

test_models.py

class TestPledge(TestCase):
    """Test cases for Pledge."""

    @classmethod
    def setUpTestData(cls):
        prospect_obj = {
            'ic': 'Test Prospect',
            ...
        }
        Prospect.objects.create(**prospect_obj)
        Fund.objects.create(name='Test Fund')
        cls.pledge_obj_add_1 = {
            'prospect': 'Test Prospect',
            'pledge_amount': '50',
            'pledge_fund': 'Test Fund',
            'pledge_date': '01/03/2017'
        }
        cls.pledge_obj_add_2 = {
            'prospect': 'Test Prospect',
            'pledge_amount': '100',
            'pledge_fund': 'Test Fund',
            'pledge_date': '01/03/2016'
        }

    def test_from_upload_add_pledge(self):
        """Test adding Pledge via custom manager's from_upload()."""
        Pledge.objects.from_upload([self.pledge_obj_add_1])
        self.assertEqual(Pledge.objects.count(), 1)

    def test_from_upload_multiple_pledge(self):
        """Test adding multiple Pledges via custom manager."""
        Pledge.objects.from_upload(
            [self.pledge_obj_add_1, self.pledge_obj_add_2])
        self.assertEqual(Pledge.objects.count(), 2)

第一次考试通过了,但第二次考试失败了。以下是测试输出:

FAIL: test_from_upload_multiple_pledge (ccall.tests.test_models.TestPledge)
Test adding multiple Pledges via custom manager.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/nhanh/phonathon/ccall/tests/test_models.py", line 273, in test_from_upload_multiple_pledge
    self.assertEqual(Pledge.objects.count(), 2)
AssertionError: 1 != 2

以及日志输出:

ERROR:ccall Cannot create Pledge object, no Prospect: {'pledge_amount': '50','prospect': <Prospect: Test Prospect>, 'pledge_date': datetime.datetime(2017, 3, 1, 0, 0), 'pledge_fund': <Fund: Test Fund>}
DEBUG:ccall Created Pledge object: {'pledge_amount': '100', 'prospect': <Prospect: Test Prospect>, 'pledge_date': datetime.datetime(2016, 3, 1, 0, 0),'pledge_fund': <Fund: Test Fund>}

我不明白的是,第一个对象抛出了一个错误,而第二个对象结果很好(它们有完全相同的ForeignKey字段)。我创建了一个测试来添加一个单一的质押对象,它不会抛出错误。我是不是碰巧触发了Django ORM的细微差别?谢谢你的帮助!你知道吗

更新:我已经包括了下面两个相关模型的实现。你知道吗

class ProspectManager(models.Manager):
    """Custom manager for model Prospect."""

    def get_by_natural_key(self, ic):
        return self.get(ic=ic)

    def from_upload(self, data):
        """Process data from Prospect upload."""
        ...

class Prospect(models.Model):
    """Model for a Prospect."""
    objects = ProspectManager()

    ic = models.CharField(max_length=15, verbose_name='IC', unique=True)
    ...

    def natural_key(self):
        return self.ic

class FundManager(models.Manager):
    """Custom manager for model Fund."""

    def get_by_natural_key(self, name):
        return self.get(name=name)

    def from_upload(self, data):
        """Process data from Fund upload."""
        ...


class Fund(models.Model):
    """Model for a Pledge Fund."""
    objects = FundManager()

    name = models.CharField(verbose_name='Fund name',
                            max_length=50, unique=True)

    def natural_key(self):
        return self.name

Tags: namefromtestselfobjobjectsmodelsdef

热门问题