Commit 53dbd80b by Czémán Arnold

Merge branch 'issue_494' into 'master'

Upgrade to Django 1.11

See merge request !395
parents 4565cf03 df34da69
Pipeline #549 passed with stage
in 0 seconds
""" """
Creates Levels for all installed apps that have levels. Creates Levels for all installed apps that have levels.
""" """
from django.db.models import get_models, signals from django.db.models import signals
from django.apps import apps
from django.db import DEFAULT_DB_ALIAS from django.db import DEFAULT_DB_ALIAS
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
from ..models import Level, AclBase from ..models import Level, AclBase
def create_levels(app, created_models, verbosity, db=DEFAULT_DB_ALIAS, def create_levels(app_config, verbosity=False, using=DEFAULT_DB_ALIAS,
**kwargs): **kwargs):
"""Create and set the weights of the configured Levels. """Create and set the weights of the configured Levels.
Based on django.contrib.auth.management.__init__.create_permissions""" Based on django.contrib.auth.management.__init__.create_permissions"""
# if not router.allow_migrate(db, auth_app.Permission): # if not router.allow_migrate(using, auth_app.Permission):
# return # return
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
app_models = [k for k in get_models(app) if AclBase in k.__bases__] app_models = [k for k in apps.get_models(app_config)
if AclBase in k.__bases__]
print "Creating levels for models: %s." % ", ".join( print "Creating levels for models: %s." % ", ".join(
[m.__name__ for m in app_models]) [m.__name__ for m in app_models])
...@@ -31,7 +33,7 @@ def create_levels(app, created_models, verbosity, db=DEFAULT_DB_ALIAS, ...@@ -31,7 +33,7 @@ def create_levels(app, created_models, verbosity, db=DEFAULT_DB_ALIAS,
for klass in app_models: for klass in app_models:
# Force looking up the content types in the current database # Force looking up the content types in the current database
# before creating foreign keys to them. # before creating foreign keys to them.
ctype1 = ContentType.objects.db_manager(db).get_for_model(klass) ctype1 = ContentType.objects.db_manager(using).get_for_model(klass)
ctypes.add(ctype1) ctypes.add(ctype1)
weight = 0 weight = 0
try: try:
...@@ -46,7 +48,7 @@ def create_levels(app, created_models, verbosity, db=DEFAULT_DB_ALIAS, ...@@ -46,7 +48,7 @@ def create_levels(app, created_models, verbosity, db=DEFAULT_DB_ALIAS,
# Find all the Levels that have a content_type for a model we're # Find all the Levels that have a content_type for a model we're
# looking for. We don't need to check for codenames since we already have # looking for. We don't need to check for codenames since we already have
# a list of the ones we're going to create. # a list of the ones we're going to create.
all_levels = set(Level.objects.using(db).filter( all_levels = set(Level.objects.using(using).filter(
content_type__in=ctypes, content_type__in=ctypes,
).values_list( ).values_list(
"content_type", "codename" "content_type", "codename"
...@@ -57,7 +59,7 @@ def create_levels(app, created_models, verbosity, db=DEFAULT_DB_ALIAS, ...@@ -57,7 +59,7 @@ def create_levels(app, created_models, verbosity, db=DEFAULT_DB_ALIAS,
for ctype, (codename, name) in searched_levels for ctype, (codename, name) in searched_levels
if (ctype.pk, codename) not in all_levels if (ctype.pk, codename) not in all_levels
] ]
Level.objects.using(db).bulk_create(levels) Level.objects.using(using).bulk_create(levels)
if verbosity >= 2: if verbosity >= 2:
print("Adding levels [%s]." % ", ".join(unicode(l) for l in levels)) print("Adding levels [%s]." % ", ".join(unicode(l) for l in levels))
print("Searched: [%s]." % ", ".join( print("Searched: [%s]." % ", ".join(
...@@ -70,5 +72,5 @@ def create_levels(app, created_models, verbosity, db=DEFAULT_DB_ALIAS, ...@@ -70,5 +72,5 @@ def create_levels(app, created_models, verbosity, db=DEFAULT_DB_ALIAS,
content_type=ctype).update(weight=weight) content_type=ctype).update(weight=weight)
signals.post_syncdb.connect( signals.post_migrate.connect(
create_levels, dispatch_uid="circle.acl.management.create_levels") create_levels, dispatch_uid="circle.acl.management.create_levels")
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
import logging import logging
from django.contrib.auth.models import User, Group from django.contrib.auth.models import User, Group
from django.contrib.contenttypes.generic import ( from django.contrib.contenttypes.fields import (
GenericForeignKey, GenericRelation GenericForeignKey, GenericRelation
) )
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
......
...@@ -12,9 +12,10 @@ def update_permissions_after_migration(sender, **kwargs): ...@@ -12,9 +12,10 @@ def update_permissions_after_migration(sender, **kwargs):
""" """
from django.conf import settings from django.conf import settings
from django.db.models import get_models from django.apps import apps
from django.contrib.auth.management import create_permissions from django.contrib.auth.management import create_permissions
create_permissions(sender, get_models(), 2 if settings.DEBUG else 0) create_permissions(sender, apps.get_models(), 2 if settings.DEBUG else 0)
post_migrate.connect(update_permissions_after_migration) post_migrate.connect(update_permissions_after_migration)
...@@ -166,96 +166,95 @@ if exists(p): ...@@ -166,96 +166,95 @@ if exists(p):
STATICFILES_DIRS.append(p) STATICFILES_DIRS.append(p)
STATICFILES_STORAGE = 'pipeline.storage.PipelineCachedStorage' STATICFILES_STORAGE = 'pipeline.storage.PipelineCachedStorage'
PIPELINE_COMPILERS = (
'pipeline.compilers.less.LessCompiler', PIPELINE = {
) 'COMPILERS' : ('pipeline.compilers.less.LessCompiler',),
PIPELINE_CSS_COMPRESSOR = 'pipeline.compressors.yuglify.YuglifyCompressor' 'LESS_ARGUMENTS': u'--include-path={}'.format(':'.join(STATICFILES_DIRS)),
# PIPELINE_JS_COMPRESSOR = 'pipeline.compressors.slimit.SlimItCompressor' 'CSS_COMPRESSOR': 'pipeline.compressors.yuglify.YuglifyCompressor',
PIPELINE_JS_COMPRESSOR = None 'JS_COMPRESSOR': None,
PIPELINE_DISABLE_WRAPPER = True 'DISABLE_WRAPPER': True,
PIPELINE_LESS_ARGUMENTS = u'--include-path={}'.format(':'.join(STATICFILES_DIRS)) 'STYLESHEETS': {
PIPELINE_CSS = { "all": {"source_filenames": (
"all": {"source_filenames": ( "compile_bootstrap.less",
"compile_bootstrap.less", "bootstrap/dist/css/bootstrap-theme.css",
"bootstrap/dist/css/bootstrap-theme.css", "fontawesome/css/font-awesome.css",
"fontawesome/css/font-awesome.css", "jquery-simple-slider/css/simple-slider.css",
"jquery-simple-slider/css/simple-slider.css", "intro.js/introjs.css",
"intro.js/introjs.css", "template.less",
"template.less", "dashboard/dashboard.less",
"dashboard/dashboard.less", "network/network.less",
"network/network.less", "autocomplete_light/vendor/select2/dist/css/select2.css",
"autocomplete_light/style.css", "autocomplete_light/select2.css",
), ),
"output_filename": "all.css", "output_filename": "all.css",
} }
}
PIPELINE_JS = {
"all": {"source_filenames": (
# "jquery/dist/jquery.js", # included separately
"bootbox/bootbox.js",
"bootstrap/dist/js/bootstrap.js",
"intro.js/intro.js",
"jquery-knob/dist/jquery.knob.min.js",
"jquery-simple-slider/js/simple-slider.js",
"favico.js/favico.js",
"datatables/media/js/jquery.dataTables.js",
"dashboard/dashboard.js",
"dashboard/activity.js",
"dashboard/group-details.js",
"dashboard/group-list.js",
"dashboard/js/stupidtable.min.js", # no bower file
"dashboard/node-create.js",
"dashboard/node-details.js",
"dashboard/node-list.js",
"dashboard/profile.js",
"dashboard/store.js",
"dashboard/template-list.js",
"dashboard/vm-common.js",
"dashboard/vm-create.js",
"dashboard/vm-list.js",
"dashboard/help.js",
"js/host.js",
"js/network.js",
"js/switch-port.js",
"js/host-list.js",
"autocomplete_light/autocomplete.js",
"autocomplete_light/widget.js",
"autocomplete_light/addanother.js",
"autocomplete_light/text_widget.js",
"autocomplete_light/remote.js",
),
"output_filename": "all.js",
},
"vm-detail": {"source_filenames": (
"clipboard/dist/clipboard.min.js",
"dashboard/vm-details.js",
"no-vnc/include/util.js",
"no-vnc/include/webutil.js",
"no-vnc/include/base64.js",
"no-vnc/include/websock.js",
"no-vnc/include/des.js",
"no-vnc/include/keysym.js",
"no-vnc/include/keysymdef.js",
"no-vnc/include/keyboard.js",
"no-vnc/include/input.js",
"no-vnc/include/display.js",
"no-vnc/include/jsunzip.js",
"no-vnc/include/rfb.js",
"dashboard/vm-console.js",
"dashboard/vm-tour.js",
),
"output_filename": "vm-detail.js",
}, },
"datastore": {"source_filenames": ( 'JAVASCRIPT': {
"chart.js/dist/Chart.min.js", "all": {"source_filenames": (
"dashboard/datastore-details.js" # "jquery/dist/jquery.js", # included separately
), "bootbox/bootbox.js",
"output_filename": "datastore.js", "bootstrap/dist/js/bootstrap.js",
"intro.js/intro.js",
"jquery-knob/dist/jquery.knob.min.js",
"jquery-simple-slider/js/simple-slider.js",
"favico.js/favico.js",
"datatables/media/js/jquery.dataTables.js",
"autocomplete_light/jquery.init.js",
"autocomplete_light/autocomplete.init.js",
"autocomplete_light/vendor/select2/dist/js/select2.js",
"autocomplete_light/select2.js",
"dashboard/dashboard.js",
"dashboard/activity.js",
"dashboard/group-details.js",
"dashboard/group-list.js",
"dashboard/js/stupidtable.min.js", # no bower file
"dashboard/node-create.js",
"dashboard/node-details.js",
"dashboard/node-list.js",
"dashboard/profile.js",
"dashboard/store.js",
"dashboard/template-list.js",
"dashboard/vm-common.js",
"dashboard/vm-create.js",
"dashboard/vm-list.js",
"dashboard/help.js",
"js/host.js",
"js/network.js",
"js/switch-port.js",
"js/host-list.js",
),
"output_filename": "all.js",
},
"vm-detail": {"source_filenames": (
"clipboard/dist/clipboard.min.js",
"dashboard/vm-details.js",
"no-vnc/include/util.js",
"no-vnc/include/webutil.js",
"no-vnc/include/base64.js",
"no-vnc/include/websock.js",
"no-vnc/include/des.js",
"no-vnc/include/keysym.js",
"no-vnc/include/keysymdef.js",
"no-vnc/include/keyboard.js",
"no-vnc/include/input.js",
"no-vnc/include/display.js",
"no-vnc/include/jsunzip.js",
"no-vnc/include/rfb.js",
"dashboard/vm-console.js",
"dashboard/vm-tour.js",
),
"output_filename": "vm-detail.js",
},
"datastore": {"source_filenames": (
"chart.js/dist/Chart.min.js",
"dashboard/datastore-details.js"
),
"output_filename": "datastore.js",
},
}, },
} }
########## SECRET CONFIGURATION ########## SECRET CONFIGURATION
# See: https://docs.djangoproject.com/en/dev/ref/settings/#secret-key # See: https://docs.djangoproject.com/en/dev/ref/settings/#secret-key
# Note: This key should only be used for development and testing. # Note: This key should only be used for development and testing.
...@@ -279,26 +278,31 @@ FIXTURE_DIRS = ( ...@@ -279,26 +278,31 @@ FIXTURE_DIRS = (
########## TEMPLATE CONFIGURATION ########## TEMPLATE CONFIGURATION
# See: https://docs.djangoproject.com/en/dev/ref/settings/#template-context-processors
TEMPLATE_CONTEXT_PROCESSORS = (
'django.contrib.auth.context_processors.auth',
'django.core.context_processors.debug',
'django.core.context_processors.i18n',
'django.core.context_processors.media',
'django.core.context_processors.static',
'django.core.context_processors.tz',
'django.contrib.messages.context_processors.messages',
'django.core.context_processors.request',
'dashboard.context_processors.notifications',
'dashboard.context_processors.extract_settings',
'dashboard.context_processors.broadcast_messages',
)
# See: https://docs.djangoproject.com/en/dev/ref/settings/#template-dirs # See: https://docs.djangoproject.com/en/dev/ref/settings/#TEMPLATES
TEMPLATE_DIRS = ( TEMPLATES = [{
normpath(join(SITE_ROOT, '../../site-circle/templates')), 'BACKEND': 'django.template.backends.django.DjangoTemplates',
normpath(join(SITE_ROOT, 'templates')), 'DIRS' : (
) normpath(join(SITE_ROOT, '../../site-circle/templates')),
normpath(join(SITE_ROOT, 'templates')),
),
'APP_DIRS': True,
'OPTIONS': {
'context_processors': (
'django.contrib.auth.context_processors.auth',
'django.template.context_processors.debug',
'django.template.context_processors.i18n',
'django.template.context_processors.media',
'django.template.context_processors.static',
'django.template.context_processors.tz',
'django.contrib.messages.context_processors.messages',
'django.template.context_processors.request',
'dashboard.context_processors.notifications',
'dashboard.context_processors.extract_settings',
'dashboard.context_processors.broadcast_messages',
),
},
}]
########## END TEMPLATE CONFIGURATION ########## END TEMPLATE CONFIGURATION
...@@ -336,6 +340,10 @@ DJANGO_APPS = ( ...@@ -336,6 +340,10 @@ DJANGO_APPS = (
# Useful template tags: # Useful template tags:
# 'django.contrib.humanize', # 'django.contrib.humanize',
# Django autocomplete light
# it needs registering before django admin
'dal',
'dal_select2',
# Admin panel and documentation: # Admin panel and documentation:
'django.contrib.admin', 'django.contrib.admin',
# 'django.contrib.admindocs', # 'django.contrib.admindocs',
...@@ -348,7 +356,6 @@ THIRD_PARTY_APPS = ( ...@@ -348,7 +356,6 @@ THIRD_PARTY_APPS = (
'taggit', 'taggit',
'statici18n', 'statici18n',
'django_sshkey', 'django_sshkey',
'autocomplete_light',
'pipeline', 'pipeline',
) )
......
...@@ -27,7 +27,7 @@ from base import * # noqa ...@@ -27,7 +27,7 @@ from base import * # noqa
DEBUG = True DEBUG = True
# See: https://docs.djangoproject.com/en/dev/ref/settings/#template-debug # See: https://docs.djangoproject.com/en/dev/ref/settings/#template-debug
TEMPLATE_DEBUG = DEBUG TEMPLATES[0]['OPTIONS']['debug'] = DEBUG
########## END DEBUG CONFIGURATION ########## END DEBUG CONFIGURATION
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTOCOL', 'https') SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTOCOL', 'https')
...@@ -110,8 +110,10 @@ if DEBUG: ...@@ -110,8 +110,10 @@ if DEBUG:
from django.dispatch import Signal from django.dispatch import Signal
Signal.send_robust = Signal.send Signal.send_robust = Signal.send
PIPELINE_COMPILERS = ( PIPELINE["COMPILERS"] = (
'dashboard.compilers.DummyLessCompiler', 'dashboard.compilers.DummyLessCompiler',
) )
ADMIN_ENABLED = True ADMIN_ENABLED = True
ALLOWED_HOSTS = ['*']
...@@ -14,9 +14,10 @@ ...@@ -14,9 +14,10 @@
# #
# You should have received a copy of the GNU General Public License along # You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>. # with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
import os import os
from .base import * # noqa from .base import * # flake8:noqa
# fix https://github.com/django-nose/django-nose/issues/197 # fix https://github.com/django-nose/django-nose/issues/197
......
...@@ -38,7 +38,11 @@ INSTALLED_APPS += ( ...@@ -38,7 +38,11 @@ INSTALLED_APPS += (
'django_nose', 'django_nose',
) )
TEST_RUNNER = 'django_nose.NoseTestSuiteRunner' TEST_RUNNER = 'django_nose.NoseTestSuiteRunner'
NOSE_ARGS = ['--with-doctest', '--exclude-dir=dashboard/tests/selenium'] NOSE_ARGS = [
'--with-doctest',
'--exclude-dir=dashboard/tests/selenium',
'--exclude=circle'
]
PASSWORD_HASHERS = ['django.contrib.auth.hashers.MD5PasswordHasher'] PASSWORD_HASHERS = ['django.contrib.auth.hashers.MD5PasswordHasher']
CACHES = { CACHES = {
...@@ -59,7 +63,7 @@ for i in LOCAL_APPS: ...@@ -59,7 +63,7 @@ for i in LOCAL_APPS:
# don't print SQL queries # don't print SQL queries
LOGGING['handlers']['null'] = {'level': "DEBUG", LOGGING['handlers']['null'] = {'level': "DEBUG",
'class': "django.utils.log.NullHandler"} 'class': "logging.NullHandler"}
LOGGING['loggers']['django.db.backends'] = { LOGGING['loggers']['django.db.backends'] = {
'handlers': ['null'], 'handlers': ['null'],
'propagate': False, 'propagate': False,
......
...@@ -15,13 +15,16 @@ ...@@ -15,13 +15,16 @@
# You should have received a copy of the GNU General Public License along # You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>. # with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
from django.conf.urls import patterns, include, url from django.conf.urls import include, url
from django.views.generic import TemplateView from django.views.generic import TemplateView
from django.conf import settings from django.conf import settings
from django.contrib import admin from django.contrib import admin
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.shortcuts import redirect from django.shortcuts import redirect
from django.contrib.auth.views import (
password_reset_confirm, password_reset
)
from circle.settings.base import get_env_variable from circle.settings.base import get_env_variable
...@@ -33,9 +36,7 @@ from firewall.views import add_blacklist_item ...@@ -33,9 +36,7 @@ from firewall.views import add_blacklist_item
admin.autodiscover() admin.autodiscover()
urlpatterns = patterns( urlpatterns = [
'',
url(r'^$', lambda x: redirect(reverse("dashboard.index"))), url(r'^$', lambda x: redirect(reverse("dashboard.index"))),
url(r'^network/', include('network.urls')), url(r'^network/', include('network.urls')),
url(r'^blacklist-add/', add_blacklist_item), url(r'^blacklist-add/', add_blacklist_item),
...@@ -45,12 +46,11 @@ urlpatterns = patterns( ...@@ -45,12 +46,11 @@ urlpatterns = patterns(
# django/contrib/auth/urls.py (care when new version) # django/contrib/auth/urls.py (care when new version)
url((r'^accounts/reset/(?P<uidb64>[0-9A-Za-z_\-]+)/' url((r'^accounts/reset/(?P<uidb64>[0-9A-Za-z_\-]+)/'
r'(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$'), r'(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$'),
'django.contrib.auth.views.password_reset_confirm', password_reset_confirm,
{'set_password_form': CircleSetPasswordForm}, {'set_password_form': CircleSetPasswordForm},
name='accounts.password_reset_confirm' name='accounts.password_reset_confirm'
), ),
url(r'^accounts/password/reset/$', ("django.contrib.auth.views." url(r'^accounts/password/reset/$', password_reset,
"password_reset"),
{'password_reset_form': CirclePasswordResetForm}, {'password_reset_form': CirclePasswordResetForm},
name="accounts.password-reset", name="accounts.password-reset",
), ),
...@@ -73,27 +73,24 @@ urlpatterns = patterns( ...@@ -73,27 +73,24 @@ urlpatterns = patterns(
name="info.support"), name="info.support"),
url(r'^info/resize-how-to/$', ResizeHelpView.as_view(), url(r'^info/resize-how-to/$', ResizeHelpView.as_view(),
name="info.resize"), name="info.resize"),
) ]
if 'rosetta' in settings.INSTALLED_APPS: if 'rosetta' in settings.INSTALLED_APPS:
urlpatterns += patterns( urlpatterns += [
'',
url(r'^rosetta/', include('rosetta.urls')), url(r'^rosetta/', include('rosetta.urls')),
) ]
if settings.ADMIN_ENABLED: if settings.ADMIN_ENABLED:
urlpatterns += patterns( urlpatterns += [
'',
url(r'^admin/', include(admin.site.urls)), url(r'^admin/', include(admin.site.urls)),
) ]
if get_env_variable('DJANGO_SAML', 'FALSE') == 'TRUE': if get_env_variable('DJANGO_SAML', 'FALSE') == 'TRUE':
urlpatterns += patterns( urlpatterns += [
'',
(r'^saml2/', include('djangosaml2.urls')), (r'^saml2/', include('djangosaml2.urls')),
) ]
handler500 = 'common.views.handler500' handler500 = 'common.views.handler500'
handler403 = 'common.views.handler403' handler403 = 'common.views.handler403'
...@@ -45,7 +45,8 @@ def handler500(request): ...@@ -45,7 +45,8 @@ def handler500(request):
logger.exception("unhandled exception") logger.exception("unhandled exception")
ctx = get_context(request, exception) ctx = get_context(request, exception)
try: try:
resp = render_to_response("500.html", ctx, RequestContext(request)) resp = render_to_response("500.html", ctx,
RequestContext(request).flatten())
except: except:
resp = render_to_response("500.html", ctx) resp = render_to_response("500.html", ctx)
resp.status_code = 500 resp.status_code = 500
......
...@@ -31,7 +31,7 @@ from django.contrib.auth.models import User, Group ...@@ -31,7 +31,7 @@ from django.contrib.auth.models import User, Group
from django.core.validators import URLValidator from django.core.validators import URLValidator
from django.core.exceptions import PermissionDenied, ValidationError from django.core.exceptions import PermissionDenied, ValidationError
import autocomplete_light from dal import autocomplete
from crispy_forms.helper import FormHelper from crispy_forms.helper import FormHelper
from crispy_forms.layout import ( from crispy_forms.layout import (
Layout, Div, BaseInput, Field, HTML, Submit, TEMPLATE_PACK, Fieldset Layout, Div, BaseInput, Field, HTML, Submit, TEMPLATE_PACK, Fieldset
...@@ -43,7 +43,6 @@ from crispy_forms.bootstrap import FormActions ...@@ -43,7 +43,6 @@ from crispy_forms.bootstrap import FormActions
from django import forms from django import forms
from django.contrib.auth.forms import UserCreationForm as OrgUserCreationForm from django.contrib.auth.forms import UserCreationForm as OrgUserCreationForm
from django.forms.widgets import TextInput, HiddenInput from django.forms.widgets import TextInput, HiddenInput
from django.template import Context
from django.template.loader import render_to_string from django.template.loader import render_to_string
from django.utils.html import escape, format_html from django.utils.html import escape, format_html
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
...@@ -67,6 +66,7 @@ from .validators import domain_validator ...@@ -67,6 +66,7 @@ from .validators import domain_validator
from dashboard.models import ConnectCommand, create_profile from dashboard.models import ConnectCommand, create_profile
LANGUAGES_WITH_CODE = ((l[0], string_concat(l[1], " (", l[0], ")")) LANGUAGES_WITH_CODE = ((l[0], string_concat(l[1], " (", l[0], ")"))
for l in LANGUAGES) for l in LANGUAGES)
...@@ -1180,8 +1180,7 @@ class AnyTag(Div): ...@@ -1180,8 +1180,7 @@ class AnyTag(Div):
fields += render_field(field, form, form_style, context, fields += render_field(field, form, form_style, context,
template_pack=template_pack) template_pack=template_pack)
return render_to_string(self.template, Context({'tag': self, return render_to_string(self.template, {'tag': self, 'fields': fields})
'fields': fields}))
class WorkingBaseInput(BaseInput): class WorkingBaseInput(BaseInput):
...@@ -1334,27 +1333,31 @@ class UserEditForm(forms.ModelForm): ...@@ -1334,27 +1333,31 @@ class UserEditForm(forms.ModelForm):
class AclUserOrGroupAddForm(forms.Form): class AclUserOrGroupAddForm(forms.Form):
name = forms.CharField(widget=autocomplete_light.TextWidget( name = forms.CharField(
'AclUserGroupAutocomplete', widget=autocomplete.ListSelect2(
attrs={'class': 'form-control', url='autocomplete.acl.user-group',
'placeholder': _("Name of group or user")})) attrs={'class': 'form-control',
'data-html': 'true',
'data-placeholder': _("Name of group or user")}))
class TransferOwnershipForm(forms.Form): class TransferOwnershipForm(forms.Form):
name = forms.CharField( name = forms.CharField(
widget=autocomplete_light.TextWidget( widget=autocomplete.ListSelect2(
'AclUserAutocomplete', url='autocomplete.acl.user',
attrs={'class': 'form-control', attrs={'class': 'form-control',
'placeholder': _("Name of user")}), 'data-html': 'true',
'data-placeholder': _("Name of user")}),
label=_("E-mail address or identifier of user")) label=_("E-mail address or identifier of user"))
class AddGroupMemberForm(forms.Form): class AddGroupMemberForm(forms.Form):
new_member = forms.CharField( new_member = forms.CharField(
widget=autocomplete_light.TextWidget( widget=autocomplete.ListSelect2(
'AclUserAutocomplete', url='autocomplete.acl.user',
attrs={'class': 'form-control', attrs={'class': 'form-control',
'placeholder': _("Name of user")}), 'data-html': 'true',
'data-placeholder': _("Name of user")}),
label=_("E-mail address or identifier of user")) label=_("E-mail address or identifier of user"))
......
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
from __future__ import unicode_literals, absolute_import from __future__ import unicode_literals, absolute_import
import logging import logging
from optparse import make_option
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
...@@ -32,19 +31,18 @@ logger = logging.getLogger(__name__) ...@@ -32,19 +31,18 @@ logger = logging.getLogger(__name__)
class Command(BaseCommand): class Command(BaseCommand):
option_list = BaseCommand.option_list + ( def add_arguments(self, parser):
make_option('--force', action="store_true"), parser.add_argument('--force', action="store_true")
make_option('--external-net'), parser.add_argument('--external-net')
make_option('--management-net'), parser.add_argument('--management-net')
make_option('--vm-net'), parser.add_argument('--vm-net')
make_option('--external-if'), parser.add_argument('--external-if')
make_option('--management-if'), parser.add_argument('--management-if')
make_option('--vm-if'), parser.add_argument('--vm-if')
make_option('--datastore-queue'), parser.add_argument('--datastore-queue')
make_option('--firewall-queue'), parser.add_argument('--firewall-queue')
make_option('--admin-user'), parser.add_argument('--admin-user')
make_option('--admin-pass'), parser.add_argument('--admin-pass')
)
def create(self, model, field, **kwargs): def create(self, model, field, **kwargs):
value = kwargs[field] value = kwargs[field]
...@@ -59,14 +57,15 @@ class Command(BaseCommand): ...@@ -59,14 +57,15 @@ class Command(BaseCommand):
# http://docs.saltstack.com/en/latest/ref/states/all/salt.states.cmd.html # http://docs.saltstack.com/en/latest/ref/states/all/salt.states.cmd.html
def print_state(self): def print_state(self):
print "\nchanged=%s" % ("yes" if self.changed else "no") self.stdout.write("\nchanged=%s" % ("yes" if self.changed else "no"))