Reformat all files with isort and black
This commit is contained in:
+62
-65
@@ -10,105 +10,102 @@ MANAGERS = ADMINS
|
||||
PROJECT_ROOT = os.path.dirname(os.path.dirname(__file__))
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': os.path.join(PROJECT_ROOT, 'example.db'),
|
||||
"default": {
|
||||
"ENGINE": "django.db.backends.sqlite3",
|
||||
"NAME": os.path.join(PROJECT_ROOT, "example.db"),
|
||||
}
|
||||
}
|
||||
|
||||
SITE_ID = 1
|
||||
|
||||
# Make this unique, and don't share it with anybody.
|
||||
SECRET_KEY = '5$f%)&a4tc*bg(79+ku!7o$kri-duw99@hq_)va^_kaw9*l)!7'
|
||||
SECRET_KEY = "5$f%)&a4tc*bg(79+ku!7o$kri-duw99@hq_)va^_kaw9*l)!7"
|
||||
|
||||
|
||||
# Language
|
||||
# TIME_ZONE = 'America/Chicago'
|
||||
LANGUAGE_CODE = 'en-us'
|
||||
LANGUAGE_CODE = "en-us"
|
||||
USE_I18N = True
|
||||
USE_L10N = True
|
||||
USE_TZ = True
|
||||
|
||||
# Paths
|
||||
MEDIA_ROOT = ''
|
||||
MEDIA_URL = '/media/'
|
||||
STATIC_ROOT = ''
|
||||
STATIC_URL = '/static/'
|
||||
MEDIA_ROOT = ""
|
||||
MEDIA_URL = "/media/"
|
||||
STATIC_ROOT = ""
|
||||
STATIC_URL = "/static/"
|
||||
|
||||
# Apps
|
||||
STATICFILES_FINDERS = (
|
||||
'django.contrib.staticfiles.finders.FileSystemFinder',
|
||||
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
|
||||
"django.contrib.staticfiles.finders.FileSystemFinder",
|
||||
"django.contrib.staticfiles.finders.AppDirectoriesFinder",
|
||||
)
|
||||
|
||||
MIDDLEWARE = (
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
"django.middleware.common.CommonMiddleware",
|
||||
"django.contrib.sessions.middleware.SessionMiddleware",
|
||||
"django.middleware.csrf.CsrfViewMiddleware",
|
||||
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
||||
"django.contrib.messages.middleware.MessageMiddleware",
|
||||
)
|
||||
|
||||
TEMPLATES=[{
|
||||
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
||||
"DIRS": (),
|
||||
"OPTIONS": {
|
||||
"loaders": (
|
||||
"django.template.loaders.filesystem.Loader",
|
||||
"django.template.loaders.app_directories.Loader",
|
||||
),
|
||||
"context_processors": (
|
||||
"django.template.context_processors.debug",
|
||||
"django.template.context_processors.i18n",
|
||||
"django.template.context_processors.media",
|
||||
"django.template.context_processors.request",
|
||||
"django.template.context_processors.static",
|
||||
"django.contrib.messages.context_processors.messages",
|
||||
"django.contrib.auth.context_processors.auth",
|
||||
),
|
||||
},
|
||||
}]
|
||||
TEMPLATES = [
|
||||
{
|
||||
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
||||
"DIRS": (),
|
||||
"OPTIONS": {
|
||||
"loaders": (
|
||||
"django.template.loaders.filesystem.Loader",
|
||||
"django.template.loaders.app_directories.Loader",
|
||||
),
|
||||
"context_processors": (
|
||||
"django.template.context_processors.debug",
|
||||
"django.template.context_processors.i18n",
|
||||
"django.template.context_processors.media",
|
||||
"django.template.context_processors.request",
|
||||
"django.template.context_processors.static",
|
||||
"django.contrib.messages.context_processors.messages",
|
||||
"django.contrib.auth.context_processors.auth",
|
||||
),
|
||||
},
|
||||
}
|
||||
]
|
||||
|
||||
ROOT_URLCONF = 'example.urls'
|
||||
ROOT_URLCONF = "example.urls"
|
||||
|
||||
WSGI_APPLICATION = 'example.wsgi.application'
|
||||
WSGI_APPLICATION = "example.wsgi.application"
|
||||
|
||||
INSTALLED_APPS = (
|
||||
'django.contrib.auth',
|
||||
'django.contrib.admin',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
|
||||
'polymorphic', # needed if you want to use the polymorphic admin
|
||||
'pexp', # this Django app is for testing and experimentation; not needed otherwise
|
||||
'orders',
|
||||
"django.contrib.auth",
|
||||
"django.contrib.admin",
|
||||
"django.contrib.contenttypes",
|
||||
"django.contrib.sessions",
|
||||
"django.contrib.messages",
|
||||
"django.contrib.staticfiles",
|
||||
"polymorphic", # needed if you want to use the polymorphic admin
|
||||
"pexp", # this Django app is for testing and experimentation; not needed otherwise
|
||||
"orders",
|
||||
)
|
||||
|
||||
TEST_RUNNER = 'django.test.runner.DiscoverRunner' # silence system checks
|
||||
TEST_RUNNER = "django.test.runner.DiscoverRunner" # silence system checks
|
||||
|
||||
# Logging configuration
|
||||
LOGGING = {
|
||||
'version': 1,
|
||||
'disable_existing_loggers': False,
|
||||
'filters': {
|
||||
'require_debug_false': {
|
||||
'()': 'django.utils.log.RequireDebugFalse'
|
||||
"version": 1,
|
||||
"disable_existing_loggers": False,
|
||||
"filters": {"require_debug_false": {"()": "django.utils.log.RequireDebugFalse"}},
|
||||
"handlers": {
|
||||
"mail_admins": {
|
||||
"level": "ERROR",
|
||||
"filters": ["require_debug_false"],
|
||||
"class": "django.utils.log.AdminEmailHandler",
|
||||
}
|
||||
},
|
||||
'handlers': {
|
||||
'mail_admins': {
|
||||
'level': 'ERROR',
|
||||
'filters': ['require_debug_false'],
|
||||
'class': 'django.utils.log.AdminEmailHandler'
|
||||
"loggers": {
|
||||
"django.request": {
|
||||
"handlers": ["mail_admins"],
|
||||
"level": "ERROR",
|
||||
"propagate": True,
|
||||
}
|
||||
},
|
||||
'loggers': {
|
||||
'django.request': {
|
||||
'handlers': ['mail_admins'],
|
||||
'level': 'ERROR',
|
||||
'propagate': True,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,6 @@ from django.views.generic import RedirectView
|
||||
admin.autodiscover()
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^admin/', admin.site.urls),
|
||||
url(r'^$', RedirectView.as_view(url=reverse_lazy('admin:index'), permanent=False)),
|
||||
url(r"^admin/", admin.site.urls),
|
||||
url(r"^$", RedirectView.as_view(url=reverse_lazy("admin:index"), permanent=False)),
|
||||
]
|
||||
|
||||
@@ -15,12 +15,14 @@ framework.
|
||||
"""
|
||||
import os
|
||||
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "example.settings")
|
||||
|
||||
# This application object is used by any WSGI server configured to use this
|
||||
# file. This includes Django's development server, if the WSGI_APPLICATION
|
||||
# setting points here.
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "example.settings")
|
||||
|
||||
|
||||
application = get_wsgi_application()
|
||||
|
||||
# Apply WSGI middleware here.
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
from django.contrib import admin
|
||||
|
||||
from polymorphic.admin import PolymorphicInlineSupportMixin, StackedPolymorphicInline
|
||||
from .models import Order, Payment, CreditCardPayment, BankPayment, SepaPayment
|
||||
|
||||
from .models import BankPayment, CreditCardPayment, Order, Payment, SepaPayment
|
||||
|
||||
|
||||
class CreditCardPaymentInline(StackedPolymorphicInline.Child):
|
||||
@@ -24,11 +25,7 @@ class PaymentInline(StackedPolymorphicInline):
|
||||
"""
|
||||
|
||||
model = Payment
|
||||
child_inlines = (
|
||||
CreditCardPaymentInline,
|
||||
BankPaymentInline,
|
||||
SepaPaymentInline,
|
||||
)
|
||||
child_inlines = (CreditCardPaymentInline, BankPaymentInline, SepaPaymentInline)
|
||||
|
||||
|
||||
@admin.register(Order)
|
||||
@@ -39,5 +36,5 @@ class OrderAdmin(PolymorphicInlineSupportMixin, admin.ModelAdmin):
|
||||
To make sure the inlines are properly handled,
|
||||
the ``PolymorphicInlineSupportMixin`` is needed to
|
||||
"""
|
||||
inlines = (PaymentInline,)
|
||||
|
||||
inlines = (PaymentInline,)
|
||||
|
||||
@@ -6,83 +6,148 @@ from django.db import migrations, models
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('contenttypes', '0002_remove_content_type_name'),
|
||||
]
|
||||
dependencies = [("contenttypes", "0002_remove_content_type_name")]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Order',
|
||||
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')),
|
||||
(
|
||||
"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',
|
||||
"ordering": ("title",),
|
||||
"verbose_name": "Organisation",
|
||||
"verbose_name_plural": "Organisations",
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Payment',
|
||||
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)),
|
||||
(
|
||||
"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',
|
||||
},
|
||||
options={"verbose_name": "Payment", "verbose_name_plural": "Payments"},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='BankPayment',
|
||||
name="BankPayment",
|
||||
fields=[
|
||||
('payment_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, on_delete=models.CASCADE, to='orders.Payment')),
|
||||
('bank_name', models.CharField(max_length=100)),
|
||||
('swift', models.CharField(max_length=20)),
|
||||
(
|
||||
"payment_ptr",
|
||||
models.OneToOneField(
|
||||
parent_link=True,
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
on_delete=models.CASCADE,
|
||||
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',
|
||||
"verbose_name": "Bank Payment",
|
||||
"verbose_name_plural": "Bank Payments",
|
||||
},
|
||||
bases=('orders.payment',),
|
||||
bases=("orders.payment",),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='CreditCardPayment',
|
||||
name="CreditCardPayment",
|
||||
fields=[
|
||||
('payment_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, on_delete=models.CASCADE, 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()),
|
||||
(
|
||||
"payment_ptr",
|
||||
models.OneToOneField(
|
||||
parent_link=True,
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
on_delete=models.CASCADE,
|
||||
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',
|
||||
"verbose_name": "Credit Card Payment",
|
||||
"verbose_name_plural": "Credit Card Payments",
|
||||
},
|
||||
bases=('orders.payment',),
|
||||
bases=("orders.payment",),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='SepaPayment',
|
||||
name="SepaPayment",
|
||||
fields=[
|
||||
('payment_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, on_delete=models.CASCADE, to='orders.Payment')),
|
||||
('iban', models.CharField(max_length=34)),
|
||||
('bic', models.CharField(max_length=11)),
|
||||
(
|
||||
"payment_ptr",
|
||||
models.OneToOneField(
|
||||
parent_link=True,
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
on_delete=models.CASCADE,
|
||||
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',
|
||||
"verbose_name": "Bank Payment",
|
||||
"verbose_name_plural": "Bank Payments",
|
||||
},
|
||||
bases=('orders.payment',),
|
||||
bases=("orders.payment",),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='payment',
|
||||
name='order',
|
||||
field=models.ForeignKey(to='orders.Order', on_delete=models.CASCADE),
|
||||
model_name="payment",
|
||||
name="order",
|
||||
field=models.ForeignKey(to="orders.Order", on_delete=models.CASCADE),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='payment',
|
||||
name='polymorphic_ctype',
|
||||
field=models.ForeignKey(related_name='polymorphic_orders.payment_set+', editable=False, on_delete=models.CASCADE, to='contenttypes.ContentType', null=True),
|
||||
model_name="payment",
|
||||
name="polymorphic_ctype",
|
||||
field=models.ForeignKey(
|
||||
related_name="polymorphic_orders.payment_set+",
|
||||
editable=False,
|
||||
on_delete=models.CASCADE,
|
||||
to="contenttypes.ContentType",
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
]
|
||||
|
||||
@@ -11,12 +11,13 @@ 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',)
|
||||
ordering = ("title",)
|
||||
|
||||
def __str__(self):
|
||||
return self.title
|
||||
@@ -27,8 +28,9 @@ class Payment(PolymorphicModel):
|
||||
"""
|
||||
A generic payment model.
|
||||
"""
|
||||
|
||||
order = models.ForeignKey(Order, on_delete=models.CASCADE)
|
||||
currency = models.CharField(default='USD', max_length=3)
|
||||
currency = models.CharField(default="USD", max_length=3)
|
||||
amount = models.DecimalField(max_digits=10, decimal_places=2)
|
||||
|
||||
class Meta:
|
||||
@@ -43,6 +45,7 @@ class CreditCardPayment(Payment):
|
||||
"""
|
||||
Credit card
|
||||
"""
|
||||
|
||||
MONTH_CHOICES = [(i, n) for i, n in sorted(MONTHS_3.items())]
|
||||
|
||||
card_type = models.CharField(max_length=10)
|
||||
@@ -58,6 +61,7 @@ class BankPayment(Payment):
|
||||
"""
|
||||
Payment by bank
|
||||
"""
|
||||
|
||||
bank_name = models.CharField(max_length=100)
|
||||
swift = models.CharField(max_length=20)
|
||||
|
||||
@@ -70,6 +74,7 @@ class SepaPayment(Payment):
|
||||
"""
|
||||
Payment by SEPA (EU)
|
||||
"""
|
||||
|
||||
iban = models.CharField(max_length=34)
|
||||
bic = models.CharField(max_length=11)
|
||||
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
from django.contrib import admin
|
||||
from polymorphic.admin import PolymorphicParentModelAdmin, PolymorphicChildModelAdmin, PolymorphicChildModelFilter
|
||||
|
||||
from pexp.models import *
|
||||
from polymorphic.admin import (
|
||||
PolymorphicChildModelAdmin,
|
||||
PolymorphicChildModelFilter,
|
||||
PolymorphicParentModelAdmin,
|
||||
)
|
||||
|
||||
|
||||
class ProjectAdmin(PolymorphicParentModelAdmin):
|
||||
@@ -14,11 +19,7 @@ class ProjectChildAdmin(PolymorphicChildModelAdmin):
|
||||
|
||||
# On purpose, only have the shared fields here.
|
||||
# The fields of the derived model should still be displayed.
|
||||
base_fieldsets = (
|
||||
("Base fields", {
|
||||
'fields': ('topic',)
|
||||
}),
|
||||
)
|
||||
base_fieldsets = (("Base fields", {"fields": ("topic",)}),)
|
||||
|
||||
|
||||
admin.site.register(Project, ProjectAdmin)
|
||||
|
||||
@@ -7,12 +7,12 @@ import sys
|
||||
import time
|
||||
from pprint import pprint
|
||||
from random import Random
|
||||
|
||||
from django.core.management import BaseCommand
|
||||
from django.db import connection
|
||||
|
||||
from pexp.models import *
|
||||
|
||||
|
||||
rnd = Random()
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ def show_queries():
|
||||
connection.queries = []
|
||||
|
||||
|
||||
def print_timing(func, message='', iterations=1):
|
||||
def print_timing(func, message="", iterations=1):
|
||||
def wrapper(*arg):
|
||||
results = []
|
||||
connection.queries_log.clear()
|
||||
@@ -36,13 +36,12 @@ def print_timing(func, message='', iterations=1):
|
||||
res_sum = 0
|
||||
for r in results:
|
||||
res_sum += r
|
||||
print("%s%-19s: %.4f ms, %i queries (%i times)" % (
|
||||
message, func.func_name,
|
||||
res_sum,
|
||||
len(connection.queries),
|
||||
iterations
|
||||
))
|
||||
print(
|
||||
"%s%-19s: %.4f ms, %i queries (%i times)"
|
||||
% (message, func.func_name, res_sum, len(connection.queries), iterations)
|
||||
)
|
||||
sys.stdout.flush()
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
@@ -52,9 +51,9 @@ class Command(BaseCommand):
|
||||
def handle_noargs(self, **options):
|
||||
if False:
|
||||
TestModelA.objects.all().delete()
|
||||
a = TestModelA.objects.create(field1='A1')
|
||||
b = TestModelB.objects.create(field1='B1', field2='B2')
|
||||
c = TestModelC.objects.create(field1='C1', field2='C2', field3='C3')
|
||||
a = TestModelA.objects.create(field1="A1")
|
||||
b = TestModelB.objects.create(field1="B1", field2="B2")
|
||||
c = TestModelC.objects.create(field1="C1", field2="C2", field3="C3")
|
||||
connection.queries_log.clear()
|
||||
print(TestModelC.base_objects.all())
|
||||
show_queries()
|
||||
@@ -64,7 +63,9 @@ class Command(BaseCommand):
|
||||
for i in range(1000):
|
||||
a = TestModelA.objects.create(field1=str(i % 100))
|
||||
b = TestModelB.objects.create(field1=str(i % 100), field2=str(i % 200))
|
||||
c = TestModelC.objects.create(field1=str(i % 100), field2=str(i % 200), field3=str(i % 300))
|
||||
c = TestModelC.objects.create(
|
||||
field1=str(i % 100), field2=str(i % 200), field3=str(i % 300)
|
||||
)
|
||||
if i % 100 == 0:
|
||||
print(i)
|
||||
|
||||
@@ -77,9 +78,9 @@ class Command(BaseCommand):
|
||||
return
|
||||
|
||||
NormalModelA.objects.all().delete()
|
||||
a = NormalModelA.objects.create(field1='A1')
|
||||
b = NormalModelB.objects.create(field1='B1', field2='B2')
|
||||
c = NormalModelC.objects.create(field1='C1', field2='C2', field3='C3')
|
||||
a = NormalModelA.objects.create(field1="A1")
|
||||
b = NormalModelB.objects.create(field1="B1", field2="B2")
|
||||
c = NormalModelC.objects.create(field1="C1", field2="C2", field3="C3")
|
||||
qs = TestModelA.objects.raw("SELECT * from pexp_testmodela")
|
||||
for o in list(qs):
|
||||
print(o)
|
||||
@@ -87,7 +88,8 @@ class Command(BaseCommand):
|
||||
|
||||
def poly_sql_query():
|
||||
cursor = connection.cursor()
|
||||
cursor.execute("""
|
||||
cursor.execute(
|
||||
"""
|
||||
SELECT id, pexp_testmodela.field1, pexp_testmodelb.field2, pexp_testmodelc.field3
|
||||
FROM pexp_testmodela
|
||||
LEFT OUTER JOIN pexp_testmodelb
|
||||
@@ -96,18 +98,23 @@ def poly_sql_query():
|
||||
ON pexp_testmodelb.testmodela_ptr_id = pexp_testmodelc.testmodelb_ptr_id
|
||||
WHERE pexp_testmodela.field1=%i
|
||||
ORDER BY pexp_testmodela.id
|
||||
""" % rnd.randint(0, 100))
|
||||
"""
|
||||
% rnd.randint(0, 100)
|
||||
)
|
||||
# row=cursor.fetchone()
|
||||
return
|
||||
|
||||
|
||||
def poly_sql_query2():
|
||||
cursor = connection.cursor()
|
||||
cursor.execute("""
|
||||
cursor.execute(
|
||||
"""
|
||||
SELECT id, pexp_testmodela.field1
|
||||
FROM pexp_testmodela
|
||||
WHERE pexp_testmodela.field1=%i
|
||||
ORDER BY pexp_testmodela.id
|
||||
""" % rnd.randint(0, 100))
|
||||
"""
|
||||
% rnd.randint(0, 100)
|
||||
)
|
||||
# row=cursor.fetchone()
|
||||
return
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
This module is a scratchpad for general development, testing & debugging.
|
||||
"""
|
||||
@@ -20,13 +19,15 @@ class Command(NoArgsCommand):
|
||||
Project.objects.all().delete()
|
||||
a = Project.objects.create(topic="John's gathering")
|
||||
b = ArtProject.objects.create(topic="Sculpting with Tim", artist="T. Turner")
|
||||
c = ResearchProject.objects.create(topic="Swallow Aerodynamics", supervisor="Dr. Winter")
|
||||
print Project.objects.all()
|
||||
print
|
||||
c = ResearchProject.objects.create(
|
||||
topic="Swallow Aerodynamics", supervisor="Dr. Winter"
|
||||
)
|
||||
print(Project.objects.all())
|
||||
print("")
|
||||
|
||||
TestModelA.objects.all().delete()
|
||||
a = TestModelA.objects.create(field1='A1')
|
||||
b = TestModelB.objects.create(field1='B1', field2='B2')
|
||||
c = TestModelC.objects.create(field1='C1', field2='C2', field3='C3')
|
||||
print TestModelA.objects.all()
|
||||
print
|
||||
a = TestModelA.objects.create(field1="A1")
|
||||
b = TestModelB.objects.create(field1="B1", field2="B2")
|
||||
c = TestModelC.objects.create(field1="C1", field2="C2", field3="C3")
|
||||
print(TestModelA.objects.all())
|
||||
print("")
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
This module is a scratchpad for general development, testing & debugging
|
||||
"""
|
||||
|
||||
import time
|
||||
import sys
|
||||
import time
|
||||
from pprint import pprint
|
||||
|
||||
from django.core.management import BaseCommand
|
||||
from django.db import connection
|
||||
from pprint import pprint
|
||||
from pexp.models import *
|
||||
|
||||
from pexp.models import *
|
||||
|
||||
num_objects = 1000
|
||||
|
||||
@@ -27,7 +27,7 @@ def show_queries():
|
||||
# benchmark wrappers
|
||||
|
||||
|
||||
def print_timing(func, message='', iterations=1):
|
||||
def print_timing(func, message="", iterations=1):
|
||||
def wrapper(*arg):
|
||||
results = []
|
||||
connection.queries_log.clear()
|
||||
@@ -40,28 +40,31 @@ def print_timing(func, message='', iterations=1):
|
||||
for r in results:
|
||||
res_sum += r
|
||||
median = res_sum / len(results)
|
||||
print("%s%-19s: %.0f ms, %i queries" % (
|
||||
message, func.func_name,
|
||||
median,
|
||||
len(connection.queries) / len(results)
|
||||
))
|
||||
print(
|
||||
"%s%-19s: %.0f ms, %i queries"
|
||||
% (message, func.func_name, median, len(connection.queries) / len(results))
|
||||
)
|
||||
sys.stdout.flush()
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
def run_vanilla_any_poly(func, iterations=1):
|
||||
f = print_timing(func, ' ', iterations)
|
||||
f = print_timing(func, " ", iterations)
|
||||
f(NormalModelC)
|
||||
f = print_timing(func, 'poly ', iterations)
|
||||
f = print_timing(func, "poly ", iterations)
|
||||
f(TestModelC)
|
||||
|
||||
|
||||
###################################################################################
|
||||
# benchmarks
|
||||
|
||||
|
||||
def bench_create(model):
|
||||
for i in range(num_objects):
|
||||
model.objects.create(field1='abc' + str(i), field2='abcd' + str(i), field3='abcde' + str(i))
|
||||
model.objects.create(
|
||||
field1="abc" + str(i), field2="abcd" + str(i), field3="abcde" + str(i)
|
||||
)
|
||||
# print 'count:',model.objects.count()
|
||||
|
||||
|
||||
@@ -94,6 +97,7 @@ def bench_load2_short(model):
|
||||
def bench_delete(model):
|
||||
model.objects.all().delete()
|
||||
|
||||
|
||||
###################################################################################
|
||||
# Command
|
||||
|
||||
@@ -105,10 +109,10 @@ class Command(BaseCommand):
|
||||
func_list = [
|
||||
(bench_delete, 1),
|
||||
(bench_create, 1),
|
||||
(bench_load1, 5),
|
||||
(bench_load1, 5),
|
||||
(bench_load1_short, 5),
|
||||
(bench_load2, 5),
|
||||
(bench_load2_short, 5)
|
||||
(bench_load2_short, 5),
|
||||
]
|
||||
for f, iterations in func_list:
|
||||
run_vanilla_any_poly(f, iterations=iterations)
|
||||
|
||||
@@ -15,5 +15,7 @@ class Command(BaseCommand):
|
||||
Project.objects.all().delete()
|
||||
o = Project.objects.create(topic="John's gathering")
|
||||
o = ArtProject.objects.create(topic="Sculpting with Tim", artist="T. Turner")
|
||||
o = ResearchProject.objects.create(topic="Swallow Aerodynamics", supervisor="Dr. Winter")
|
||||
o = ResearchProject.objects.create(
|
||||
topic="Swallow Aerodynamics", supervisor="Dr. Winter"
|
||||
)
|
||||
print(Project.objects.all())
|
||||
|
||||
@@ -2,181 +2,295 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
import polymorphic.showfields
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('contenttypes', '0002_remove_content_type_name'),
|
||||
]
|
||||
dependencies = [("contenttypes", "0002_remove_content_type_name")]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='NormalModelA',
|
||||
name="NormalModelA",
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('field1', models.CharField(max_length=10)),
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
verbose_name="ID",
|
||||
serialize=False,
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
),
|
||||
),
|
||||
("field1", models.CharField(max_length=10)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Project',
|
||||
name="Project",
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('topic', models.CharField(max_length=30)),
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
verbose_name="ID",
|
||||
serialize=False,
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
),
|
||||
),
|
||||
("topic", models.CharField(max_length=30)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
options={"abstract": False},
|
||||
bases=(polymorphic.showfields.ShowFieldContent, models.Model),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='ProxyBase',
|
||||
name="ProxyBase",
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('title', models.CharField(max_length=200)),
|
||||
('polymorphic_ctype', models.ForeignKey(related_name='polymorphic_pexp.proxybase_set+', editable=False, on_delete=models.CASCADE, to='contenttypes.ContentType', null=True)),
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
verbose_name="ID",
|
||||
serialize=False,
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
),
|
||||
),
|
||||
("title", models.CharField(max_length=200)),
|
||||
(
|
||||
"polymorphic_ctype",
|
||||
models.ForeignKey(
|
||||
related_name="polymorphic_pexp.proxybase_set+",
|
||||
editable=False,
|
||||
on_delete=models.CASCADE,
|
||||
to="contenttypes.ContentType",
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'ordering': ('title',),
|
||||
},
|
||||
options={"ordering": ("title",)},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='TestModelA',
|
||||
name="TestModelA",
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('field1', models.CharField(max_length=10)),
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
verbose_name="ID",
|
||||
serialize=False,
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
),
|
||||
),
|
||||
("field1", models.CharField(max_length=10)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
options={"abstract": False},
|
||||
bases=(polymorphic.showfields.ShowFieldTypeAndContent, models.Model),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='UUIDModelA',
|
||||
name="UUIDModelA",
|
||||
fields=[
|
||||
('uuid_primary_key', models.UUIDField(serialize=False, primary_key=True)),
|
||||
('field1', models.CharField(max_length=10)),
|
||||
(
|
||||
"uuid_primary_key",
|
||||
models.UUIDField(serialize=False, primary_key=True),
|
||||
),
|
||||
("field1", models.CharField(max_length=10)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
options={"abstract": False},
|
||||
bases=(polymorphic.showfields.ShowFieldTypeAndContent, models.Model),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='ArtProject',
|
||||
name="ArtProject",
|
||||
fields=[
|
||||
('project_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, on_delete=models.CASCADE, to='pexp.Project')),
|
||||
('artist', models.CharField(max_length=30)),
|
||||
(
|
||||
"project_ptr",
|
||||
models.OneToOneField(
|
||||
parent_link=True,
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
on_delete=models.CASCADE,
|
||||
to="pexp.Project",
|
||||
),
|
||||
),
|
||||
("artist", models.CharField(max_length=30)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
bases=('pexp.project',),
|
||||
options={"abstract": False},
|
||||
bases=("pexp.project",),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='NormalModelB',
|
||||
name="NormalModelB",
|
||||
fields=[
|
||||
('normalmodela_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, on_delete=models.CASCADE, to='pexp.NormalModelA')),
|
||||
('field2', models.CharField(max_length=10)),
|
||||
(
|
||||
"normalmodela_ptr",
|
||||
models.OneToOneField(
|
||||
parent_link=True,
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
on_delete=models.CASCADE,
|
||||
to="pexp.NormalModelA",
|
||||
),
|
||||
),
|
||||
("field2", models.CharField(max_length=10)),
|
||||
],
|
||||
bases=('pexp.normalmodela',),
|
||||
bases=("pexp.normalmodela",),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='ResearchProject',
|
||||
name="ResearchProject",
|
||||
fields=[
|
||||
('project_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, on_delete=models.CASCADE, to='pexp.Project')),
|
||||
('supervisor', models.CharField(max_length=30)),
|
||||
(
|
||||
"project_ptr",
|
||||
models.OneToOneField(
|
||||
parent_link=True,
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
on_delete=models.CASCADE,
|
||||
to="pexp.Project",
|
||||
),
|
||||
),
|
||||
("supervisor", models.CharField(max_length=30)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
bases=('pexp.project',),
|
||||
options={"abstract": False},
|
||||
bases=("pexp.project",),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='TestModelB',
|
||||
name="TestModelB",
|
||||
fields=[
|
||||
('testmodela_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, on_delete=models.CASCADE, to='pexp.TestModelA')),
|
||||
('field2', models.CharField(max_length=10)),
|
||||
(
|
||||
"testmodela_ptr",
|
||||
models.OneToOneField(
|
||||
parent_link=True,
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
on_delete=models.CASCADE,
|
||||
to="pexp.TestModelA",
|
||||
),
|
||||
),
|
||||
("field2", models.CharField(max_length=10)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
bases=('pexp.testmodela',),
|
||||
options={"abstract": False},
|
||||
bases=("pexp.testmodela",),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='UUIDModelB',
|
||||
name="UUIDModelB",
|
||||
fields=[
|
||||
('uuidmodela_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, on_delete=models.CASCADE, to='pexp.UUIDModelA')),
|
||||
('field2', models.CharField(max_length=10)),
|
||||
(
|
||||
"uuidmodela_ptr",
|
||||
models.OneToOneField(
|
||||
parent_link=True,
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
on_delete=models.CASCADE,
|
||||
to="pexp.UUIDModelA",
|
||||
),
|
||||
),
|
||||
("field2", models.CharField(max_length=10)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
bases=('pexp.uuidmodela',),
|
||||
options={"abstract": False},
|
||||
bases=("pexp.uuidmodela",),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='uuidmodela',
|
||||
name='polymorphic_ctype',
|
||||
field=models.ForeignKey(related_name='polymorphic_pexp.uuidmodela_set+', editable=False, on_delete=models.CASCADE, to='contenttypes.ContentType', null=True),
|
||||
model_name="uuidmodela",
|
||||
name="polymorphic_ctype",
|
||||
field=models.ForeignKey(
|
||||
related_name="polymorphic_pexp.uuidmodela_set+",
|
||||
editable=False,
|
||||
on_delete=models.CASCADE,
|
||||
to="contenttypes.ContentType",
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='testmodela',
|
||||
name='polymorphic_ctype',
|
||||
field=models.ForeignKey(related_name='polymorphic_pexp.testmodela_set+', editable=False, on_delete=models.CASCADE, to='contenttypes.ContentType', null=True),
|
||||
model_name="testmodela",
|
||||
name="polymorphic_ctype",
|
||||
field=models.ForeignKey(
|
||||
related_name="polymorphic_pexp.testmodela_set+",
|
||||
editable=False,
|
||||
on_delete=models.CASCADE,
|
||||
to="contenttypes.ContentType",
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='project',
|
||||
name='polymorphic_ctype',
|
||||
field=models.ForeignKey(related_name='polymorphic_pexp.project_set+', editable=False, on_delete=models.CASCADE, to='contenttypes.ContentType', null=True),
|
||||
model_name="project",
|
||||
name="polymorphic_ctype",
|
||||
field=models.ForeignKey(
|
||||
related_name="polymorphic_pexp.project_set+",
|
||||
editable=False,
|
||||
on_delete=models.CASCADE,
|
||||
to="contenttypes.ContentType",
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='ProxyA',
|
||||
fields=[
|
||||
],
|
||||
options={
|
||||
'proxy': True,
|
||||
},
|
||||
bases=('pexp.proxybase',),
|
||||
name="ProxyA", fields=[], options={"proxy": True}, bases=("pexp.proxybase",)
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='ProxyB',
|
||||
fields=[
|
||||
],
|
||||
options={
|
||||
'proxy': True,
|
||||
},
|
||||
bases=('pexp.proxybase',),
|
||||
name="ProxyB", fields=[], options={"proxy": True}, bases=("pexp.proxybase",)
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='NormalModelC',
|
||||
name="NormalModelC",
|
||||
fields=[
|
||||
('normalmodelb_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, on_delete=models.CASCADE, to='pexp.NormalModelB')),
|
||||
('field3', models.CharField(max_length=10)),
|
||||
(
|
||||
"normalmodelb_ptr",
|
||||
models.OneToOneField(
|
||||
parent_link=True,
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
on_delete=models.CASCADE,
|
||||
to="pexp.NormalModelB",
|
||||
),
|
||||
),
|
||||
("field3", models.CharField(max_length=10)),
|
||||
],
|
||||
bases=('pexp.normalmodelb',),
|
||||
bases=("pexp.normalmodelb",),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='TestModelC',
|
||||
name="TestModelC",
|
||||
fields=[
|
||||
('testmodelb_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, on_delete=models.CASCADE, to='pexp.TestModelB')),
|
||||
('field3', models.CharField(max_length=10)),
|
||||
('field4', models.ManyToManyField(related_name='related_c', to='pexp.TestModelB')),
|
||||
(
|
||||
"testmodelb_ptr",
|
||||
models.OneToOneField(
|
||||
parent_link=True,
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
on_delete=models.CASCADE,
|
||||
to="pexp.TestModelB",
|
||||
),
|
||||
),
|
||||
("field3", models.CharField(max_length=10)),
|
||||
(
|
||||
"field4",
|
||||
models.ManyToManyField(
|
||||
related_name="related_c", to="pexp.TestModelB"
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
bases=('pexp.testmodelb',),
|
||||
options={"abstract": False},
|
||||
bases=("pexp.testmodelb",),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='UUIDModelC',
|
||||
name="UUIDModelC",
|
||||
fields=[
|
||||
('uuidmodelb_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, on_delete=models.CASCADE, to='pexp.UUIDModelB')),
|
||||
('field3', models.CharField(max_length=10)),
|
||||
(
|
||||
"uuidmodelb_ptr",
|
||||
models.OneToOneField(
|
||||
parent_link=True,
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
on_delete=models.CASCADE,
|
||||
to="pexp.UUIDModelB",
|
||||
),
|
||||
),
|
||||
("field3", models.CharField(max_length=10)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
bases=('pexp.uuidmodelb',),
|
||||
options={"abstract": False},
|
||||
bases=("pexp.uuidmodelb",),
|
||||
),
|
||||
]
|
||||
|
||||
@@ -8,6 +8,7 @@ from polymorphic.showfields import ShowFieldContent, ShowFieldTypeAndContent
|
||||
|
||||
class Project(ShowFieldContent, PolymorphicModel):
|
||||
"""Polymorphic model"""
|
||||
|
||||
topic = models.CharField(max_length=30)
|
||||
|
||||
|
||||
@@ -21,6 +22,7 @@ class ResearchProject(Project):
|
||||
|
||||
class UUIDModelA(ShowFieldTypeAndContent, PolymorphicModel):
|
||||
"""UUID as primary key example"""
|
||||
|
||||
uuid_primary_key = models.UUIDField(primary_key=True)
|
||||
field1 = models.CharField(max_length=10)
|
||||
|
||||
@@ -35,17 +37,17 @@ class UUIDModelC(UUIDModelB):
|
||||
|
||||
class ProxyBase(PolymorphicModel):
|
||||
"""Proxy model example - a single table with multiple types."""
|
||||
|
||||
title = models.CharField(max_length=200)
|
||||
|
||||
def __unicode__(self):
|
||||
return u"<ProxyBase[type={0}]: {1}>".format(self.polymorphic_ctype, self.title)
|
||||
|
||||
class Meta:
|
||||
ordering = ('title',)
|
||||
ordering = ("title",)
|
||||
|
||||
|
||||
class ProxyA(ProxyBase):
|
||||
|
||||
class Meta:
|
||||
proxy = True
|
||||
|
||||
@@ -54,7 +56,6 @@ class ProxyA(ProxyBase):
|
||||
|
||||
|
||||
class ProxyB(ProxyBase):
|
||||
|
||||
class Meta:
|
||||
proxy = True
|
||||
|
||||
@@ -64,6 +65,7 @@ class ProxyB(ProxyBase):
|
||||
|
||||
# Internals for management command tests
|
||||
|
||||
|
||||
class TestModelA(ShowFieldTypeAndContent, PolymorphicModel):
|
||||
field1 = models.CharField(max_length=10)
|
||||
|
||||
@@ -74,11 +76,12 @@ class TestModelB(TestModelA):
|
||||
|
||||
class TestModelC(TestModelB):
|
||||
field3 = models.CharField(max_length=10)
|
||||
field4 = models.ManyToManyField(TestModelB, related_name='related_c')
|
||||
field4 = models.ManyToManyField(TestModelB, related_name="related_c")
|
||||
|
||||
|
||||
class NormalModelA(models.Model):
|
||||
"""Normal Django inheritance, no polymorphic behavior"""
|
||||
|
||||
field1 = models.CharField(max_length=10)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user