Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

make project compatible for django 3.x #706

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 72 additions & 70 deletions xadmin/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,21 @@
from django.utils import timezone
from django.template.loader import get_template
from django.template.context import Context
from django.utils import six
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Django 3 has remove django.utils.six

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes

import six
from django.utils.safestring import mark_safe
from django.utils.html import escape,format_html
from django.utils.html import escape, format_html
from django.utils.text import Truncator
from django.core.cache import cache, caches

from xadmin.views.list import EMPTY_CHANGELIST_VALUE
from xadmin.util import is_related_field,is_related_field2
from xadmin.util import is_related_field, is_related_field2
import datetime

FILTER_PREFIX = '_p_'
SEARCH_VAR = '_q_'

from .util import (get_model_from_relation,
reverse_field_path, get_limit_choices_to_from_path, prepare_lookup_value)
reverse_field_path, get_limit_choices_to_from_path, prepare_lookup_value)


class BaseFilter(object):
Expand Down Expand Up @@ -125,9 +125,9 @@ def __init__(self, field, request, params, model, admin_view, field_path):
self.context_params["%s_val" % name] = ''

arr = map(
lambda kv: setattr(self, 'lookup_' + kv[0], kv[1]),
self.context_params.items()
)
lambda kv: setattr(self, 'lookup_' + kv[0], kv[1]),
self.context_params.items()
)
if six.PY3:
list(arr)

Expand Down Expand Up @@ -169,27 +169,27 @@ def choices(self):
('', _('All')),
('1', _('Yes')),
('0', _('No')),
):
):
yield {
'selected': (
self.lookup_exact_val == lookup
and not self.lookup_isnull_val
),
'query_string': self.query_string(
{self.lookup_exact_name: lookup},
[self.lookup_isnull_name],
),
'display': title,
}
'selected': (
self.lookup_exact_val == lookup
and not self.lookup_isnull_val
),
'query_string': self.query_string(
{self.lookup_exact_name: lookup},
[self.lookup_isnull_name],
),
'display': title,
}
if isinstance(self.field, models.NullBooleanField):
yield {
'selected': self.lookup_isnull_val == 'True',
'query_string': self.query_string(
{self.lookup_isnull_name: 'True'},
[self.lookup_exact_name],
),
'display': _('Unknown'),
}
'selected': self.lookup_isnull_val == 'True',
'query_string': self.query_string(
{self.lookup_isnull_name: 'True'},
[self.lookup_exact_name],
),
'display': _('Unknown'),
}


@manager.register
Expand Down Expand Up @@ -222,10 +222,10 @@ class TextFieldListFilter(FieldFilter):
@classmethod
def test(cls, field, request, params, model, admin_view, field_path):
return (
isinstance(field, models.CharField)
and field.max_length > 20
or isinstance(field, models.TextField)
)
isinstance(field, models.CharField)
and field.max_length > 20
or isinstance(field, models.TextField)
)


@manager.register
Expand Down Expand Up @@ -320,7 +320,7 @@ def choices(self):
yield {
'selected': self.date_params == param_dict,
'query_string': self.query_string(
param_dict, [FILTER_PREFIX + self.field_generic]),
param_dict, [FILTER_PREFIX + self.field_generic]),
'display': title,
}

Expand All @@ -339,12 +339,12 @@ def test(cls, field, request, params, model, admin_view, field_path):

def __init__(self, field, request, params, model, model_admin, field_path):
other_model = get_model_from_relation(field)
if hasattr(field, 'rel'):
rel_name = field.rel.get_related_field().name
if hasattr(field, 'remote_field'):
rel_name = field.remote_field.get_related_field().name
else:
rel_name = other_model._meta.pk.name

self.lookup_formats = {'in': '%%s__%s__in' % rel_name,'exact': '%%s__%s__exact' % rel_name}
self.lookup_formats = {'in': '%%s__%s__in' % rel_name, 'exact': '%%s__%s__exact' % rel_name}
super(RelatedFieldSearchFilter, self).__init__(
field, request, params, model, model_admin, field_path)

Expand All @@ -360,9 +360,9 @@ def __init__(self, field, request, params, model, model_admin, field_path):
other_model._meta.app_label, other_model._meta.model_name))
self.label = self.label_for_value(other_model, rel_name, self.lookup_exact_val) if self.lookup_exact_val else ""
self.choices = '?'
if field.rel.limit_choices_to:
for i in list(field.rel.limit_choices_to):
self.choices += "&_p_%s=%s" % (i, field.rel.limit_choices_to[i])
if field.remote_field.limit_choices_to:
for i in list(field.remote_field.limit_choices_to):
self.choices += "&_p_%s=%s" % (i, field.remote_field.limit_choices_to[i])
self.choices = format_html(self.choices)

def label_for_value(self, other_model, rel_name, value):
Expand Down Expand Up @@ -390,12 +390,12 @@ def test(cls, field, request, params, model, admin_view, field_path):

def __init__(self, field, request, params, model, model_admin, field_path):
other_model = get_model_from_relation(field)
if hasattr(field, 'rel'):
rel_name = field.rel.get_related_field().name
if hasattr(field, 'remote_field'):
rel_name = field.remote_field.get_related_field().name
else:
rel_name = other_model._meta.pk.name

self.lookup_formats = {'in': '%%s__%s__in' % rel_name,'exact': '%%s__%s__exact' %
self.lookup_formats = {'in': '%%s__%s__in' % rel_name, 'exact': '%%s__%s__exact' %
rel_name, 'isnull': '%s__isnull'}
self.lookup_choices = field.get_choices(include_blank=False)
super(RelatedFieldListFilter, self).__init__(
Expand All @@ -409,7 +409,7 @@ def __init__(self, field, request, params, model, model_admin, field_path):

def has_output(self):
if (is_related_field(self.field)
and self.field.field.null or hasattr(self.field, 'rel')
and self.field.field.null or hasattr(self.field, 'remote_field')
and self.field.null):
extra = 1
else:
Expand All @@ -435,7 +435,7 @@ def choices(self):
'display': val,
}
if (is_related_field(self.field)
and self.field.field.null or hasattr(self.field, 'rel')
and self.field.field.null or hasattr(self.field, 'remote_field')
and self.field.null):
yield {
'selected': bool(self.lookup_isnull_val),
Expand All @@ -445,81 +445,83 @@ def choices(self):
'display': EMPTY_CHANGELIST_VALUE,
}


@manager.register
class MultiSelectFieldListFilter(ListFieldFilter):
""" Delegates the filter to the default filter and ors the results of each

Lists the distinct values of each field as a checkbox
Uses the default spec for each

"""
template = 'xadmin/filters/checklist.html'
lookup_formats = {'in': '%s__in'}
cache_config = {'enabled':False,'key':'quickfilter_%s','timeout':3600,'cache':'default'}
cache_config = {'enabled': False, 'key': 'quickfilter_%s', 'timeout': 3600, 'cache': 'default'}

@classmethod
def test(cls, field, request, params, model, admin_view, field_path):
return True

def get_cached_choices(self):
if not self.cache_config['enabled']:
return None
c = caches(self.cache_config['cache'])
return c.get(self.cache_config['key']%self.field_path)
def set_cached_choices(self,choices):
return c.get(self.cache_config['key'] % self.field_path)

def set_cached_choices(self, choices):
if not self.cache_config['enabled']:
return
c = caches(self.cache_config['cache'])
return c.set(self.cache_config['key']%self.field_path,choices)
def __init__(self, field, request, params, model, model_admin, field_path,field_order_by=None,field_limit=None,sort_key=None,cache_config=None):
super(MultiSelectFieldListFilter,self).__init__(field, request, params, model, model_admin, field_path)
return c.set(self.cache_config['key'] % self.field_path, choices)

def __init__(self, field, request, params, model, model_admin, field_path, field_order_by=None, field_limit=None, sort_key=None, cache_config=None):
super(MultiSelectFieldListFilter, self).__init__(field, request, params, model, model_admin, field_path)

# Check for it in the cachce
if cache_config is not None and type(cache_config)==dict:
if cache_config is not None and type(cache_config) == dict:
self.cache_config.update(cache_config)

if self.cache_config['enabled']:
self.field_path = field_path
choices = self.get_cached_choices()
if choices:
self.lookup_choices = choices
return

# Else rebuild it
queryset = self.admin_view.queryset().exclude(**{"%s__isnull"%field_path:True}).values_list(field_path, flat=True).distinct()
queryset = self.admin_view.queryset().exclude(**{"%s__isnull" % field_path: True}).values_list(field_path, flat=True).distinct()
#queryset = self.admin_view.queryset().distinct(field_path).exclude(**{"%s__isnull"%field_path:True})

if field_order_by is not None:
# Do a subquery to order the distinct set
queryset = self.admin_view.queryset().filter(id__in=queryset).order_by(field_order_by)
if field_limit is not None and type(field_limit)==int and queryset.count()>field_limit:

if field_limit is not None and type(field_limit) == int and queryset.count() > field_limit:
queryset = queryset[:field_limit]
self.lookup_choices = [str(it) for it in queryset.values_list(field_path,flat=True) if str(it).strip()!=""]

self.lookup_choices = [str(it) for it in queryset.values_list(field_path, flat=True) if str(it).strip() != ""]
if sort_key is not None:
self.lookup_choices = sorted(self.lookup_choices,key=sort_key)
self.lookup_choices = sorted(self.lookup_choices, key=sort_key)

if self.cache_config['enabled']:
self.set_cached_choices(self.lookup_choices)
self.set_cached_choices(self.lookup_choices)

def choices(self):
self.lookup_in_val = (type(self.lookup_in_val) in (tuple,list)) and self.lookup_in_val or list(self.lookup_in_val)
self.lookup_in_val = (type(self.lookup_in_val) in (tuple, list)) and self.lookup_in_val or list(self.lookup_in_val)
yield {
'selected': len(self.lookup_in_val) == 0,
'query_string': self.query_string({},[self.lookup_in_name]),
'query_string': self.query_string({}, [self.lookup_in_name]),
'display': _('All'),
}
for val in self.lookup_choices:
yield {
'selected': smart_text(val) in self.lookup_in_val,
'query_string': self.query_string({self.lookup_in_name: ",".join([val]+self.lookup_in_val),}),
'remove_query_string': self.query_string({self.lookup_in_name: ",".join([v for v in self.lookup_in_val if v != val]),}),
'query_string': self.query_string({self.lookup_in_name: ",".join([val] + self.lookup_in_val), }),
'remove_query_string': self.query_string({self.lookup_in_name: ",".join([v for v in self.lookup_in_val if v != val]), }),
'display': val,
}


@manager.register
class AllValuesFieldListFilter(ListFieldFilter):
lookup_formats = {'exact': '%s__exact', 'isnull': '%s__isnull'}
Expand Down
19 changes: 10 additions & 9 deletions xadmin/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
from django.conf import settings
from django.contrib.contenttypes.models import ContentType
from django.utils.translation import ugettext_lazy as _, ugettext
from django.core.urlresolvers import NoReverseMatch, reverse
from django.urls.base import reverse
from django.core.serializers.json import DjangoJSONEncoder
from django.db.models.base import ModelBase
from django.utils.encoding import python_2_unicode_compatible, smart_text

from django.utils.encoding import smart_text
from six import python_2_unicode_compatible
from django.db.models.signals import post_migrate
from django.contrib.auth.models import Permission

Expand All @@ -19,6 +19,7 @@

AUTH_USER_MODEL = getattr(settings, 'AUTH_USER_MODEL', 'auth.User')


def add_view_permissions(sender, **kwargs):
"""
This syncdb hooks takes care of adding a view permission too all our
Expand All @@ -35,7 +36,7 @@ def add_view_permissions(sender, **kwargs):
Permission.objects.create(content_type=content_type,
codename=codename,
name="Can view %s" % content_type.name)
#print "Added view permission for %s" % content_type.name
# print "Added view permission for %s" % content_type.name

# check for all our view permissions after a syncdb
post_migrate.connect(add_view_permissions)
Expand All @@ -44,9 +45,9 @@ def add_view_permissions(sender, **kwargs):
@python_2_unicode_compatible
class Bookmark(models.Model):
title = models.CharField(_(u'Title'), max_length=128)
user = models.ForeignKey(AUTH_USER_MODEL, verbose_name=_(u"user"), blank=True, null=True)
user = models.ForeignKey(AUTH_USER_MODEL, on_delete=models.CASCADE, verbose_name=_(u"user"), blank=True, null=True)
url_name = models.CharField(_(u'Url Name'), max_length=64)
content_type = models.ForeignKey(ContentType)
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
query = models.CharField(_(u'Query String'), max_length=1000, blank=True)
is_share = models.BooleanField(_(u'Is Shared'), default=False)

Expand All @@ -66,6 +67,7 @@ class Meta:


class JSONEncoder(DjangoJSONEncoder):

def default(self, o):
if isinstance(o, datetime.datetime):
return o.strftime('%Y-%m-%d %H:%M:%S')
Expand All @@ -84,7 +86,7 @@ def default(self, o):

@python_2_unicode_compatible
class UserSettings(models.Model):
user = models.ForeignKey(AUTH_USER_MODEL, verbose_name=_(u"user"))
user = models.ForeignKey(AUTH_USER_MODEL, on_delete=models.CASCADE, verbose_name=_(u"user"))
key = models.CharField(_('Settings Key'), max_length=256)
value = models.TextField(_('Settings Content'))

Expand All @@ -104,7 +106,7 @@ class Meta:

@python_2_unicode_compatible
class UserWidget(models.Model):
user = models.ForeignKey(AUTH_USER_MODEL, verbose_name=_(u"user"))
user = models.ForeignKey(AUTH_USER_MODEL, on_delete=models.CASCADE, verbose_name=_(u"user"))
page_id = models.CharField(_(u"Page"), max_length=256)
widget_type = models.CharField(_(u"Widget Type"), max_length=50)
value = models.TextField(_(u"Widget Params"))
Expand Down Expand Up @@ -186,4 +188,3 @@ def __str__(self):
def get_edited_object(self):
"Returns the edited object represented by this log entry"
return self.content_type.get_object_for_this_type(pk=self.object_id)

Loading