Updated to DJango 1.8
This commit is contained in:
parent
4a8a77715c
commit
751dda7126
11
TODO.md
11
TODO.md
|
@ -313,16 +313,15 @@ celery max-tasks-per-child
|
||||||
* webapp has_website list filter
|
* webapp has_website list filter
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# FIXME account deletion generates a integrity error
|
|
||||||
|
|
||||||
|
|
||||||
apt-get install python3 python3-pip
|
|
||||||
cp /usr/local/lib/python2.7/dist-packages/orchestra.pth /usr/local/lib/python3.4/dist-packages/
|
|
||||||
glic3rinu's django-fluent-dashboard
|
glic3rinu's django-fluent-dashboard
|
||||||
* gevent is not ported to python3 :'(
|
* gevent is not ported to python3 :'(
|
||||||
* uwsgi python3
|
* uwsgi python3
|
||||||
|
https://github.com/django-nose/django-nose/archive/master.zip
|
||||||
|
django_debug_toolbar-1.3.0-py2.py3-none-any.whl
|
||||||
|
|
||||||
|
|
||||||
|
# FIXME account deletion generates a integrity error
|
||||||
# FIXME what to do when deleting accounts? set fk null and fill a username charfield? issues, invoices.. we whant all this to go away?
|
# FIXME what to do when deleting accounts? set fk null and fill a username charfield? issues, invoices.. we whant all this to go away?
|
||||||
* implement delete All related services
|
* implement delete All related services
|
||||||
|
|
||||||
|
* address name change does not remove old one :P
|
||||||
|
|
|
@ -9,7 +9,7 @@ class UsedContentTypeFilter(SimpleListFilter):
|
||||||
def lookups(self, request, model_admin):
|
def lookups(self, request, model_admin):
|
||||||
qset = model_admin.model._default_manager.all().order_by()
|
qset = model_admin.model._default_manager.all().order_by()
|
||||||
result = ()
|
result = ()
|
||||||
for pk, name in qset.values_list('content_type', 'content_type__name').distinct():
|
for pk, name in qset.values_list('content_type', 'content_type__model').distinct():
|
||||||
result += ((str(pk), name.capitalize()),)
|
result += ((str(pk), name.capitalize()),)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
|
@ -165,9 +165,9 @@ class BillAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
transactions = bill.transactions.all()
|
transactions = bill.transactions.all()
|
||||||
if len(transactions) == 1:
|
if len(transactions) == 1:
|
||||||
args = (transactions[0].pk,)
|
args = (transactions[0].pk,)
|
||||||
url = reverse('admin:%s_%s_change' % (t_opts.app_label, t_opts.module_name), args=args)
|
url = reverse('admin:%s_%s_change' % (t_opts.app_label, t_opts.model_name), args=args)
|
||||||
else:
|
else:
|
||||||
url = reverse('admin:%s_%s_changelist' % (t_opts.app_label, t_opts.module_name))
|
url = reverse('admin:%s_%s_changelist' % (t_opts.app_label, t_opts.model_name))
|
||||||
url += '?bill=%i' % bill.pk
|
url += '?bill=%i' % bill.pk
|
||||||
state = bill.get_payment_state_display().upper()
|
state = bill.get_payment_state_display().upper()
|
||||||
color = PAYMENT_STATE_COLORS.get(bill.payment_state, 'grey')
|
color = PAYMENT_STATE_COLORS.get(bill.payment_state, 'grey')
|
||||||
|
|
|
@ -92,7 +92,7 @@ class ReadOnlySQLPasswordHashField(ReadOnlyPasswordHashField):
|
||||||
summary = mark_safe("<strong>%s</strong>" % _("No password set."))
|
summary = mark_safe("<strong>%s</strong>" % _("No password set."))
|
||||||
else:
|
else:
|
||||||
size = len(value)
|
size = len(value)
|
||||||
summary = value[:size/2] + '*'*(size-size/2)
|
summary = value[:int(size/2)] + '*'*int(size-size/2)
|
||||||
summary = "<strong>hash</strong>: %s" % summary
|
summary = "<strong>hash</strong>: %s" % summary
|
||||||
if value.startswith('*'):
|
if value.startswith('*'):
|
||||||
summary = "<strong>algorithm</strong>: sha1_bin_hex %s" % summary
|
summary = "<strong>algorithm</strong>: sha1_bin_hex %s" % summary
|
||||||
|
|
|
@ -60,7 +60,7 @@ class DomainInline(admin.TabularInline):
|
||||||
|
|
||||||
class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
list_display = (
|
list_display = (
|
||||||
'structured_name', 'display_is_top', 'websites', 'account_link'
|
'structured_name', 'display_is_top', 'display_websites', 'account_link'
|
||||||
)
|
)
|
||||||
add_fields = ('name', 'account')
|
add_fields = ('name', 'account')
|
||||||
fields = ('name', 'account_link')
|
fields = ('name', 'account_link')
|
||||||
|
@ -85,7 +85,7 @@ class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
display_is_top.boolean = True
|
display_is_top.boolean = True
|
||||||
display_is_top.admin_order_field = 'top'
|
display_is_top.admin_order_field = 'top'
|
||||||
|
|
||||||
def websites(self, domain):
|
def display_websites(self, domain):
|
||||||
if apps.isinstalled('orchestra.apps.websites'):
|
if apps.isinstalled('orchestra.apps.websites'):
|
||||||
webs = domain.websites.all()
|
webs = domain.websites.all()
|
||||||
if webs:
|
if webs:
|
||||||
|
@ -95,9 +95,9 @@ class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
links.append('<a href="%s">%s</a>' % (url, web.name))
|
links.append('<a href="%s">%s</a>' % (url, web.name))
|
||||||
return '<br>'.join(links)
|
return '<br>'.join(links)
|
||||||
return _("No website")
|
return _("No website")
|
||||||
websites.admin_order_field = 'websites__name'
|
display_websites.admin_order_field = 'websites__name'
|
||||||
websites.short_description = _("Websites")
|
display_websites.short_description = _("Websites")
|
||||||
websites.allow_tags = True
|
display_websites.allow_tags = True
|
||||||
|
|
||||||
def get_queryset(self, request):
|
def get_queryset(self, request):
|
||||||
""" Order by structured name and imporve performance """
|
""" Order by structured name and imporve performance """
|
||||||
|
|
|
@ -38,10 +38,7 @@ class OperationsMiddleware(object):
|
||||||
Stores all the operations derived from save and delete signals and executes them
|
Stores all the operations derived from save and delete signals and executes them
|
||||||
at the end of the request/response cycle
|
at the end of the request/response cycle
|
||||||
|
|
||||||
It also works as a transaction middleware. Each view function will be run
|
It also works as a transaction middleware, making requets to run within an atomic block.
|
||||||
with commit_on_response activated - that way a save() doesn't do a direct
|
|
||||||
commit, the commit is done when a successful response is created. If an
|
|
||||||
exception happens, the database is rolled back.
|
|
||||||
"""
|
"""
|
||||||
# Thread local is used because request object is not available on model signals
|
# Thread local is used because request object is not available on model signals
|
||||||
thread_locals = local()
|
thread_locals = local()
|
||||||
|
@ -77,55 +74,38 @@ class OperationsMiddleware(object):
|
||||||
instance = kwargs.pop('instance')
|
instance = kwargs.pop('instance')
|
||||||
manager.collect(instance, action, **kwargs)
|
manager.collect(instance, action, **kwargs)
|
||||||
|
|
||||||
def commit_transaction(self):
|
def enter_transaction_management(self):
|
||||||
if not transaction.get_autocommit():
|
type(self).thread_locals.transaction = transaction.atomic()
|
||||||
if transaction.is_dirty():
|
type(self).thread_locals.transaction.__enter__()
|
||||||
# Note: it is possible that the commit fails. If the reason is
|
|
||||||
# closed connection or some similar reason, then there is
|
def leave_transaction_management(self, exception=None):
|
||||||
# little hope to proceed nicely. However, in some cases (
|
type(self).thread_locals.transaction.__exit__(exception, None, None)
|
||||||
# deferred foreign key checks for exampl) it is still possible
|
|
||||||
# to rollback().
|
|
||||||
try:
|
|
||||||
transaction.commit()
|
|
||||||
except Exception:
|
|
||||||
# If the rollback fails, the transaction state will be
|
|
||||||
# messed up. It doesn't matter, the connection will be set
|
|
||||||
# to clean state after the request finishes. And, we can't
|
|
||||||
# clean the state here properly even if we wanted to, the
|
|
||||||
# connection is in transaction but we can't rollback...
|
|
||||||
transaction.rollback()
|
|
||||||
transaction.leave_transaction_management()
|
|
||||||
raise
|
|
||||||
transaction.leave_transaction_management()
|
|
||||||
|
|
||||||
def process_request(self, request):
|
def process_request(self, request):
|
||||||
""" Store request on a thread local variable """
|
""" Store request on a thread local variable """
|
||||||
type(self).thread_locals.request = request
|
type(self).thread_locals.request = request
|
||||||
# Enters transaction management
|
self.enter_transaction_management()
|
||||||
transaction.enter_transaction_management()
|
|
||||||
|
|
||||||
def process_exception(self, request, exception):
|
def process_exception(self, request, exception):
|
||||||
"""Rolls back the database and leaves transaction management"""
|
"""Rolls back the database and leaves transaction management"""
|
||||||
if transaction.is_dirty():
|
self.leave_transaction_management(exception)
|
||||||
# This rollback might fail because of network failure for example.
|
|
||||||
# If rollback isn't possible it is impossible to clean the
|
|
||||||
# connection's state. So leave the connection in dirty state and
|
|
||||||
# let request_finished signal deal with cleaning the connection.
|
|
||||||
transaction.rollback()
|
|
||||||
transaction.leave_transaction_management()
|
|
||||||
|
|
||||||
def process_response(self, request, response):
|
def process_response(self, request, response):
|
||||||
""" Processes pending backend operations """
|
""" Processes pending backend operations """
|
||||||
if not isinstance(response, HttpResponseServerError):
|
if not isinstance(response, HttpResponseServerError):
|
||||||
operations = type(self).get_pending_operations()
|
operations = type(self).get_pending_operations()
|
||||||
if operations:
|
if operations:
|
||||||
|
try:
|
||||||
scripts, block = manager.generate(operations)
|
scripts, block = manager.generate(operations)
|
||||||
|
except Exception as exception:
|
||||||
|
self.leave_transaction_management(exception)
|
||||||
|
raise
|
||||||
# We commit transaction just before executing operations
|
# We commit transaction just before executing operations
|
||||||
# because here is when IntegrityError show up
|
# because here is when IntegrityError show up
|
||||||
self.commit_transaction()
|
self.leave_transaction_management()
|
||||||
logs = manager.execute(scripts, block=block)
|
logs = manager.execute(scripts, block=block)
|
||||||
if logs and resolve(request.path).app_name == 'admin':
|
if logs and resolve(request.path).app_name == 'admin':
|
||||||
message_user(request, logs)
|
message_user(request, logs)
|
||||||
return response
|
return response
|
||||||
self.commit_transaction()
|
self.leave_transaction_management()
|
||||||
return response
|
return response
|
||||||
|
|
|
@ -94,7 +94,7 @@ class TransactionAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
||||||
filter_by_account_fields = ('bill', 'source')
|
filter_by_account_fields = ('bill', 'source')
|
||||||
change_readonly_fields = ('amount', 'currency')
|
change_readonly_fields = ('amount', 'currency')
|
||||||
readonly_fields = ('bill_link', 'display_state', 'process_link', 'account_link', 'source_link')
|
readonly_fields = ('bill_link', 'display_state', 'process_link', 'account_link', 'source_link')
|
||||||
list_select_related = ('account', 'source', 'bill__account')
|
list_select_related = ('source', 'bill__account')
|
||||||
|
|
||||||
bill_link = admin_link('bill')
|
bill_link = admin_link('bill')
|
||||||
source_link = admin_link('source')
|
source_link = admin_link('source')
|
||||||
|
|
|
@ -135,7 +135,7 @@ function install_requirements () {
|
||||||
ca-certificates \
|
ca-certificates \
|
||||||
gettext"
|
gettext"
|
||||||
|
|
||||||
PIP="django==1.7.7 \
|
PIP="django==1.8 \
|
||||||
django-celery-email==1.0.4 \
|
django-celery-email==1.0.4 \
|
||||||
django-fluent-dashboard==0.4 \
|
django-fluent-dashboard==0.4 \
|
||||||
https://bitbucket.org/izi/django-admin-tools/get/a0abfffd76a0.zip \
|
https://bitbucket.org/izi/django-admin-tools/get/a0abfffd76a0.zip \
|
||||||
|
@ -174,8 +174,8 @@ function install_requirements () {
|
||||||
freezegun \
|
freezegun \
|
||||||
coverage \
|
coverage \
|
||||||
orchestra-orm==dev \
|
orchestra-orm==dev \
|
||||||
django-debug-toolbar==1.2.1 \
|
django-debug-toolbar==1.3.0 \
|
||||||
django-nose==1.2 \
|
https://github.com/django-nose/django-nose/archive/master.zip \
|
||||||
sqlparse \
|
sqlparse \
|
||||||
pyinotify \
|
pyinotify \
|
||||||
--allow-external orchestra-orm --allow-unverified orchestra-orm"
|
--allow-external orchestra-orm --allow-unverified orchestra-orm"
|
||||||
|
|
|
@ -15,7 +15,7 @@ class MultiSelectField(models.CharField, metaclass=models.SubfieldBase):
|
||||||
'choices': self.choices
|
'choices': self.choices
|
||||||
}
|
}
|
||||||
if self.has_default():
|
if self.has_default():
|
||||||
defaults['initial'] = eval(self.get_default())
|
defaults['initial'] = self.get_default()
|
||||||
defaults.update(kwargs)
|
defaults.update(kwargs)
|
||||||
return MultiSelectFormField(**defaults)
|
return MultiSelectFormField(**defaults)
|
||||||
|
|
||||||
|
@ -27,13 +27,13 @@ class MultiSelectField(models.CharField, metaclass=models.SubfieldBase):
|
||||||
|
|
||||||
def to_python(self, value):
|
def to_python(self, value):
|
||||||
if value:
|
if value:
|
||||||
if isinstance(value, list) and value[0].startswith('('):
|
# if isinstance(value, tuple) and value[0].startswith('('):
|
||||||
# Workaround unknown bug on default model values
|
# # Workaround unknown bug on default model values
|
||||||
# [u"('SUPPORT'", u" 'ADMIN'", u" 'BILLING'", u" 'TECH'", u" 'ADDS'", u" 'EMERGENCY')"]
|
# # [u"('SUPPORT'", u" 'ADMIN'", u" 'BILLING'", u" 'TECH'", u" 'ADDS'", u" 'EMERGENCY')"]
|
||||||
value = list(eval(', '.join(value)))
|
# value = list(eval(', '.join(value)))
|
||||||
if isinstance(value, list):
|
if isinstance(value, str):
|
||||||
return value
|
|
||||||
return value.split(',')
|
return value.split(',')
|
||||||
|
return value
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def contribute_to_class(self, cls, name):
|
def contribute_to_class(self, cls, name):
|
||||||
|
|
Loading…
Reference in New Issue