diff --git a/example/example/settings.py b/example/example/settings.py index 9e33a05..8679620 100644 --- a/example/example/settings.py +++ b/example/example/settings.py @@ -73,6 +73,7 @@ INSTALLED_APPS = ( 'polymorphic', # needed if you want to use the polymorphic admin 'pexp', # this Django app is for testing and experimentation; not needed otherwise + 'orders', ) if django.VERSION >= (1, 7): diff --git a/example/orders/__init__.py b/example/orders/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/example/orders/admin.py b/example/orders/admin.py new file mode 100644 index 0000000..755c3ad --- /dev/null +++ b/example/orders/admin.py @@ -0,0 +1,43 @@ +from django.contrib import admin + +from polymorphic.admin import PolymorphicInlineSupportMixin, StackedPolymorphicInline +from .models import Order, Payment, CreditCardPayment, BankPayment, SepaPayment + + +class CreditCardPaymentInline(StackedPolymorphicInline.Child): + model = CreditCardPayment + + +class BankPaymentInline(StackedPolymorphicInline.Child): + model = BankPayment + + +class SepaPaymentInline(StackedPolymorphicInline.Child): + model = SepaPayment + + +class PaymentInline(StackedPolymorphicInline): + """ + An inline for a polymorphic model. + The actual form appearance of each row is determined by + the child inline that corresponds with the actual model type. + """ + + model = Payment + child_inlines = ( + CreditCardPaymentInline, + BankPaymentInline, + SepaPaymentInline, + ) + + +@admin.register(Order) +class OrderAdmin(PolymorphicInlineSupportMixin, admin.ModelAdmin): + """ + Admin for orders. + The inline is polymorphic. + To make sure the inlines are properly handled, + the ``PolymorphicInlineSupportMixin`` is needed to + """ + inlines = (PaymentInline,) + diff --git a/example/orders/migrations/0001_initial.py b/example/orders/migrations/0001_initial.py new file mode 100644 index 0000000..f32d754 --- /dev/null +++ b/example/orders/migrations/0001_initial.py @@ -0,0 +1,88 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('contenttypes', '0002_remove_content_type_name'), + ] + + operations = [ + migrations.CreateModel( + name='Order', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('title', models.CharField(max_length=200, verbose_name='Title')), + ], + options={ + 'ordering': ('title',), + 'verbose_name': 'Organisation', + 'verbose_name_plural': 'Organisations', + }, + ), + migrations.CreateModel( + name='Payment', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('currency', models.CharField(default=b'USD', max_length=3)), + ('amount', models.DecimalField(max_digits=10, decimal_places=2)), + ], + options={ + 'verbose_name': 'Payment', + 'verbose_name_plural': 'Payments', + }, + ), + migrations.CreateModel( + name='BankPayment', + fields=[ + ('payment_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='orders.Payment')), + ('bank_name', models.CharField(max_length=100)), + ('swift', models.CharField(max_length=20)), + ], + options={ + 'verbose_name': 'Bank Payment', + 'verbose_name_plural': 'Bank Payments', + }, + bases=('orders.payment',), + ), + migrations.CreateModel( + name='CreditCardPayment', + fields=[ + ('payment_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='orders.Payment')), + ('card_type', models.CharField(max_length=10)), + ('expiry_month', models.PositiveSmallIntegerField(choices=[(1, 'jan'), (2, 'feb'), (3, 'mar'), (4, 'apr'), (5, 'may'), (6, 'jun'), (7, 'jul'), (8, 'aug'), (9, 'sep'), (10, 'oct'), (11, 'nov'), (12, 'dec')])), + ('expiry_year', models.PositiveIntegerField()), + ], + options={ + 'verbose_name': 'Credit Card Payment', + 'verbose_name_plural': 'Credit Card Payments', + }, + bases=('orders.payment',), + ), + migrations.CreateModel( + name='SepaPayment', + fields=[ + ('payment_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='orders.Payment')), + ('iban', models.CharField(max_length=34)), + ('bic', models.CharField(max_length=11)), + ], + options={ + 'verbose_name': 'Bank Payment', + 'verbose_name_plural': 'Bank Payments', + }, + bases=('orders.payment',), + ), + migrations.AddField( + model_name='payment', + name='order', + field=models.ForeignKey(to='orders.Order'), + ), + migrations.AddField( + model_name='payment', + name='polymorphic_ctype', + field=models.ForeignKey(related_name='polymorphic_orders.payment_set+', editable=False, to='contenttypes.ContentType', null=True), + ), + ] diff --git a/example/orders/migrations/__init__.py b/example/orders/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/example/orders/models.py b/example/orders/models.py new file mode 100644 index 0000000..9691fae --- /dev/null +++ b/example/orders/models.py @@ -0,0 +1,78 @@ +from django.db import models +from django.utils.dates import MONTHS_3 +from django.utils.six import python_2_unicode_compatible +from django.utils.translation import ugettext_lazy as _ + +from polymorphic.models import PolymorphicModel + + +@python_2_unicode_compatible +class Order(models.Model): + """ + An example order that has polymorphic relations + """ + title = models.CharField(_("Title"), max_length=200) + + class Meta: + verbose_name = _("Organisation") + verbose_name_plural = _("Organisations") + ordering = ('title',) + + def __str__(self): + return self.title + + +@python_2_unicode_compatible +class Payment(PolymorphicModel): + """ + A generic payment model. + """ + order = models.ForeignKey(Order) + currency = models.CharField(default='USD', max_length=3) + amount = models.DecimalField(max_digits=10, decimal_places=2) + + class Meta: + verbose_name = _("Payment") + verbose_name_plural = _("Payments") + + def __str__(self): + return "{0} {1}".format(self.currency, self.amount) + + +class CreditCardPayment(Payment): + """ + Credit card + """ + MONTH_CHOICES = [(i, n) for i, n in sorted(MONTHS_3.items())] + + card_type = models.CharField(max_length=10) + expiry_month = models.PositiveSmallIntegerField(choices=MONTH_CHOICES) + expiry_year = models.PositiveIntegerField() + + class Meta: + verbose_name = _("Credit Card Payment") + verbose_name_plural = _("Credit Card Payments") + + +class BankPayment(Payment): + """ + Payment by bank + """ + bank_name = models.CharField(max_length=100) + swift = models.CharField(max_length=20) + + class Meta: + verbose_name = _("Bank Payment") + verbose_name_plural = _("Bank Payments") + + +class SepaPayment(Payment): + """ + Payment by SEPA (EU) + """ + iban = models.CharField(max_length=34) + bic = models.CharField(max_length=11) + + class Meta: + verbose_name = _("SEPA Payment") + verbose_name_plural = _("SEPA Payments")