Drop support for Django <1.8, Python <2.7
parent
df0041dff6
commit
298460c4cf
|
|
@ -2,22 +2,16 @@
|
|||
Automatically mention all model fields as parameters in the model construction.
|
||||
Based on http://djangosnippets.org/snippets/2533/
|
||||
"""
|
||||
import django
|
||||
from django.utils.html import strip_tags
|
||||
from django.utils.encoding import force_text
|
||||
import inspect
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.html import strip_tags
|
||||
|
||||
|
||||
def improve_model_docstring(app, what, name, obj, options, lines):
|
||||
from django.db import models # must be inside the function, to allow settings initialization first.
|
||||
|
||||
if inspect.isclass(obj) and issubclass(obj, models.Model):
|
||||
if django.VERSION >= (1,8):
|
||||
model_fields = obj._meta.get_fields()
|
||||
elif django.VERSION >= (1,6):
|
||||
model_fields = obj._meta.fields
|
||||
else:
|
||||
model_fields = obj._meta._fields()
|
||||
|
||||
for field in model_fields:
|
||||
help_text = strip_tags(force_text(field.help_text))
|
||||
|
|
@ -39,9 +33,9 @@ def improve_model_docstring(app, what, name, obj, options, lines):
|
|||
# Return the extended docstring
|
||||
return lines
|
||||
|
||||
|
||||
# Allow this module to be used as sphinx extension:
|
||||
def setup(app):
|
||||
# Generate docstrings for Django model fields
|
||||
# Register the docstring processor with sphinx
|
||||
app.connect('autodoc-process-docstring', improve_model_docstring)
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ sys.path.insert(0, os.path.abspath('_ext'))
|
|||
sys.path.insert(0, os.path.abspath('..'))
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'djangodummy.settings'
|
||||
|
||||
if django.VERSION >= (1, 8):
|
||||
django.setup()
|
||||
|
||||
# -- General configuration -----------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -32,8 +32,6 @@ Django as automatic manager for several purposes, including accessing
|
|||
related objects. It must not filter objects and it's safest to use
|
||||
the plain ``PolymorphicManager`` here.
|
||||
|
||||
Note that get_query_set is deprecated in Django 1.8 and creates warnings in Django 1.7.
|
||||
|
||||
Manager Inheritance
|
||||
-------------------
|
||||
|
||||
|
|
@ -69,8 +67,6 @@ regarding their start time and ``ArtProject.objects_ordered.most_recent()``
|
|||
will return the ten most recent art projects.
|
||||
.
|
||||
|
||||
Note that get_query_set is deprecated in Django 1.8 and creates warnings in Django 1.7.
|
||||
|
||||
Using a Custom Queryset Class
|
||||
-----------------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import django
|
||||
import os
|
||||
|
||||
DEBUG = True
|
||||
|
|
@ -67,7 +66,6 @@ INSTALLED_APPS = (
|
|||
'django.contrib.admin',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
#'django.contrib.sites',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
|
||||
|
|
@ -76,7 +74,6 @@ INSTALLED_APPS = (
|
|||
'orders',
|
||||
)
|
||||
|
||||
if django.VERSION >= (1, 7):
|
||||
TEST_RUNNER = 'django.test.runner.DiscoverRunner' # silence system checks
|
||||
|
||||
# Logging configuration
|
||||
|
|
|
|||
|
|
@ -3,34 +3,32 @@
|
|||
This module is a scratchpad for general development, testing & debugging
|
||||
Well, even more so than pcmd.py. You best ignore p2cmd.py.
|
||||
"""
|
||||
from django.core.management.base import NoArgsCommand
|
||||
from pprint import pprint
|
||||
import time
|
||||
import sys
|
||||
import time
|
||||
from pprint import pprint
|
||||
from random import Random
|
||||
from django.core.management.base import NoArgsCommand
|
||||
from django.db import connection
|
||||
|
||||
from pexp.models import *
|
||||
|
||||
|
||||
def reset_queries():
|
||||
if django.VERSION < (1, 8):
|
||||
connection.queries = []
|
||||
else:
|
||||
connection.queries_log.clear()
|
||||
rnd = Random()
|
||||
|
||||
|
||||
def show_queries():
|
||||
print
|
||||
print 'QUERIES:', len(connection.queries)
|
||||
print()
|
||||
print("QUERIES:", len(connection.queries))
|
||||
pprint(connection.queries)
|
||||
print
|
||||
print()
|
||||
connection.queries = []
|
||||
|
||||
|
||||
def print_timing(func, message='', iterations=1):
|
||||
def wrapper(*arg):
|
||||
results = []
|
||||
reset_queries()
|
||||
for i in xrange(iterations):
|
||||
connection.queries_log.clear()
|
||||
for i in range(iterations):
|
||||
t1 = time.time()
|
||||
x = func(*arg)
|
||||
t2 = time.time()
|
||||
|
|
@ -38,13 +36,12 @@ def print_timing(func, message='', iterations=1):
|
|||
res_sum = 0
|
||||
for r in results:
|
||||
res_sum += r
|
||||
median = res_sum / len(results)
|
||||
print '%s%-19s: %.4f ms, %i queries (%i times)' % (
|
||||
print("%s%-19s: %.4f ms, %i queries (%i times)" % (
|
||||
message, func.func_name,
|
||||
res_sum,
|
||||
len(connection.queries),
|
||||
iterations
|
||||
)
|
||||
))
|
||||
sys.stdout.flush()
|
||||
return wrapper
|
||||
|
||||
|
|
@ -58,18 +55,18 @@ class Command(NoArgsCommand):
|
|||
a = TestModelA.objects.create(field1='A1')
|
||||
b = TestModelB.objects.create(field1='B1', field2='B2')
|
||||
c = TestModelC.objects.create(field1='C1', field2='C2', field3='C3')
|
||||
reset_queries()
|
||||
print TestModelC.base_objects.all()
|
||||
connection.queries_log.clear()
|
||||
print(TestModelC.base_objects.all())
|
||||
show_queries()
|
||||
|
||||
if False:
|
||||
TestModelA.objects.all().delete()
|
||||
for i in xrange(1000):
|
||||
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))
|
||||
if i % 100 == 0:
|
||||
print i
|
||||
print(i)
|
||||
|
||||
f = print_timing(poly_sql_query, iterations=1000)
|
||||
f()
|
||||
|
|
@ -85,11 +82,7 @@ class Command(NoArgsCommand):
|
|||
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
|
||||
|
||||
from django.db import connection, transaction
|
||||
from random import Random
|
||||
rnd = Random()
|
||||
print(o)
|
||||
|
||||
|
||||
def poly_sql_query():
|
||||
|
|
|
|||
|
|
@ -3,31 +3,26 @@
|
|||
This module is a scratchpad for general development, testing & debugging
|
||||
"""
|
||||
|
||||
import time
|
||||
import sys
|
||||
|
||||
from django.core.management.base import NoArgsCommand
|
||||
from django.db import connection
|
||||
from pprint import pprint
|
||||
import sys
|
||||
from pexp.models import *
|
||||
|
||||
|
||||
num_objects = 1000
|
||||
|
||||
|
||||
def reset_queries():
|
||||
if django.VERSION < (1, 8):
|
||||
connection.queries = []
|
||||
else:
|
||||
def show_queries():
|
||||
print()
|
||||
print("QUERIES:", len(connection.queries))
|
||||
pprint(connection.queries)
|
||||
print()
|
||||
connection.queries_log.clear()
|
||||
|
||||
|
||||
def show_queries():
|
||||
print
|
||||
print 'QUERIES:', len(connection.queries)
|
||||
pprint(connection.queries)
|
||||
print
|
||||
reset_queries()
|
||||
|
||||
import time
|
||||
|
||||
###################################################################################
|
||||
# benchmark wrappers
|
||||
|
||||
|
|
@ -35,8 +30,8 @@ import time
|
|||
def print_timing(func, message='', iterations=1):
|
||||
def wrapper(*arg):
|
||||
results = []
|
||||
reset_queries()
|
||||
for i in xrange(iterations):
|
||||
connection.queries_log.clear()
|
||||
for i in range(iterations):
|
||||
t1 = time.time()
|
||||
x = func(*arg)
|
||||
t2 = time.time()
|
||||
|
|
@ -45,11 +40,11 @@ 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' % (
|
||||
print("%s%-19s: %.0f ms, %i queries" % (
|
||||
message, func.func_name,
|
||||
median,
|
||||
len(connection.queries) / len(results)
|
||||
)
|
||||
))
|
||||
sys.stdout.flush()
|
||||
return wrapper
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import django
|
||||
from django.db import models
|
||||
|
||||
from polymorphic.models import PolymorphicModel
|
||||
|
|
@ -20,15 +19,9 @@ class ResearchProject(Project):
|
|||
supervisor = models.CharField(max_length=30)
|
||||
|
||||
|
||||
if django.VERSION < (1, 8):
|
||||
from polymorphic.tools_for_tests import UUIDField
|
||||
else:
|
||||
from django.db.models import UUIDField
|
||||
|
||||
|
||||
class UUIDModelA(ShowFieldTypeAndContent, PolymorphicModel):
|
||||
"""UUID as primary key example"""
|
||||
uuid_primary_key = UUIDField(primary_key=True)
|
||||
uuid_primary_key = models.UUIDField(primary_key=True)
|
||||
field1 = models.CharField(max_length=10)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6,36 +6,6 @@ Copyright:
|
|||
This code and affiliated files are (C) by Bert Constantin and individual contributors.
|
||||
Please see LICENSE and AUTHORS for more information.
|
||||
"""
|
||||
import django
|
||||
|
||||
# See PEP 440 (https://www.python.org/dev/peps/pep-0440/)
|
||||
__version__ = "1.2"
|
||||
|
||||
|
||||
# Monkey-patch Django < 1.5 to allow ContentTypes for proxy models.
|
||||
if django.VERSION[:2] < (1, 5):
|
||||
from django.contrib.contenttypes.models import ContentTypeManager
|
||||
from django.utils.encoding import smart_text
|
||||
|
||||
def get_for_model(self, model, for_concrete_model=True):
|
||||
if for_concrete_model:
|
||||
model = model._meta.concrete_model
|
||||
elif model._deferred:
|
||||
model = model._meta.proxy_for_model
|
||||
|
||||
opts = model._meta
|
||||
|
||||
try:
|
||||
ct = self._get_from_cache(opts)
|
||||
except KeyError:
|
||||
ct, created = self.get_or_create(
|
||||
app_label=opts.app_label,
|
||||
model=opts.object_name.lower(),
|
||||
defaults={'name': smart_text(opts.verbose_name_raw)},
|
||||
)
|
||||
self._add_to_cache(self.db, ct)
|
||||
|
||||
return ct
|
||||
|
||||
ContentTypeManager.get_for_model__original = ContentTypeManager.get_for_model
|
||||
ContentTypeManager.get_for_model = get_for_model
|
||||
|
|
|
|||
|
|
@ -1,14 +1,10 @@
|
|||
from django.contrib.contenttypes.admin import GenericInlineModelAdmin
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.utils.functional import cached_property
|
||||
|
||||
from polymorphic.formsets import polymorphic_child_forms_factory, BaseGenericPolymorphicInlineFormSet, GenericPolymorphicFormSetChild
|
||||
from .inlines import PolymorphicInlineModelAdmin
|
||||
|
||||
try:
|
||||
from django.contrib.contenttypes.admin import GenericInlineModelAdmin # Django 1.7+
|
||||
except ImportError:
|
||||
from django.contrib.contenttypes.generic import GenericInlineModelAdmin
|
||||
|
||||
|
||||
class GenericPolymorphicInlineModelAdmin(PolymorphicInlineModelAdmin, GenericInlineModelAdmin):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ Each row in the inline can correspond with a different subclass.
|
|||
from functools import partial
|
||||
|
||||
from django.contrib.admin.options import InlineModelAdmin
|
||||
from django.contrib.admin.utils import flatten_fieldsets
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.forms import Media
|
||||
|
||||
|
|
@ -13,11 +14,6 @@ from polymorphic.formsets import polymorphic_child_forms_factory, BasePolymorphi
|
|||
from polymorphic.formsets.utils import add_media
|
||||
from .helpers import PolymorphicInlineSupportMixin
|
||||
|
||||
try:
|
||||
from django.contrib.admin.utils import flatten_fieldsets # Django 1.7+
|
||||
except ImportError:
|
||||
from django.contrib.admin.util import flatten_fieldsets
|
||||
|
||||
|
||||
class PolymorphicInlineModelAdmin(InlineModelAdmin):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -1,19 +1,18 @@
|
|||
"""
|
||||
The parent admin displays the list view of the base model.
|
||||
"""
|
||||
import sys
|
||||
import warnings
|
||||
|
||||
import django
|
||||
from django.conf.urls import url
|
||||
from django.contrib import admin
|
||||
from django.contrib.admin.helpers import AdminErrorList, AdminForm
|
||||
from django.contrib.admin.templatetags.admin_urls import add_preserved_filters
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.core.urlresolvers import RegexURLResolver
|
||||
from django.http import Http404, HttpResponseRedirect
|
||||
from django.shortcuts import render_to_response
|
||||
from django.template.context import RequestContext
|
||||
from django.template.response import TemplateResponse
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.http import urlencode
|
||||
from django.utils.safestring import mark_safe
|
||||
|
|
@ -21,16 +20,6 @@ from django.utils.translation import ugettext_lazy as _
|
|||
|
||||
from .forms import PolymorphicModelChoiceForm
|
||||
|
||||
try:
|
||||
# Django 1.6 implements this
|
||||
from django.contrib.admin.templatetags.admin_urls import add_preserved_filters
|
||||
except ImportError:
|
||||
def add_preserved_filters(context, form_url):
|
||||
return form_url
|
||||
|
||||
if sys.version_info[0] >= 3:
|
||||
long = int
|
||||
|
||||
|
||||
class RegistrationClosed(RuntimeError):
|
||||
"The admin model can't be registered anymore at this point."
|
||||
|
|
@ -210,13 +199,6 @@ class PolymorphicParentModelAdmin(admin.ModelAdmin):
|
|||
qs = qs.non_polymorphic()
|
||||
return qs
|
||||
|
||||
# For Django 1.5:
|
||||
def queryset(self, request):
|
||||
qs = super(PolymorphicParentModelAdmin, self).queryset(request)
|
||||
if not self.polymorphic_list:
|
||||
qs = qs.non_polymorphic()
|
||||
return qs
|
||||
|
||||
def add_view(self, request, form_url='', extra_context=None):
|
||||
"""Redirect the add view to the real admin."""
|
||||
ct_id = int(request.GET.get('ct_id', 0))
|
||||
|
|
@ -238,7 +220,6 @@ class PolymorphicParentModelAdmin(admin.ModelAdmin):
|
|||
real_admin = self._get_real_admin(object_id)
|
||||
return real_admin.change_view(request, object_id, *args, **kwargs)
|
||||
|
||||
if django.VERSION >= (1, 7):
|
||||
def changeform_view(self, request, object_id=None, *args, **kwargs):
|
||||
# The `changeform_view` is available as of Django 1.7, combining the add_view and change_view.
|
||||
# As it's directly called by django-reversion, this method is also overwritten to make sure it
|
||||
|
|
@ -334,9 +315,9 @@ class PolymorphicParentModelAdmin(admin.ModelAdmin):
|
|||
try:
|
||||
pos = path.find('/')
|
||||
if pos == -1:
|
||||
object_id = long(path)
|
||||
object_id = int(path)
|
||||
else:
|
||||
object_id = long(path[0:pos])
|
||||
object_id = int(path[0:pos])
|
||||
except ValueError:
|
||||
raise Http404("No ct_id parameter, unable to find admin subclass for path '{0}'.".format(path))
|
||||
|
||||
|
|
@ -407,8 +388,6 @@ class PolymorphicParentModelAdmin(admin.ModelAdmin):
|
|||
'add': True,
|
||||
'save_on_top': self.save_on_top,
|
||||
})
|
||||
if hasattr(self.admin_site, 'root_path'):
|
||||
context['root_path'] = self.admin_site.root_path # Django < 1.4
|
||||
|
||||
templates = self.add_type_template or [
|
||||
"admin/%s/%s/add_type_form.html" % (app_label, opts.object_name.lower()),
|
||||
|
|
@ -417,13 +396,8 @@ class PolymorphicParentModelAdmin(admin.ModelAdmin):
|
|||
"admin/add_type_form.html"
|
||||
]
|
||||
|
||||
if django.VERSION >= (1, 8):
|
||||
from django.template.response import TemplateResponse
|
||||
request.current_app = self.admin_site.name
|
||||
return TemplateResponse(request, templates, context)
|
||||
else:
|
||||
context_instance = RequestContext(request, current_app=self.admin_site.name)
|
||||
return render_to_response(templates, context, context_instance=context_instance)
|
||||
|
||||
@property
|
||||
def change_list_template(self):
|
||||
|
|
@ -445,7 +419,4 @@ class PolymorphicParentModelAdmin(admin.ModelAdmin):
|
|||
|
||||
|
||||
def _get_opt(model):
|
||||
try:
|
||||
return model._meta.app_label, model._meta.model_name # Django 1.7 format
|
||||
except AttributeError:
|
||||
return model._meta.app_label, model._meta.module_name
|
||||
return model._meta.app_label, model._meta.model_name
|
||||
|
|
|
|||
|
|
@ -132,6 +132,17 @@ class PolymorphicModelBase(ModelBase):
|
|||
if type(manager) == models.manager.ManagerDescriptor:
|
||||
manager = manager.manager
|
||||
|
||||
# As of Django 1.5, the abstract models don't get any managers, only a
|
||||
# AbstractManagerDescriptor as substitute.
|
||||
if type(manager) == AbstractManagerDescriptor and base.__name__ == 'PolymorphicModel':
|
||||
model = manager.model
|
||||
if key == 'objects':
|
||||
manager = PolymorphicManager()
|
||||
manager.model = model
|
||||
elif key == 'base_objects':
|
||||
manager = models.Manager()
|
||||
manager.model = model
|
||||
|
||||
if AbstractManagerDescriptor is not None:
|
||||
# Django 1.4 unconditionally assigned managers to a model. As of Django 1.5 however,
|
||||
# the abstract models don't get any managers, only a AbstractManagerDescriptor as substitute.
|
||||
|
|
|
|||
|
|
@ -1,15 +1,11 @@
|
|||
import django
|
||||
from django.contrib.contenttypes.forms import BaseGenericInlineFormSet, generic_inlineformset_factory
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.db import models
|
||||
from django.forms.models import ModelForm
|
||||
|
||||
from .models import BasePolymorphicModelFormSet, polymorphic_child_forms_factory, PolymorphicFormSetChild
|
||||
|
||||
try:
|
||||
from django.contrib.contenttypes.forms import BaseGenericInlineFormSet, generic_inlineformset_factory # Django 1.7+
|
||||
except ImportError:
|
||||
from django.contrib.contenttypes.generic import BaseGenericInlineFormSet, generic_inlineformset_factory
|
||||
|
||||
|
||||
class GenericPolymorphicFormSetChild(PolymorphicFormSetChild):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
from collections import OrderedDict
|
||||
|
||||
import django
|
||||
from django import forms
|
||||
|
|
@ -7,11 +8,6 @@ from django.forms.models import ModelForm, BaseModelFormSet, BaseInlineFormSet,
|
|||
from django.utils.functional import cached_property
|
||||
from .utils import add_media
|
||||
|
||||
try:
|
||||
from collections import OrderedDict
|
||||
except ImportError:
|
||||
from django.utils.datastructures import SortedDict as OrderedDict # Python 2.6
|
||||
|
||||
|
||||
class PolymorphicFormSetChild(object):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -4,14 +4,9 @@ The manager class for use in the models.
|
|||
"""
|
||||
from __future__ import unicode_literals
|
||||
import warnings
|
||||
import django
|
||||
from django.db import models
|
||||
from polymorphic.query import PolymorphicQuerySet
|
||||
|
||||
try:
|
||||
from django.utils.six import python_2_unicode_compatible
|
||||
except ImportError:
|
||||
from django.utils.encoding import python_2_unicode_compatible # Django 1.5
|
||||
from polymorphic.query import PolymorphicQuerySet
|
||||
|
||||
|
||||
__all__ = (
|
||||
|
|
@ -32,6 +27,12 @@ class PolymorphicManager(models.Manager):
|
|||
use_for_related_fields = True
|
||||
queryset_class = PolymorphicQuerySet
|
||||
|
||||
@classmethod
|
||||
def from_queryset(cls, queryset_class, class_name=None):
|
||||
manager = super(PolymorphicManager, cls).from_queryset(queryset_class, class_name=class_name)
|
||||
manager.queryset_class = queryset_class # also set our version, Django uses _queryset_class
|
||||
return manager
|
||||
|
||||
def __init__(self, queryset_class=None, *args, **kwrags):
|
||||
# Up till polymorphic 0.4, the queryset class could be specified as parameter to __init__.
|
||||
# However, this doesn't work for related managers which instantiate a new version of this class.
|
||||
|
|
@ -44,18 +45,11 @@ class PolymorphicManager(models.Manager):
|
|||
super(PolymorphicManager, self).__init__(*args, **kwrags)
|
||||
|
||||
def get_queryset(self):
|
||||
if django.VERSION >= (1, 7):
|
||||
qs = self.queryset_class(self.model, using=self._db, hints=self._hints)
|
||||
else:
|
||||
qs = self.queryset_class(self.model, using=self._db)
|
||||
if self.model._meta.proxy:
|
||||
qs = qs.instance_of(self.model)
|
||||
return qs
|
||||
|
||||
# For Django 1.5
|
||||
if django.VERSION < (1, 7):
|
||||
get_query_set = get_queryset
|
||||
|
||||
def __str__(self):
|
||||
return '%s (PolymorphicManager) using %s' % (self.__class__.__name__, self.queryset_class.__name__)
|
||||
|
||||
|
|
@ -71,10 +65,3 @@ class PolymorphicManager(models.Manager):
|
|||
|
||||
def get_real_instances(self, base_result_objects=None):
|
||||
return self.all().get_real_instances(base_result_objects=base_result_objects)
|
||||
|
||||
if django.VERSION >= (1, 7):
|
||||
@classmethod
|
||||
def from_queryset(cls, queryset_class, class_name=None):
|
||||
manager = super(PolymorphicManager, cls).from_queryset(queryset_class, class_name=class_name)
|
||||
manager.queryset_class = queryset_class # also set our version, Django uses _queryset_class
|
||||
return manager
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@ Seamless Polymorphic Inheritance for Django Models
|
|||
"""
|
||||
from __future__ import absolute_import
|
||||
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.db import models
|
||||
from django.db.utils import DEFAULT_DB_ALIAS
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.utils import six
|
||||
|
||||
from .base import PolymorphicModelBase
|
||||
|
|
@ -85,11 +85,7 @@ class PolymorphicModel(six.with_metaclass(PolymorphicModelBase, models.Model)):
|
|||
# so we use the following version, which uses the ContentType manager cache.
|
||||
# Note that model_class() can return None for stale content types;
|
||||
# when the content type record still exists but no longer refers to an existing model.
|
||||
try:
|
||||
model = ContentType.objects.db_manager(self._state.db).get_for_id(self.polymorphic_ctype_id).model_class()
|
||||
except AttributeError:
|
||||
# Django <1.6 workaround
|
||||
return None
|
||||
|
||||
# Protect against bad imports (dumpdata without --natural) or other
|
||||
# issues missing with the ContentType models.
|
||||
|
|
|
|||
|
|
@ -8,21 +8,16 @@ import copy
|
|||
from collections import defaultdict
|
||||
|
||||
import django
|
||||
from django.db.models.query import QuerySet, Q
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.db.models.query import Q, QuerySet
|
||||
from django.utils import six
|
||||
|
||||
from .query_translate import translate_polymorphic_filter_definitions_in_kwargs, translate_polymorphic_filter_definitions_in_args
|
||||
from .query_translate import translate_polymorphic_field_path, translate_polymorphic_Q_object
|
||||
|
||||
# chunk-size: maximum number of objects requested per db-request
|
||||
# by the PolymorphicModelIterable; we use the same chunk size as Django
|
||||
try:
|
||||
from django.db.models.query import CHUNK_SIZE # this is 100 for Django 1.1/1.2
|
||||
except ImportError:
|
||||
# CHUNK_SIZE was removed in Django 1.6
|
||||
CHUNK_SIZE = 100
|
||||
Polymorphic_QuerySet_objects_per_request = CHUNK_SIZE
|
||||
# by the polymorphic queryset.iterator() implementation
|
||||
Polymorphic_QuerySet_objects_per_request = 100
|
||||
|
||||
|
||||
def _polymorphic_iterator(queryset, base_iter):
|
||||
|
|
@ -97,14 +92,6 @@ def transmogrify(cls, obj):
|
|||
###################################################################################
|
||||
# PolymorphicQuerySet
|
||||
|
||||
def _query_annotations(query):
|
||||
try:
|
||||
return query.annotations
|
||||
except AttributeError:
|
||||
# Django < 1.8
|
||||
return query.aggregates
|
||||
|
||||
|
||||
class PolymorphicQuerySet(QuerySet):
|
||||
"""
|
||||
QuerySet for PolymorphicModel
|
||||
|
|
@ -138,9 +125,7 @@ class PolymorphicQuerySet(QuerySet):
|
|||
self.polymorphic_deferred_loading[1])
|
||||
return new
|
||||
|
||||
if django.VERSION >= (1, 7):
|
||||
def as_manager(cls):
|
||||
# Make sure the Django 1.7 way of creating managers works.
|
||||
from .managers import PolymorphicManager
|
||||
manager = PolymorphicManager.from_queryset(cls)()
|
||||
manager._built_with_as_manager = True
|
||||
|
|
@ -244,15 +229,8 @@ class PolymorphicQuerySet(QuerySet):
|
|||
Modifies kwargs if needed (these are Aggregate objects, we translate the lookup member variable)"""
|
||||
___lookup_assert_msg = 'PolymorphicModel: annotate()/aggregate(): ___ model lookup supported for keyword arguments only'
|
||||
|
||||
if django.VERSION < (1, 8):
|
||||
def patch_lookup(a):
|
||||
a.lookup = translate_polymorphic_field_path(self.model, a.lookup)
|
||||
|
||||
def test___lookup(a):
|
||||
assert '___' not in a.lookup, ___lookup_assert_msg
|
||||
else:
|
||||
def patch_lookup(a):
|
||||
# With Django > 1.8, the field on which the aggregate operates is
|
||||
# The field on which the aggregate operates is
|
||||
# stored inside a complex query expression.
|
||||
if isinstance(a, Q):
|
||||
translate_polymorphic_Q_object(self.model, a)
|
||||
|
|
@ -438,8 +416,8 @@ class PolymorphicQuerySet(QuerySet):
|
|||
if real_class != real_concrete_class:
|
||||
real_object = transmogrify(real_class, real_object)
|
||||
|
||||
if _query_annotations(self.query):
|
||||
for anno_field_name in six.iterkeys(_query_annotations(self.query)):
|
||||
if self.query.annotations:
|
||||
for anno_field_name in six.iterkeys(self.query.annotations):
|
||||
attr = getattr(base_result_objects_by_id[o_pk], anno_field_name)
|
||||
setattr(real_object, anno_field_name, attr)
|
||||
|
||||
|
|
@ -454,8 +432,8 @@ class PolymorphicQuerySet(QuerySet):
|
|||
resultlist = [results[ordered_id] for ordered_id in ordered_id_list if ordered_id in results]
|
||||
|
||||
# set polymorphic_annotate_names in all objects (currently just used for debugging/printing)
|
||||
if _query_annotations(self.query):
|
||||
annotate_names = list(six.iterkeys(_query_annotations(self.query))) # get annotate field list
|
||||
if self.query.annotations:
|
||||
annotate_names = list(six.iterkeys(self.query.annotations)) # get annotate field list
|
||||
for real_object in resultlist:
|
||||
real_object.polymorphic_annotate_names = annotate_names
|
||||
|
||||
|
|
|
|||
|
|
@ -7,26 +7,12 @@ from __future__ import absolute_import
|
|||
import copy
|
||||
import django
|
||||
from functools import reduce
|
||||
from django.db import models
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.db.models import Q, FieldDoesNotExist
|
||||
from django.db import models
|
||||
from django.db.models.fields.related import ForeignObjectRel, RelatedField
|
||||
from django.db.utils import DEFAULT_DB_ALIAS
|
||||
from django.utils import six
|
||||
|
||||
from django.db.models.fields.related import RelatedField
|
||||
if django.VERSION < (1, 6):
|
||||
# There was no common base class in Django 1.5, mention all variants here.
|
||||
from django.db.models.fields.related import RelatedObject, ManyToOneRel, ManyToManyRel
|
||||
REL_FIELD_CLASSES = (RelatedField, RelatedObject, ManyToOneRel, ManyToManyRel) # Leaving GenericRel out.
|
||||
elif django.VERSION < (1, 8):
|
||||
# As of Django 1.6 there is a ForeignObjectRel.
|
||||
from django.db.models.fields.related import ForeignObjectRel, RelatedObject
|
||||
REL_FIELD_CLASSES = (RelatedField, ForeignObjectRel, RelatedObject)
|
||||
else:
|
||||
# As of Django 1.8 the base class serves everything. RelatedObject is gone.
|
||||
from django.db.models.fields.related import ForeignObjectRel
|
||||
REL_FIELD_CLASSES = (RelatedField, ForeignObjectRel)
|
||||
|
||||
|
||||
###################################################################################
|
||||
# PolymorphicQuerySet support functions
|
||||
|
|
@ -102,7 +88,7 @@ def translate_polymorphic_filter_definitions_in_args(queryset_model, args, using
|
|||
"""
|
||||
if django.VERSION >= (1, 10):
|
||||
q_objects = [copy.deepcopy(q) for q in args]
|
||||
elif django.VERSION >= (1, 6):
|
||||
elif django.VERSION >= (1, 8):
|
||||
q_objects = [q.clone() for q in args]
|
||||
else:
|
||||
q_objects = args # NOTE: edits existing objects in place.
|
||||
|
|
@ -175,17 +161,14 @@ def translate_polymorphic_field_path(queryset_model, field_path):
|
|||
# Test whether it's actually a regular relation__ _fieldname (the field starting with an _)
|
||||
# so no tripple ClassName___field was intended.
|
||||
try:
|
||||
if django.VERSION >= (1, 8):
|
||||
# This also retreives M2M relations now (including reverse foreign key relations)
|
||||
field = queryset_model._meta.get_field(classname)
|
||||
else:
|
||||
field = queryset_model._meta.get_field_by_name(classname)[0]
|
||||
|
||||
if isinstance(field, REL_FIELD_CLASSES):
|
||||
if isinstance(field, (RelatedField, ForeignObjectRel)):
|
||||
# Can also test whether the field exists in the related object to avoid ambiguity between
|
||||
# class names and field names, but that never happens when your class names are in CamelCase.
|
||||
return field_path # No exception raised, field does exist.
|
||||
except FieldDoesNotExist:
|
||||
except models.FieldDoesNotExist:
|
||||
pass
|
||||
|
||||
# function to collect all sub-models, this should be optimized (cached)
|
||||
|
|
@ -261,7 +244,7 @@ def _create_model_filter_Q(modellist, not_instance_of=False, using=DEFAULT_DB_AL
|
|||
assert False, 'PolymorphicModel: instance_of expects a list of (polymorphic) models or a single (polymorphic) model'
|
||||
|
||||
def q_class_with_subclasses(model):
|
||||
q = Q(polymorphic_ctype=ContentType.objects.db_manager(using).get_for_model(model, for_concrete_model=False))
|
||||
q = models.Q(polymorphic_ctype=ContentType.objects.db_manager(using).get_for_model(model, for_concrete_model=False))
|
||||
for subclass in model.__subclasses__():
|
||||
q = q | q_class_with_subclasses(subclass)
|
||||
return q
|
||||
|
|
|
|||
|
|
@ -1,13 +1,10 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import django
|
||||
import re
|
||||
|
||||
from django.db import models
|
||||
from django.utils import six
|
||||
|
||||
try:
|
||||
from django.utils.six import python_2_unicode_compatible
|
||||
except ImportError:
|
||||
from django.utils.encoding import python_2_unicode_compatible # Django 1.5
|
||||
|
||||
|
||||
RE_DEFERRED = re.compile('_Deferred_.*')
|
||||
|
||||
|
|
@ -157,11 +154,6 @@ class ShowFieldBase(object):
|
|||
|
||||
return '<' + out + '>'
|
||||
|
||||
if django.VERSION < (1, 8):
|
||||
def get_deferred_fields(self):
|
||||
from django.db.models.query_utils import DeferredAttribute
|
||||
return set(attr for attr, value in self.__class__.__dict__.items() if isinstance(value, DeferredAttribute))
|
||||
|
||||
|
||||
class ShowFieldType(ShowFieldBase):
|
||||
""" model mixin that shows the object's class and it's field types """
|
||||
|
|
|
|||
|
|
@ -1,22 +1,16 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import django
|
||||
import uuid
|
||||
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.db import models
|
||||
from django.db.models.query import QuerySet
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
|
||||
from polymorphic.managers import PolymorphicManager
|
||||
from polymorphic.models import PolymorphicModel
|
||||
from polymorphic.query import PolymorphicQuerySet
|
||||
from polymorphic.showfields import ShowFieldContent, ShowFieldType, ShowFieldTypeAndContent
|
||||
|
||||
try:
|
||||
from django.db.models import UUIDField
|
||||
except ImportError:
|
||||
# django<1.8
|
||||
from polymorphic.tools_for_tests import UUIDField
|
||||
|
||||
|
||||
class PlainA(models.Model):
|
||||
field1 = models.CharField(max_length=10)
|
||||
|
|
@ -167,9 +161,6 @@ class MyManager(PolymorphicManager):
|
|||
def my_queryset_foo(self):
|
||||
return self.all().my_queryset_foo()
|
||||
|
||||
# Django <= 1.5 compatibility
|
||||
get_query_set = get_queryset
|
||||
|
||||
|
||||
class ModelWithMyManager(ShowFieldTypeAndContent, Model2A):
|
||||
objects = MyManager()
|
||||
|
|
@ -188,7 +179,6 @@ class ModelWithMyManagerDefault(ShowFieldTypeAndContent, Model2A):
|
|||
field4 = models.CharField(max_length=10)
|
||||
|
||||
|
||||
if django.VERSION >= (1, 7):
|
||||
class ModelWithMyManager2(ShowFieldTypeAndContent, Model2A):
|
||||
objects = MyManagerQuerySet.as_manager()
|
||||
field4 = models.CharField(max_length=10)
|
||||
|
|
@ -236,9 +226,6 @@ class PlainMyManager(models.Manager):
|
|||
def get_queryset(self):
|
||||
return PlainMyManagerQuerySet(self.model, using=self._db)
|
||||
|
||||
# Django <= 1.5 compatibility
|
||||
get_query_set = get_queryset
|
||||
|
||||
|
||||
class PlainParentModelWithManager(models.Model):
|
||||
pass
|
||||
|
|
@ -319,7 +306,7 @@ class Bottom(Middle):
|
|||
|
||||
|
||||
class UUIDProject(ShowFieldTypeAndContent, PolymorphicModel):
|
||||
uuid_primary_key = UUIDField(primary_key=True, default=uuid.uuid1)
|
||||
uuid_primary_key = models.UUIDField(primary_key=True, default=uuid.uuid1)
|
||||
topic = models.CharField(max_length=30)
|
||||
|
||||
|
||||
|
|
@ -332,7 +319,7 @@ class UUIDResearchProject(UUIDProject):
|
|||
|
||||
|
||||
class UUIDPlainA(models.Model):
|
||||
uuid_primary_key = UUIDField(primary_key=True, default=uuid.uuid1)
|
||||
uuid_primary_key = models.UUIDField(primary_key=True, default=uuid.uuid1)
|
||||
field1 = models.CharField(max_length=10)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,25 +1,15 @@
|
|||
from __future__ import print_function
|
||||
|
||||
import django
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
|
||||
from django.test import TestCase
|
||||
from django.db.models import Q
|
||||
from django.test import TestCase
|
||||
|
||||
from polymorphic.tests import * # all models
|
||||
|
||||
try:
|
||||
from unittest import skipIf
|
||||
except ImportError:
|
||||
# python<2.7
|
||||
from django.utils.unittest import skipIf
|
||||
|
||||
|
||||
|
||||
class MultipleDatabasesTests(TestCase):
|
||||
multi_db = True
|
||||
|
||||
@skipIf(django.VERSION < (1, 5,), "This test needs Django >=1.5")
|
||||
def test_save_to_non_default_database(self):
|
||||
Model2A.objects.db_manager('secondary').create(field1='A1')
|
||||
Model2C(field1='C1', field2='C2', field3='C3').save(using='secondary')
|
||||
|
|
|
|||
|
|
@ -1,22 +1,11 @@
|
|||
from __future__ import print_function
|
||||
import re
|
||||
|
||||
import django
|
||||
from django.db.models import Case, Count, Q, When
|
||||
from django.test import TestCase
|
||||
from django.db.models import Q, Count
|
||||
from django.utils import six
|
||||
from polymorphic.tests import * # all models
|
||||
|
||||
from polymorphic.contrib.guardian import get_polymorphic_base_content_type
|
||||
|
||||
try:
|
||||
from unittest import skipIf
|
||||
except ImportError:
|
||||
# python<2.7
|
||||
from django.utils.unittest import skipIf
|
||||
|
||||
if django.VERSION >= (1, 8):
|
||||
from django.db.models import Case, When
|
||||
from polymorphic.tests import * # all models
|
||||
|
||||
|
||||
class PolymorphicTests(TestCase):
|
||||
|
|
@ -188,11 +177,6 @@ class PolymorphicTests(TestCase):
|
|||
'<Model2D: id 4, field1 (CharField), field2 (CharField), field3 (CharField), field4 (CharField), '
|
||||
'deferred[field2,field3,field4,model2a_ptr_id,model2b_ptr_id]>')
|
||||
|
||||
# A bug in Django 1.4 prevents using defer across reverse relations
|
||||
# <https://code.djangoproject.com/ticket/14694>. Since polymorphic
|
||||
# uses reverse relations to traverse down model inheritance, deferring
|
||||
# fields in child models will not work in Django 1.4.
|
||||
@skipIf(django.VERSION < (1, 5), "Django 1.4 does not support defer on related fields")
|
||||
def test_defer_related_fields(self):
|
||||
self.create_model2abcd()
|
||||
|
||||
|
|
@ -424,7 +408,6 @@ class PolymorphicTests(TestCase):
|
|||
self.assertEqual(repr(objects[0]), '<Model2B: id 2, field1 (CharField), field2 (CharField)>')
|
||||
self.assertEqual(repr(objects[1]), '<Model2C: id 3, field1 (CharField), field2 (CharField), field3 (CharField)>')
|
||||
|
||||
@skipIf(django.VERSION < (1, 6), "Django 1.4 and 1.5 don't support q.clone()")
|
||||
def test_query_filter_exclude_is_immutable(self):
|
||||
# given
|
||||
q_to_reuse = Q(Model2B___field2='something')
|
||||
|
|
@ -564,7 +547,6 @@ class PolymorphicTests(TestCase):
|
|||
self.assertIs(type(ModelWithMyManagerDefault._default_manager), MyManager)
|
||||
self.assertIs(type(ModelWithMyManagerDefault.base_objects), models.Manager)
|
||||
|
||||
@skipIf(django.VERSION < (1, 7), "This test needs Django 1.7+")
|
||||
def test_user_defined_queryset_as_manager(self):
|
||||
self.create_model2abcd()
|
||||
ModelWithMyManager2.objects.create(field1='D1a', field4='D4a')
|
||||
|
|
@ -751,7 +733,6 @@ class PolymorphicTests(TestCase):
|
|||
lambda: Model2A.objects.aggregate(Count('Model2B___field2'))
|
||||
)
|
||||
|
||||
@skipIf(django.VERSION < (1, 8,), "This test needs Django >=1.8")
|
||||
def test_polymorphic__complex_aggregate(self):
|
||||
""" test (complex expression on) aggregate (should work for annotate either) """
|
||||
|
||||
|
|
@ -777,7 +758,6 @@ class PolymorphicTests(TestCase):
|
|||
with self.assertRaisesMessage(AssertionError, 'PolymorphicModel: annotate()/aggregate(): ___ model lookup supported for keyword arguments only'):
|
||||
Model2A.objects.aggregate(ComplexAgg('Model2B___field2'))
|
||||
|
||||
@skipIf(django.VERSION < (1, 8,), "This test needs Django >=1.8")
|
||||
def test_polymorphic__expressions(self):
|
||||
|
||||
from django.db.models.functions import Concat
|
||||
|
|
|
|||
|
|
@ -1,144 +0,0 @@
|
|||
# Compatibility module for Django < 1.8
|
||||
import uuid
|
||||
|
||||
from django import forms
|
||||
from django.db import models
|
||||
from django.utils.encoding import smart_text
|
||||
from django.utils import six
|
||||
|
||||
|
||||
class UUIDVersionError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class UUIDField(six.with_metaclass(models.SubfieldBase, models.CharField)):
|
||||
"""Encode and stores a Python uuid.UUID in a manner that is appropriate
|
||||
for the given datatabase that we are using.
|
||||
|
||||
For sqlite3 or MySQL we save it as a 36-character string value
|
||||
For PostgreSQL we save it as a uuid field
|
||||
|
||||
This class supports type 1, 2, 4, and 5 UUID's.
|
||||
"""
|
||||
|
||||
_CREATE_COLUMN_TYPES = {
|
||||
'postgresql_psycopg2': 'uuid',
|
||||
'postgresql': 'uuid'
|
||||
}
|
||||
|
||||
def __init__(self, verbose_name=None, name=None, auto=True, version=1, node=None, clock_seq=None, namespace=None, **kwargs):
|
||||
"""Contruct a UUIDField.
|
||||
|
||||
@param verbose_name: Optional verbose name to use in place of what
|
||||
Django would assign.
|
||||
@param name: Override Django's name assignment
|
||||
@param auto: If True, create a UUID value if one is not specified.
|
||||
@param version: By default we create a version 1 UUID.
|
||||
@param node: Used for version 1 UUID's. If not supplied, then the uuid.getnode() function is called to obtain it. This can be slow.
|
||||
@param clock_seq: Used for version 1 UUID's. If not supplied a random 14-bit sequence number is chosen
|
||||
@param namespace: Required for version 3 and version 5 UUID's.
|
||||
@param name: Required for version4 and version 5 UUID's.
|
||||
|
||||
See Also:
|
||||
- Python Library Reference, section 18.16 for more information.
|
||||
- RFC 4122, "A Universally Unique IDentifier (UUID) URN Namespace"
|
||||
|
||||
If you want to use one of these as a primary key for a Django
|
||||
model, do this::
|
||||
id = UUIDField(primary_key=True)
|
||||
This will currently I{not} work with Jython because PostgreSQL support
|
||||
in Jython is not working for uuid column types.
|
||||
"""
|
||||
self.max_length = 36
|
||||
kwargs['max_length'] = self.max_length
|
||||
if auto:
|
||||
kwargs['blank'] = True
|
||||
kwargs.setdefault('editable', False)
|
||||
|
||||
self.auto = auto
|
||||
self.version = version
|
||||
if version == 1:
|
||||
self.node, self.clock_seq = node, clock_seq
|
||||
elif version == 3 or version == 5:
|
||||
self.namespace, self.name = namespace, name
|
||||
|
||||
super(UUIDField, self).__init__(verbose_name=verbose_name,
|
||||
name=name, **kwargs)
|
||||
|
||||
def create_uuid(self):
|
||||
if not self.version or self.version == 4:
|
||||
return uuid.uuid4()
|
||||
elif self.version == 1:
|
||||
return uuid.uuid1(self.node, self.clock_seq)
|
||||
elif self.version == 2:
|
||||
raise UUIDVersionError("UUID version 2 is not supported.")
|
||||
elif self.version == 3:
|
||||
return uuid.uuid3(self.namespace, self.name)
|
||||
elif self.version == 5:
|
||||
return uuid.uuid5(self.namespace, self.name)
|
||||
else:
|
||||
raise UUIDVersionError("UUID version %s is not valid." % self.version)
|
||||
|
||||
def db_type(self, connection):
|
||||
from django.conf import settings
|
||||
full_database_type = settings.DATABASES['default']['ENGINE']
|
||||
database_type = full_database_type.split('.')[-1]
|
||||
return UUIDField._CREATE_COLUMN_TYPES.get(database_type, "char(%s)" % self.max_length)
|
||||
|
||||
def to_python(self, value):
|
||||
"""Return a uuid.UUID instance from the value returned by the database."""
|
||||
#
|
||||
# This is the proper way... But this doesn't work correctly when
|
||||
# working with an inherited model
|
||||
#
|
||||
if not value:
|
||||
return None
|
||||
if isinstance(value, uuid.UUID):
|
||||
return value
|
||||
# attempt to parse a UUID
|
||||
return uuid.UUID(smart_text(value))
|
||||
|
||||
#
|
||||
# If I do the following (returning a String instead of a UUID
|
||||
# instance), everything works.
|
||||
#
|
||||
|
||||
# if not value:
|
||||
# return None
|
||||
# if isinstance(value, uuid.UUID):
|
||||
# return smart_text(value)
|
||||
# else:
|
||||
# return value
|
||||
|
||||
def pre_save(self, model_instance, add):
|
||||
if self.auto and add:
|
||||
value = self.create_uuid()
|
||||
setattr(model_instance, self.attname, value)
|
||||
else:
|
||||
value = super(UUIDField, self).pre_save(model_instance, add)
|
||||
if self.auto and not value:
|
||||
value = self.create_uuid()
|
||||
setattr(model_instance, self.attname, value)
|
||||
return value
|
||||
|
||||
def get_db_prep_value(self, value, connection, prepared):
|
||||
"""Casts uuid.UUID values into the format expected by the back end for use in queries"""
|
||||
if isinstance(value, uuid.UUID):
|
||||
return smart_text(value)
|
||||
return value
|
||||
|
||||
def value_to_string(self, obj):
|
||||
val = self._get_val_from_obj(obj)
|
||||
if val is None:
|
||||
data = ''
|
||||
else:
|
||||
data = smart_text(val)
|
||||
return data
|
||||
|
||||
def formfield(self, **kwargs):
|
||||
defaults = {
|
||||
'form_class': forms.CharField,
|
||||
'max_length': self.max_length
|
||||
}
|
||||
defaults.update(kwargs)
|
||||
return super(UUIDField, self).formfield(**defaults)
|
||||
67
runtests.py
67
runtests.py
|
|
@ -1,12 +1,10 @@
|
|||
#!/usr/bin/env python
|
||||
import os
|
||||
import sys
|
||||
import django
|
||||
from os.path import abspath, dirname
|
||||
|
||||
import django
|
||||
from django.conf import settings
|
||||
from django.core.management import execute_from_command_line
|
||||
from django.conf import settings, global_settings as default_settings
|
||||
from os.path import dirname, realpath, abspath
|
||||
|
||||
|
||||
# Give feedback on used versions
|
||||
|
|
@ -17,42 +15,6 @@ sys.stderr.write('Using Django version {0} from {1}\n'.format(
|
|||
)
|
||||
|
||||
if not settings.configured:
|
||||
if django.VERSION >= (1, 8):
|
||||
template_settings = dict(
|
||||
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',
|
||||
),
|
||||
},
|
||||
},
|
||||
]
|
||||
)
|
||||
else:
|
||||
template_settings = dict(
|
||||
TEMPLATE_LOADERS = (
|
||||
'django.template.loaders.app_directories.Loader',
|
||||
'django.template.loaders.filesystem.Loader',
|
||||
),
|
||||
TEMPLATE_CONTEXT_PROCESSORS = list(default_settings.TEMPLATE_CONTEXT_PROCESSORS) + [
|
||||
'django.contrib.messages.context_processors.messages',
|
||||
'django.core.context_processors.request',
|
||||
],
|
||||
)
|
||||
|
||||
settings.configure(
|
||||
DEBUG=False,
|
||||
DATABASES={
|
||||
|
|
@ -65,7 +27,7 @@ if not settings.configured:
|
|||
'NAME': ':memory:'
|
||||
}
|
||||
},
|
||||
TEST_RUNNER = 'django.test.runner.DiscoverRunner' if django.VERSION >= (1, 7) else 'django.test.simple.DjangoTestSuiteRunner',
|
||||
TEST_RUNNER="django.test.runner.DiscoverRunner",
|
||||
INSTALLED_APPS=(
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
|
|
@ -76,9 +38,29 @@ if not settings.configured:
|
|||
),
|
||||
MIDDLEWARE_CLASSES=(),
|
||||
SITE_ID=3,
|
||||
**template_settings
|
||||
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",
|
||||
),
|
||||
},
|
||||
},
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
DEFAULT_TEST_APPS = [
|
||||
'polymorphic',
|
||||
]
|
||||
|
|
@ -90,5 +72,6 @@ def runtests():
|
|||
argv = sys.argv[:1] + ['test', '--traceback'] + other_args + test_apps
|
||||
execute_from_command_line(argv)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
runtests()
|
||||
|
|
|
|||
17
setup.py
17
setup.py
|
|
@ -1,10 +1,9 @@
|
|||
#!/usr/bin/env python
|
||||
from setuptools import setup, find_packages
|
||||
from os import path
|
||||
import codecs
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from os import path
|
||||
|
||||
from setuptools import find_packages, setup
|
||||
|
||||
|
||||
def read(*parts):
|
||||
|
|
@ -47,18 +46,14 @@ setup(
|
|||
'License :: OSI Approved :: BSD License',
|
||||
'Operating System :: OS Independent',
|
||||
'Programming Language :: Python',
|
||||
'Programming Language :: Python :: 2.6',
|
||||
'Programming Language :: Python :: 2.7',
|
||||
'Programming Language :: Python :: 3.2',
|
||||
'Programming Language :: Python :: 3.3',
|
||||
'Programming Language :: Python :: 3.4',
|
||||
'Programming Language :: Python :: 3.5',
|
||||
'Programming Language :: Python :: 3.6',
|
||||
'Framework :: Django',
|
||||
'Framework :: Django :: 1.4',
|
||||
'Framework :: Django :: 1.5',
|
||||
'Framework :: Django :: 1.6',
|
||||
'Framework :: Django :: 1.7',
|
||||
'Framework :: Django :: 1.8',
|
||||
'Framework :: Django :: 1.10',
|
||||
'Framework :: Django :: 1.11',
|
||||
'Topic :: Software Development :: Libraries :: Python Modules',
|
||||
]
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in New Issue