Django 1.9 compatibility

This commit is contained in:
Marc Aymerich 2016-04-30 12:23:13 +01:00
parent 2ae4b482f4
commit 85c0e75bcd
24 changed files with 281 additions and 49 deletions

View file

@ -67,6 +67,7 @@ class OrchestraIndexDashboard(dashboard.FluentIndexDashboard):
models.append(label) models.append(label)
label = '.'.join((opts.app_label, opts.model_name)) label = '.'.join((opts.app_label, opts.model_name))
icons[label] = options.get('icon') icons[label] = options.get('icon')
print(models)
module = AppDefaultIconList(title, models=models, icons=icons, collapsible=True) module = AppDefaultIconList(title, models=models, icons=icons, collapsible=True)
for view_name, options in views: for view_name, options in views:
self.process_registered_view(module, view_name, options) self.process_registered_view(module, view_name, options)

View file

@ -93,7 +93,7 @@ class SetPasswordHyperlinkedSerializer(HyperlinkedModelSerializer):
def validate(self, attrs): def validate(self, attrs):
""" remove password in case is not a real model field """ """ remove password in case is not a real model field """
try: try:
self.Meta.model._meta.get_field_by_name('password') self.Meta.model._meta.get_field('password')
except models.FieldDoesNotExist: except models.FieldDoesNotExist:
pass pass
else: else:

View file

@ -98,8 +98,7 @@ class PaymentStateListFilter(SimpleListFilter):
def queryset(self, request, queryset): def queryset(self, request, queryset):
# FIXME use queryset.computed_total instead of approx_total, bills.admin.BillAdmin.get_queryset # FIXME use queryset.computed_total instead of approx_total, bills.admin.BillAdmin.get_queryset
# Transaction = queryset.model.transactions.field.remote_field.related_model Transaction = queryset.model.transactions.field.remote_field.related_model
Transaction = queryset.model.transactions.related.related_model
if self.value() == 'OPEN': if self.value() == 'OPEN':
return queryset.filter(Q(is_open=True)|Q(type=queryset.model.PROFORMA)) return queryset.filter(Q(is_open=True)|Q(type=queryset.model.PROFORMA))
elif self.value() == 'PAID': elif self.value() == 'PAID':

View file

@ -118,7 +118,7 @@ class SOAForm(AdminFormMixin, forms.Form):
super(SOAForm, self).__init__(*args, **kwargs) super(SOAForm, self).__init__(*args, **kwargs)
for name in self.fields: for name in self.fields:
if not name.startswith('clear_'): if not name.startswith('clear_'):
field = Domain._meta.get_field_by_name(name)[0] field = Domain._meta.get_field(name)
self.fields[name] = forms.CharField( self.fields[name] = forms.CharField(
label=capfirst(field.verbose_name), label=capfirst(field.verbose_name),
help_text=field.help_text, help_text=field.help_text,

View file

@ -36,7 +36,7 @@ class LogEntryAdmin(admin.ModelAdmin):
def display_message(self, log): def display_message(self, log):
edit = '<a href="%(url)s"><img src="%(img)s"></img></a>' % { edit = '<a href="%(url)s"><img src="%(img)s"></img></a>' % {
'url': reverse('admin:admin_logentry_change', args=(log.pk,)), 'url': reverse('admin:admin_logentry_change', args=(log.pk,)),
'img': static('admin/img/icon_changelink.gif'), 'img': static('orchestra/images/icon_changelink.gif'),
} }
if log.is_addition(): if log.is_addition():
return _('Added "%(link)s". %(edit)s') % { return _('Added "%(link)s". %(edit)s') % {

View file

@ -12,7 +12,3 @@ class HistoryConfig(AppConfig):
administration.register( administration.register(
LogEntry, verbose_name='History', verbose_name_plural='History', icon='History.png' LogEntry, verbose_name='History', verbose_name_plural='History', icon='History.png'
) )
# prevent loosing creation time on log entry edition
# action_time = LogEntry._meta.get_field_by_name('action_time')[0]
# action_time.auto_now = False
# action_time.auto_now_add = True

View file

@ -29,7 +29,7 @@
<tr> <tr>
<th scope="row">{{ action.action_time|date:"DATETIME_FORMAT" }}</th> <th scope="row">{{ action.action_time|date:"DATETIME_FORMAT" }}</th>
<td>{{ action.user.get_username }}{% if action.user.get_full_name %} ({{ action.user.get_full_name }}){% endif %}</td> <td>{{ action.user.get_username }}{% if action.user.get_full_name %} ({{ action.user.get_full_name }}){% endif %}</td>
<td>{% if action.is_addition and not action.change_message %}{% trans 'Added' %}{% else %}{{ action.change_message }}{% endif %} <a href="{% url 'admin:admin_logentry_change' action.pk %}?edit=True" style="float:right"><img src="{% static 'admin/img/icon_changelink.gif' %}"></img></a></td> <td>{% if action.is_addition and not action.change_message %}{% trans 'Added' %}{% else %}{{ action.change_message }}{% endif %} <a href="{% url 'admin:admin_logentry_change' action.pk %}?edit=True" style="float:right"><img src="{% static 'orchestra/images/icon_changelink.gif' %}"></img></a></td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>

View file

@ -27,7 +27,7 @@ def create_local_address(sender, *args, **kwargs):
mbox = kwargs['instance'] mbox = kwargs['instance']
local_domain = settings.MAILBOXES_LOCAL_DOMAIN local_domain = settings.MAILBOXES_LOCAL_DOMAIN
if not mbox.pk and local_domain: if not mbox.pk and local_domain:
Domain = Address._meta.get_field_by_name('domain')[0].rel.to Domain = Address._meta.get_field('domain').rel.to
try: try:
domain = Domain.objects.get(name=local_domain) domain = Domain.objects.get(name=local_domain)
except Domain.DoesNotExist: except Domain.DoesNotExist:

View file

@ -12,7 +12,7 @@ class RouterTests(BaseTestCase):
def test_list_backends(self): def test_list_backends(self):
# TODO count actual, register and compare # TODO count actual, register and compare
choices = list(Route._meta.get_field_by_name('backend')[0]._choices) choices = list(Route._meta.get_field('backend')._choices)
self.assertLess(1, len(choices)) self.assertLess(1, len(choices))
def test_get_instances(self): def test_get_instances(self):
@ -25,7 +25,7 @@ class RouterTests(BaseTestCase):
pass pass
choices = backends.ServiceBackend.get_choices() choices = backends.ServiceBackend.get_choices()
Route._meta.get_field_by_name('backend')[0]._choices = choices Route._meta.get_field('backend')._choices = choices
backend = TestBackend.get_name() backend = TestBackend.get_name()
route = Route.objects.create(backend=backend, host=self.host, match='True') route = Route.objects.create(backend=backend, host=self.host, match='True')

View file

@ -167,7 +167,7 @@ class DBSoftwareService(SoftwareService):
@cached @cached
def get_account(self): def get_account(self):
account_model = self.instance._meta.get_field_by_name('account')[0] account_model = self.instance._meta.get_field('account')
return account_model.rel.to.objects.get_main() return account_model.rel.to.objects.get_main()
def validate(self): def validate(self):

View file

@ -70,7 +70,7 @@ def clone(modeladmin, request, queryset):
fields = modeladmin.get_fields(request) fields = modeladmin.get_fields(request)
query = [] query = []
for field in fields: for field in fields:
model_field = type(service)._meta.get_field_by_name(field)[0] model_field = type(service)._meta.get_field(field)
if model_field.rel: if model_field.rel:
value = getattr(service, field + '_id') value = getattr(service, field + '_id')
elif 'Boolean' in model_field.__class__.__name__: elif 'Boolean' in model_field.__class__.__name__:

View file

@ -1,6 +1,5 @@
{% extends "admin/orchestra/generic_confirmation.html" %} {% extends "admin/orchestra/generic_confirmation.html" %}
{% load i18n l10n %} {% load i18n l10n %}
{% load url from future %}
{% load admin_urls static utils %} {% load admin_urls static utils %}

View file

@ -9,7 +9,7 @@ from django.utils.text import capfirst
from ..forms.fields import MultiSelectFormField from ..forms.fields import MultiSelectFormField
class MultiSelectField(models.CharField, metaclass=models.SubfieldBase): class MultiSelectField(models.CharField):
def formfield(self, **kwargs): def formfield(self, **kwargs):
defaults = { defaults = {
'required': not self.blank, 'required': not self.blank,
@ -35,6 +35,13 @@ class MultiSelectField(models.CharField, metaclass=models.SubfieldBase):
return value return value
return [] return []
def from_db_value(self, value, expression, connection, context):
if value:
if isinstance(value, str):
return value.split(',')
return value
return []
def contribute_to_class(self, cls, name): def contribute_to_class(self, cls, name):
super(MultiSelectField, self).contribute_to_class(cls, name) super(MultiSelectField, self).contribute_to_class(cls, name)
if self.choices: if self.choices:

View file

@ -59,7 +59,7 @@ class SelectPluginAdminMixin(object):
'opts': opts, 'opts': opts,
'app_label': opts.app_label, 'app_label': opts.app_label,
'field': self.plugin_field, 'field': self.plugin_field,
'field_name': opts.get_field_by_name(self.plugin_field)[0].verbose_name, 'field_name': opts.get_field(self.plugin_field).verbose_name,
'plugin': self.plugin, 'plugin': self.plugin,
'plugins': self.plugin.get_plugins(), 'plugins': self.plugin.get_plugins(),
} }

View file

@ -23,7 +23,7 @@ class PluginDataForm(forms.ModelForm):
# Admin Readonly fields are not availeble in self.fields, so we use Meta # Admin Readonly fields are not availeble in self.fields, so we use Meta
plugin = getattr(self.instance, '%s_class' % self.plugin_field) plugin = getattr(self.instance, '%s_class' % self.plugin_field)
plugin_help_text = getattr(plugin, 'help_text', '') plugin_help_text = getattr(plugin, 'help_text', '')
model_help_text = self.instance._meta.get_field_by_name(self.plugin_field)[0].help_text model_help_text = self.instance._meta.get_field(self.plugin_field).help_text
self._meta.help_texts = { self._meta.help_texts = {
self.plugin_field: plugin_help_text or model_help_text self.plugin_field: plugin_help_text or model_help_text
} }

View file

@ -24,6 +24,116 @@
text-decoration: none; text-decoration: none;
} }
#header {
padding: 0px;
background: #417690 !important;
}
.login #container #content h1 {
text-align: center;
}
.login #container #content p {
text-align: center;
}
.login .register-links {
text-align: right
}
body.login {
background: #eee;
}
.login #container {
background: white;
border: 1px solid #ccc;
width: 28em;
min-width: 460px;
margin-left: auto;
margin-right: auto;
margin-top: 100px;
}
.login #content-main {
/*changed*/
width: 90%;
margin-left: 20px;
}
.login form {
margin-top: 1em;
}
.login .form-row {
padding: 4px 0;
float: left;
width: 100%;
}
.login .form-row label {
padding-right: 0.5em;
line-height: 2em;
font-size: 1em;
clear: both;
color: #333;
}
.login .form-row #id_username, .login .form-row #id_password {
clear: both;
padding: 6px;
width: 100%;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.login span.help {
font-size: 10px;
display: block;
}
.login .submit-row {
clear: both;
padding: 1em 0 0 9.4em;
}
.login .password-reset-link {
text-align: center;
/* LOGIN FORM */
#header #branding h1 {
margin: 0;
padding: 5px 10px;
background: transparent url(/static/orchestra/images/orchestra-logo.png) 10px 5px no-repeat;
text-indent: 0;
height: 31px;
width: 420px;
font-size: 18px;
color: whitesmoke;
font-weight: bold;
padding-left: 50px;
line-height: 30px;
}
.version {
font-size: 0%;
}
#header #branding:hover a {
text-decoration: none;
}
#header {
padding: 0px;
background: #417690 !important;
}
.login #container #content h1 { .login #container #content h1 {
text-align: center; text-align: center;
} }

View file

@ -2,6 +2,17 @@ body {
background: #FBFAF9 url(/static/orchestra/images/page-gradient.png) top left repeat-x; background: #FBFAF9 url(/static/orchestra/images/page-gradient.png) top left repeat-x;
} }
#header {
min-height: 0px;
background: none;
line-height: 0px;
padding: 0px;
height: 0px;
}
#header #navigation-menu {
height: 43px;
}
#header #branding h1 { #header #branding h1 {
margin: 0; margin: 0;
@ -20,7 +31,6 @@ body {
color: #555; color: #555;
} }
.version:before { .version:before {
content: "v"; content: "v";
opacity: 0.6; opacity: 0.6;
@ -36,19 +46,17 @@ body {
color: #9B9B9B; color: #9B9B9B;
} }
#header ul#navigation-menu li.first a { #header ul#navigation-menu li.first a {
outline: none; outline: none;
background: none; background: none;
margin: 0; margin: 0;
padding: 10px; padding: 8px 30px 9px 5px;
} }
#header-breadcrumb { #header-breadcrumb {
width: 100%; width: 100%;
z-index: -1; z-index: -1;
margin-top: 35px; margin-top: 37px;
height: 69px; height: 69px;
position: absolute; position: absolute;
background-attachment: scroll; background-clip: border-box; background-attachment: scroll; background-clip: border-box;
@ -79,6 +87,123 @@ body {
} }
div.breadcrumbs { div.breadcrumbs {
max-width: 1150px; max-width: 1350px;
margin: auto; margin: auto;
border-bottom: none;
margin-top: 43px;
}
#header-breadcrumb {
background: #79aec8;
padding-bottom: 24px;
}
.inline-group, .module {
border: 1px solid #eee;
border-radius: 4px;
}body {
background: #FBFAF9 url(/static/orchestra/images/page-gradient.png) top left repeat-x;
}
#header {
min-height: 0px;
background: none;
line-height: 0px;
padding: 0px;
height: 0px;
}
#header #navigation-menu {
height: 43px;
}
#header #branding h1 {
margin: 0;
padding: 2px 15px;
background: transparent url(/static/orchestra/images/orchestra-logo.png) 5px 2px no-repeat;
text-indent: 0;
height: 31px;
font-size: 16px;
/* font-weight: bold;*/
padding-left: 45px;
line-height: 30px;
border-right: 1px solid #ededed;
}
#branding h1, #branding h1 a:link, #branding h1 a:visited {
color: #555;
}
.version:before {
content: "v";
opacity: 0.6;
padding-right: 0.25em;
}
.version {
font-size: 60%;
}
#header #branding:hover a {
text-decoration: none;
color: #9B9B9B;
}
#header ul#navigation-menu li.first a {
outline: none;
background: none;
margin: 0;
padding: 8px 30px 9px 5px;
}
#header-breadcrumb {
width: 100%;
z-index: -1;
margin-top: 37px;
height: 69px;
position: absolute;
background-attachment: scroll; background-clip: border-box;
background-color: rgb(255, 255, 255);
background-image: url(/static/admin/img/nav-bg-reverse.gif);
background-origin: padding-box;
background-position: 0px -8px;
background-size: auto;
border-bottom-color: rgb(237, 237, 237);
border-bottom-style: solid;
border-bottom-width: 1px;
border-left-color: rgb(153, 153, 153);
border-left-style: none;
border-left-width: 0px;
border-right-color: rgb(153, 153, 153);
border-right-style: none;
border-right-width: 0px;
border-top-color: rgb(153, 153, 153);
border-top-style: none;
border-top-width: 0px;
color: white;
height: 13px;
padding-bottom: 10px;
padding-top: 10px;
background-repeat: repeat-x;
padding-left: 0;
padding-right: 0;
}
div.breadcrumbs {
max-width: 1350px;
margin: auto;
border-bottom: none;
margin-top: 43px;
}
#header-breadcrumb {
background: #79aec8;
padding-bottom: 24px;
}
.inline-group, .module {
border: 1px solid #eee;
border-radius: 4px;
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 B

View file

@ -50,13 +50,13 @@
{% if messages %} {% if messages %}
<ul class="messagelist" >{% for message in messages %} <ul class="messagelist" >{% for message in messages %}
<div style="background: {% if message.tags == 'warning' %}#ffc{% elif message.tags == 'error' %}#ffefef{% else %}#dfd{% endif %} 5px .3em no-repeat;border-bottom: 1px solid #ddd;"> <div style="background: {% if message.tags == 'warning' %}#ffc{% elif message.tags == 'error' %}#ffefef{% else %}#dfd{% endif %} 5px .3em no-repeat;border-bottom: 1px solid #ddd;">
<li{% if message.tags %} class="{{ message.tags }}"{% endif %} style="max-width:1130px;margin:auto;margin-bottom:-1px;">{{ message }}</li></div> <li{% if message.tags %} class="{{ message.tags }}"{% endif %} style="max-width:1330px;margin:auto;">{{ message }}</li></div>
{% endfor %}</ul> {% endfor %}</ul>
{% endif %} {% endif %}
{% endblock messages %} {% endblock messages %}
<!-- Content --> <!-- Content -->
<div id="content" class="{% block coltype %}colM{% endblock %}" style="max-width:1150px; margin:20px auto;"> <div id="content" class="{% block coltype %}colM{% endblock %}" style="max-width:1350px; margin:17px auto;">
{% block pretitle %}{% endblock %} {% block pretitle %}{% endblock %}
{% block content_title %}{% if title %}<h1>{{ title }}</h1>{% endif %}{% endblock %} {% block content_title %}{% if title %}<h1>{{ title }}</h1>{% endif %}{% endblock %}
{% block content %} {% block content %}
@ -74,4 +74,3 @@
</body> </body>
</html> </html>

View file

@ -1,6 +1,5 @@
{% extends "admin/base_site.html" %} {% extends "admin/base_site.html" %}
{% load i18n l10n %} {% load i18n l10n %}
{% load url from future %}
{% load admin_urls static utils %} {% load admin_urls static utils %}
{% block extrastyle %} {% block extrastyle %}

View file

@ -46,18 +46,18 @@
{% endif %} {% endif %}
<ul id="navigation-menu"> <ul id="navigation-menu">
<div style="max-width: 1170px; margin:auto;"> <div style="max-width: 1370px; margin:auto; padding-top:4px;">
<div id="branding"><a href="/admin/"></a><h1 id="site-name"><a href="/admin/">{{ ORCHESTRA_SITE_VERBOSE_NAME }}<span class="version">0.0.1a1</span></a></h1></div> <div id="branding"><a href="/admin/"></a><h1 id="site-name"><a href="/admin/">{{ ORCHESTRA_SITE_VERBOSE_NAME }}<span class="version">0.0.1a1</span></a></h1></div>
{% for item in menu.children %}{% admin_tools_render_menu_item item forloop.counter %}{% endfor %} {% for item in menu.children %}{% admin_tools_render_menu_item item forloop.counter %}{% endfor %}
<form action="{% url 'admin:orchestra_search_view' %}" method="get" name="top_search" style="display: inline;"> <form action="{% url 'admin:orchestra_search_view' %}" method="get" name="top_search" style="display: inline;">
<input type="text" id="searchbox" style="margin-left:15px;margin-top:7px;" name="q" <input type="text" id="searchbox" style="margin-left:15px;margin-top:3px;" name="q"
placeholder="Search" size="25" value="{{ query }}" placeholder="Search" size="25" value="{{ query }}"
{% if search_autofocus or app_list %}autofocus="autofocus"{% endif %} {% if search_autofocus or app_list %}autofocus="autofocus"{% endif %}
title="Use 'accountname!' for account direct access title="Use 'accountname!' for account direct access
Use 'service:word' for searching on specific services Use 'service:word' for searching on specific services
Use 'fieldname=word' for searching on specific fields"> Use 'fieldname=word' for searching on specific fields">
</form> </form>
<span style="float:right;color:grey;margin:10px;font-size:11px;"> <span style="float:right;color:grey;margin:15px;font-size:13px;">
{% url 'admin:accounts_account_change' user.pk as user_change_url %} {% url 'admin:accounts_account_change' user.pk as user_change_url %}
<a href="{{ user_change_url }}" style="color:#555;"><strong>{% filter force_escape %}{% firstof user.get_short_name user.username %}{% endfilter %}</strong></a> <a href="{{ user_change_url }}" style="color:#555;"><strong>{% filter force_escape %}{% firstof user.get_short_name user.username %}{% endfilter %}</strong></a>
<a href="{% url 'admin:password_change' %}" style="color:#555;">Change password</a> / <a href="{% url 'admin:logout' %}" style="color:#555;">Log out</a></span> <a href="{% url 'admin:password_change' %}" style="color:#555;">Change password</a> / <a href="{% url 'admin:logout' %}" style="color:#555;">Log out</a></span>

View file

@ -4,7 +4,7 @@
{% block object-tools-items %} {% block object-tools-items %}
{% for item in object_tools_items %} {% for item in object_tools_items %}
<li><a href="{{ item.url_name }}/" class="{{ item.css_class }}" title="{{ item.help_text }}">{{ item.tool_description }}</a></li> <li><a href="{% url opts|admin_urlname:item.url_name original.pk|admin_urlquote %}" class="{{ item.css_class }}" title="{{ item.help_text }}">{{ item.tool_description }}</a></li>
{% endfor %} {% endfor %}
{{ block.super }} {{ block.super }}
{% endblock %} {% endblock %}

View file

@ -1,5 +1,8 @@
from django.contrib import admin from django.contrib import admin
from django.conf.urls import include, url from django.conf.urls import include, url
from rest_framework.authtoken.views import obtain_auth_token
from orchestra.views import serve_private_media
from . import api from . import api
from .utils.apps import isinstalled from .utils.apps import isinstalled
@ -16,14 +19,8 @@ urlpatterns = [
# REST API # REST API
url(r'^api/', include(api.router.urls)), url(r'^api/', include(api.router.urls)),
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')), url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
url(r'^api-token-auth/', url(r'^api-token-auth/', obtain_auth_token, name='api-token-auth'),
'rest_framework.authtoken.views.obtain_auth_token', url(r'^media/(.+)/(.+)/(.+)/(.+)/(.+)$', serve_private_media, name='private-media'),
name='api-token-auth'
),
url(r'^media/(.+)/(.+)/(.+)/(.+)/(.+)$',
'orchestra.views.serve_private_media',
name='private-media'
),
# url(r'search', 'orchestra.views.search', name='search'), # url(r'search', 'orchestra.views.search', name='search'),
] ]

View file

@ -1,11 +1,11 @@
django==1.8.5 Django==1.9.5
django-fluent-dashboard==0.5.3 django-fluent-dashboard==0.6.1
django-admin-tools==0.6.0 django-admin-tools==0.7.2
django-extensions==1.5.7 django-extensions==1.6.1
django-celery==3.1.16 django-celery==3.1.17
celery==3.1.16 celery==3.1.23
kombu==3.0.23 kombu==3.0.35
billiard==3.3.0.18 billiard==3.3.0.23
Markdown==2.4 Markdown==2.4
djangorestframework==3.3.2 djangorestframework==3.3.2
ecdsa==0.11 ecdsa==0.11