Updated to DJango 1.8

This commit is contained in:
Marc Aymerich 2015-04-03 13:03:08 +00:00
parent 4a8a77715c
commit 751dda7126
9 changed files with 42 additions and 63 deletions

11
TODO.md
View file

@ -313,16 +313,15 @@ celery max-tasks-per-child
* 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
* gevent is not ported to 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?
* implement delete All related services
* address name change does not remove old one :P

View file

@ -9,7 +9,7 @@ class UsedContentTypeFilter(SimpleListFilter):
def lookups(self, request, model_admin):
qset = model_admin.model._default_manager.all().order_by()
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()),)
return result

View file

@ -165,9 +165,9 @@ class BillAdmin(AccountAdminMixin, ExtendedModelAdmin):
transactions = bill.transactions.all()
if len(transactions) == 1:
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:
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
state = bill.get_payment_state_display().upper()
color = PAYMENT_STATE_COLORS.get(bill.payment_state, 'grey')

View file

@ -92,7 +92,7 @@ class ReadOnlySQLPasswordHashField(ReadOnlyPasswordHashField):
summary = mark_safe("<strong>%s</strong>" % _("No password set."))
else:
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
if value.startswith('*'):
summary = "<strong>algorithm</strong>: sha1_bin_hex %s" % summary

View file

@ -60,7 +60,7 @@ class DomainInline(admin.TabularInline):
class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin):
list_display = (
'structured_name', 'display_is_top', 'websites', 'account_link'
'structured_name', 'display_is_top', 'display_websites', 'account_link'
)
add_fields = ('name', 'account')
fields = ('name', 'account_link')
@ -85,7 +85,7 @@ class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin):
display_is_top.boolean = True
display_is_top.admin_order_field = 'top'
def websites(self, domain):
def display_websites(self, domain):
if apps.isinstalled('orchestra.apps.websites'):
webs = domain.websites.all()
if webs:
@ -95,9 +95,9 @@ class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin):
links.append('<a href="%s">%s</a>' % (url, web.name))
return '<br>'.join(links)
return _("No website")
websites.admin_order_field = 'websites__name'
websites.short_description = _("Websites")
websites.allow_tags = True
display_websites.admin_order_field = 'websites__name'
display_websites.short_description = _("Websites")
display_websites.allow_tags = True
def get_queryset(self, request):
""" Order by structured name and imporve performance """

View file

@ -38,10 +38,7 @@ class OperationsMiddleware(object):
Stores all the operations derived from save and delete signals and executes them
at the end of the request/response cycle
It also works as a transaction middleware. Each view function will be run
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.
It also works as a transaction middleware, making requets to run within an atomic block.
"""
# Thread local is used because request object is not available on model signals
thread_locals = local()
@ -77,55 +74,38 @@ class OperationsMiddleware(object):
instance = kwargs.pop('instance')
manager.collect(instance, action, **kwargs)
def commit_transaction(self):
if not transaction.get_autocommit():
if transaction.is_dirty():
# Note: it is possible that the commit fails. If the reason is
# closed connection or some similar reason, then there is
# little hope to proceed nicely. However, in some cases (
# 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 enter_transaction_management(self):
type(self).thread_locals.transaction = transaction.atomic()
type(self).thread_locals.transaction.__enter__()
def leave_transaction_management(self, exception=None):
type(self).thread_locals.transaction.__exit__(exception, None, None)
def process_request(self, request):
""" Store request on a thread local variable """
type(self).thread_locals.request = request
# Enters transaction management
transaction.enter_transaction_management()
self.enter_transaction_management()
def process_exception(self, request, exception):
"""Rolls back the database and leaves transaction management"""
if transaction.is_dirty():
# 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()
self.leave_transaction_management(exception)
def process_response(self, request, response):
""" Processes pending backend operations """
if not isinstance(response, HttpResponseServerError):
operations = type(self).get_pending_operations()
if operations:
scripts, block = manager.generate(operations)
try:
scripts, block = manager.generate(operations)
except Exception as exception:
self.leave_transaction_management(exception)
raise
# We commit transaction just before executing operations
# because here is when IntegrityError show up
self.commit_transaction()
self.leave_transaction_management()
logs = manager.execute(scripts, block=block)
if logs and resolve(request.path).app_name == 'admin':
message_user(request, logs)
return response
self.commit_transaction()
self.leave_transaction_management()
return response

View file

@ -94,7 +94,7 @@ class TransactionAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
filter_by_account_fields = ('bill', 'source')
change_readonly_fields = ('amount', 'currency')
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')
source_link = admin_link('source')

View file

@ -135,7 +135,7 @@ function install_requirements () {
ca-certificates \
gettext"
PIP="django==1.7.7 \
PIP="django==1.8 \
django-celery-email==1.0.4 \
django-fluent-dashboard==0.4 \
https://bitbucket.org/izi/django-admin-tools/get/a0abfffd76a0.zip \
@ -174,8 +174,8 @@ function install_requirements () {
freezegun \
coverage \
orchestra-orm==dev \
django-debug-toolbar==1.2.1 \
django-nose==1.2 \
django-debug-toolbar==1.3.0 \
https://github.com/django-nose/django-nose/archive/master.zip \
sqlparse \
pyinotify \
--allow-external orchestra-orm --allow-unverified orchestra-orm"

View file

@ -15,7 +15,7 @@ class MultiSelectField(models.CharField, metaclass=models.SubfieldBase):
'choices': self.choices
}
if self.has_default():
defaults['initial'] = eval(self.get_default())
defaults['initial'] = self.get_default()
defaults.update(kwargs)
return MultiSelectFormField(**defaults)
@ -27,13 +27,13 @@ class MultiSelectField(models.CharField, metaclass=models.SubfieldBase):
def to_python(self, value):
if value:
if isinstance(value, list) and value[0].startswith('('):
# Workaround unknown bug on default model values
# [u"('SUPPORT'", u" 'ADMIN'", u" 'BILLING'", u" 'TECH'", u" 'ADDS'", u" 'EMERGENCY')"]
value = list(eval(', '.join(value)))
if isinstance(value, list):
return value
return value.split(',')
# if isinstance(value, tuple) and value[0].startswith('('):
# # Workaround unknown bug on default model values
# # [u"('SUPPORT'", u" 'ADMIN'", u" 'BILLING'", u" 'TECH'", u" 'ADDS'", u" 'EMERGENCY')"]
# value = list(eval(', '.join(value)))
if isinstance(value, str):
return value.split(',')
return value
return []
def contribute_to_class(self, cls, name):