我有以下数据模型:
class PaymentGateway(models.Model):
GATEWAYS = Choices(
('stripe', _('Stripe')),
('paybox', _('PayBox')),
('generic', _('Generic')),
)
tenant = models.ForeignKey(Tenant,
related_name="payment_gateways")
name = models.CharField(
max_length=50,
verbose_name=_('Name'),
choices=GATEWAYS,
default=GATEWAYS.generic
)
class StripeGateway(PaymentGateway):
stripe_public_key = models.CharField(max_length=255)
stripe_key = models.CharField(max_length=255)
class Meta:
verbose_name = u'Stripe Gateway'
def __init__(self, *args, **kwargs):
super(StripeGateway, self).__init__(*args, **kwargs)
self.name = PaymentGateway.GATEWAYS.stripe
def __unicode__(self):
return "Stripe data for %(school_name)s" % {"school_name": self.school.name}
class EtransactionGateway(PaymentGateway):
pbx_site = models.IntegerField()
pbx_rang = models.IntegerField()
pbx_identifiant = models.IntegerField()
pbx_devise = models.IntegerField()
pbx_secret = models.CharField(max_length=255)
class Meta:
verbose_name = u'Etransaction Gateway'
def __init__(self, *args, **kwargs):
super(EtransactionGateway, self).__init__(*args, **kwargs)
self.name = PaymentGateway.GATEWAYS.paybox
def __unicode__(self):
return "E-transaction data for %(school_name)s" % {"school_name": self.school.name}
这很好,但是当我创建StripeGateway或EtransactionGateway的实例时,我可以看到另一个PaymentGateway实例。
我已尝试按[建议] [https://docs.djangoproject.com/en/dev/topics/db/models/#be-careful-with-related-name-aEDIT创建PaymentGateway摘要:我已根据评论尝试将抽象添加到父类,然后我运行与runnd相关的查询-name)但是当我这样做并运行迁移时(我已经使用当前场景运行了第一次迁移)然后我收到错误,说eTransactionGateway中的id字段与来自paymentGateway的那个冲突(抱歉,我可以&#t; t现在找到踪迹。)
现在这没关系,但我真的不喜欢PaymentGateway的实例,或者至少有backref payment_gateways返回子类,因为现在这样的事情:
tenant = Tenant.objects.get(name='tenant_1')
gws = tenant.payment_gateways.all()
返回对我没有任何价值的父实例。
有什么建议吗?
编辑:我已根据评论尝试将抽象添加到父类,然后运行
所以类现在看起来像这样:
class PaymentGateway(models.Model):
GATEWAYS = Choices(
('stripe', _('Stripe')),
('paybox', _('PayBox')),
('generic', _('Generic')),
)
tenant = models.ForeignKey(Tenant, related_name = "%(app_label)s_%(class)s_related")
name = models.CharField(
max_length=50,
verbose_name=_('Name'),
choices=GATEWAYS,
default=GATEWAYS.generic
)
class Meta:
abstract = True
class StripeGateway(PaymentGateway):
stripe_public_key = models.CharField(max_length=255)
stripe_key = models.CharField(max_length=255)
class Meta:
verbose_name = u'Stripe Gateway'
def __init__(self, *args, **kwargs):
super(StripeGateway, self).__init__(*args, **kwargs)
self.name = PaymentGateway.GATEWAYS.stripe
def __unicode__(self):
return "Stripe data for %(school_name)s" % {"school_name": self.school.name}
class EtransactionGateway(PaymentGateway):
pbx_site = models.IntegerField()
pbx_rang = models.IntegerField()
pbx_identifiant = models.IntegerField()
pbx_devise = models.IntegerField()
pbx_secret = models.CharField(max_length=255)
class Meta:
verbose_name = u'Etransaction Gateway'
def __init__(self, *args, **kwargs):
super(EtransactionGateway, self).__init__(*args, **kwargs)
self.name = PaymentGateway.GATEWAYS.paybox
def __unicode__(self):
return "E-transaction data for %(school_name)s" % {"school_name": self.school.name}
我先重置数据库
python manage.py reset_db
然后
python manage.py makemigrations
得到这样的消息:
You are trying to add a non-nullable field 'id' to etransactiongateway without a default; we can't do that (the database needs something to populate existing rows).
Please select a fix:
1) Provide a one-off default now (will be set on all existing rows)
2) Quit, and let me add a default in models.py
Select an option:
You are trying to add a non-nullable field 'tenant' to stripegateway without a default; we can't do that (the database needs something to populate existing rows).
Please select a fix:
1)现在提供一次性默认值(将在所有现有行上设置) 2)退出,让我在models.py
中添加默认值我选择1,因为我甚至没有在我的子类中使用id字段(这是由Django内部管理),对于第二条消息,我使用了一个租户的id我已经知道存在于id为1的db中
之后获取此输出:
Migrations for 'payment':
0010_auto_20170704_2305.py:
- RemovEDIT: I've tried, based on comments, to add abstract to parent class and then I rune field tenat from paymentgateway
- Remove field paymentgateway_ptr from etransactiongateway
- Remove field paymentgateway_ptr from stripegateway
- Add field id to etransactiongateway
- Add field name to etransactiongateway
- Add field tenant to etransactiongateway
- Add field id to stripegateway
- Add field name to stripegateway
- Add field tenant to stripegateway
- Delete model PaymentGateway
此迁移对我来说很奇怪,但无论如何,让我们尝试迁移,这是输出:
Applying payment.0010_auto_20170704_2305...Traceback (most recent call last):
File "manage.py", line 25, in <module>
execute_from_command_line(sys.argv)
File "/home/acme/python_envs/acme/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 353, in execute_from_command_line
utility.execute()
File "/home/acme/python_envs/acme/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 345, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/home/acme/python_envs/acme/local/lib/python2.7/site-packages/django/core/management/base.py", line 348, in run_from_argv
self.execute(*args, **cmd_options)
File "/home/acme/python_envs/acme/local/lib/python2.7/site-packages/django/core/management/base.py", line 399, in execute
output = self.handle(*args, **options)
File "/home/acme/python_envs/acme/local/lib/python2.7/site-packages/django/core/management/commands/migrate.py", line 200, in handle
executor.migrate(targets, plan, fake=fake, fake_initial=fake_initial)
File "/home/acme/python_envs/acme/local/lib/python2.7/site-packages/django/db/migrations/executor.py", line 92, in migrate
self._migrate_all_forwards(plan, full_plan, fake=fake, fake_initial=fake_initial)
File "/home/acme/python_envs/acme/local/lib/python2.7/site-packages/django/db/migrations/executor.py", line 121, in _migrate_all_forwards
state = self.apply_migration(state, migration, fake=fake, fake_initial=fake_initial)
File "/home/acme/python_envs/acme/local/lib/python2.7/site-packages/django/db/migrations/executor.py", line 198, in apply_migration
state = migration.apply(state, schema_editor)
File "/home/acme/python_envs/acme/local/lib/python2.7/site-packages/django/db/migrations/migration.py", line 115, in apply
operation.state_forwards(self.app_label, project_state)
File "/home/acme/python_envs/acme/local/lib/python2.7/site-packages/django/db/migrations/operations/fields.py", line 51, in state_forwards
state.reload_model(app_label, self.model_name_lower)
File "/home/acme/python_envs/acme/local/lib/python2.7/site-packages/django/db/migrations/state.py", line 148, in reload_model
self.apps.render_multiple(states_to_be_rendered)
File "/home/acme/python_envs/acme/local/lib/python2.7/site-packages/django/db/migrations/state.py", line 296, in render_multiple
model.render(self)
File "/home/acme/python_envs/acme/local/lib/python2.7/site-packages/django/db/migrations/state.py", line 585, in render
body,EDIT: I've tried, based on comments, to add abstract to parent class and then I run
File "/home/acme/python_envs/acme/local/lib/python2.7/site-packages/django/db/models/base.py", line 223, in __new__
'base class %r' % (field.name, name, base.__name__)
django.core.exceptions.FieldError: Local field u'id' in class 'EtransactionGateway' clashes with field of similar name from base class 'PaymentGateway'
答案 0 :(得分:0)
如果您不想在数据库中为父模型创建表,可以在模型的元类中添加abstract=True
。
class PaymentGateway(models.Model):
...
class Meta:
abstract = True