表达式只能用于更新,不能用于插入
Expressions can only be used to update, not to insert
我在尝试使用工厂男孩和 unittest.mock 模拟付款创建对象时遇到了这个问题
self = <django.db.models.sql.compiler.SQLInsertCompiler object at 0x7f5aa2913400>, field = <django.db.models.fields.CharField: card_id>
value = <MagicMock name='call_tap_api().get().resolve_expression()' id='140027256369728'>
def prepare_value(self, field, value):
"""
Prepare a value to be used in a query by resolving it if it is an
expression and otherwise calling the field's get_db_prep_save().
"""
if hasattr(value, 'resolve_expression'):
value = value.resolve_expression(self.query, allow_joins=False, for_save=True)
# Don't allow values containing Col expressions. They refer to
# existing columns on a row, but in the case of insert the row
# doesn't exist yet.
if value.contains_column_references:
raise ValueError(
'Failed to insert expression "%s" on %s. F() expressions '
> 'can only be used to update, not to insert.' % (value, field)
)
E ValueError: Failed to insert expression "<MagicMock name='call_tap_api().get().resolve_expression()' id='140027256369728'>" on tap.TapSubscription.card_id. F() expressions can only be used to update, not to insert.
/usr/local/lib/python3.6/site-packages/django/db/models/sql/compiler.py:1171: ValueError
这是我使用的导致问题的代码
@pytest.mark.django_db
@tap_vcr.use_cassette(match_on=('method', 'path'))
@override_settings(TAP_SECRET_KEY='test')
@mock.patch('core.payment.gateway.tap.utils.initiate_payment')
def test_subscription_handler(client, user):
user = UserFactory.create()
with mock.patch('core.payment.gateway.tap.utils.call_tap_api') as call_tap_api:
customer_id = create_customer(user)
card_token = tockenize_card('123456789',
'01',
'01',
'100',
user.username)
card_id = save_card(customer_id, card_token)
instance = TapSubscriptionFactory.create(user=user, card_id= card_id)
assert instance.id
create_customer() 和 tockenize_card() 和 save_card() 正在使用 call_tap_api() 用于调用支付 api 的函数,其中使用 @mock.patch 我得到的值就像 <MagicMock name='call_tap_api().get().resolve_expression()' id='140651554367360'>
我已经解决了这个问题:
@pytest.mark.django_db
@tap_vcr.use_cassette(match_on=('method', 'path'))
@override_settings(TAP_SECRET_KEY='test')
@mock.patch('core.payment.gateway.tap.utils.initiate_payment')
def test_subscription_handler(client, user):
user = UserFactory.create()
with mock.patch('core.payment.gateway.tap.utils.call_tap_api') as call_tap_api:
customer_id = user.tap_customer_id
card_token = factory.fuzzy.FuzzyInteger(1, 9999)
card_id = factory.fuzzy.FuzzyInteger(1, 9999)
instance = TapSubscriptionFactory.create(user=user, card_id= card_id)
assert instance.id
现在 customer_id 和 card_token 和 card_id 得到生成的值而不是
<MagicMock name='call_tap_api().get().resolve_expression()' id='140651554367360'>
我在尝试使用工厂男孩和 unittest.mock 模拟付款创建对象时遇到了这个问题
self = <django.db.models.sql.compiler.SQLInsertCompiler object at 0x7f5aa2913400>, field = <django.db.models.fields.CharField: card_id>
value = <MagicMock name='call_tap_api().get().resolve_expression()' id='140027256369728'>
def prepare_value(self, field, value):
"""
Prepare a value to be used in a query by resolving it if it is an
expression and otherwise calling the field's get_db_prep_save().
"""
if hasattr(value, 'resolve_expression'):
value = value.resolve_expression(self.query, allow_joins=False, for_save=True)
# Don't allow values containing Col expressions. They refer to
# existing columns on a row, but in the case of insert the row
# doesn't exist yet.
if value.contains_column_references:
raise ValueError(
'Failed to insert expression "%s" on %s. F() expressions '
> 'can only be used to update, not to insert.' % (value, field)
)
E ValueError: Failed to insert expression "<MagicMock name='call_tap_api().get().resolve_expression()' id='140027256369728'>" on tap.TapSubscription.card_id. F() expressions can only be used to update, not to insert.
/usr/local/lib/python3.6/site-packages/django/db/models/sql/compiler.py:1171: ValueError
这是我使用的导致问题的代码
@pytest.mark.django_db
@tap_vcr.use_cassette(match_on=('method', 'path'))
@override_settings(TAP_SECRET_KEY='test')
@mock.patch('core.payment.gateway.tap.utils.initiate_payment')
def test_subscription_handler(client, user):
user = UserFactory.create()
with mock.patch('core.payment.gateway.tap.utils.call_tap_api') as call_tap_api:
customer_id = create_customer(user)
card_token = tockenize_card('123456789',
'01',
'01',
'100',
user.username)
card_id = save_card(customer_id, card_token)
instance = TapSubscriptionFactory.create(user=user, card_id= card_id)
assert instance.id
create_customer() 和 tockenize_card() 和 save_card() 正在使用 call_tap_api() 用于调用支付 api 的函数,其中使用 @mock.patch 我得到的值就像 <MagicMock name='call_tap_api().get().resolve_expression()' id='140651554367360'>
我已经解决了这个问题:
@pytest.mark.django_db
@tap_vcr.use_cassette(match_on=('method', 'path'))
@override_settings(TAP_SECRET_KEY='test')
@mock.patch('core.payment.gateway.tap.utils.initiate_payment')
def test_subscription_handler(client, user):
user = UserFactory.create()
with mock.patch('core.payment.gateway.tap.utils.call_tap_api') as call_tap_api:
customer_id = user.tap_customer_id
card_token = factory.fuzzy.FuzzyInteger(1, 9999)
card_id = factory.fuzzy.FuzzyInteger(1, 9999)
instance = TapSubscriptionFactory.create(user=user, card_id= card_id)
assert instance.id
现在 customer_id 和 card_token 和 card_id 得到生成的值而不是
<MagicMock name='call_tap_api().get().resolve_expression()' id='140651554367360'>