Skip to content

Commit

Permalink
Merge pull request #1513 from digi604/multidb_test
Browse files Browse the repository at this point in the history
Multidb testing for travis
  • Loading branch information
digi604 committed Dec 20, 2012
2 parents 314eedc + 113e386 commit 9c70a95
Show file tree
Hide file tree
Showing 24 changed files with 682 additions and 675 deletions.
16 changes: 13 additions & 3 deletions .travis.yml
Expand Up @@ -4,12 +4,22 @@ python:
- "2.6"
- "2.7"
env:
- DJANGO=test_requirements/django-1.3.txt
- DJANGO=test_requirements/django-1.4.txt
- DJANGO=test_requirements/django-1.3.txt DB='sqlite://localhost/:memory:'
- DJANGO=test_requirements/django-1.3.txt DB='mysql://root@127.0.0.1/djangocms_test'
- DJANGO=test_requirements/django-1.3.txt DB='postgres://postgres@127.0.0.1/djangocms_test'
- DJANGO=test_requirements/django-1.4.txt DB='sqlite://localhost/:memory:'
- DJANGO=test_requirements/django-1.4.txt DB='mysql://root@127.0.0.1/djangocms_test'
- DJANGO=test_requirements/django-1.4.txt DB='postgres://postgres@127.0.0.1/djangocms_test'

before_script:
- sh -c "if [ '$DB' = 'postgres://postgres@127.0.0.1/djangocms_test' ]; then psql -c 'DROP DATABASE IF EXISTS djangocms_test;' -U postgres; fi"
- sh -c "if [ '$DB' = 'postgres://postgres@127.0.0.1/djangocms_test' ]; then psql -c 'create database djangocms_test;' -U postgres; fi"
- sh -c "if [ '$DB' = 'mysql://root@127.0.0.1/djangocms_test' ]; then mysql -e 'create database IF NOT EXISTS djangocms_test CHARACTER SET utf8 COLLATE utf8_general_ci;'; fi"

install:
- pip install -q -r $DJANGO --use-mirrors
script:
python runtests.py
python runtests.py --db $DB
notifications:
email:
recipients:
Expand Down
2 changes: 1 addition & 1 deletion cms/models/managers.py
Expand Up @@ -340,7 +340,7 @@ def for_page(self, page):
"""
# permissions should be managed on the draft page only
page = page.get_draft_object()
from cms.models import ACCESS_DESCENDANTS, ACCESS_CHILDREN,\
from cms.models import ACCESS_DESCENDANTS, ACCESS_CHILDREN, \
ACCESS_PAGE_AND_CHILDREN, ACCESS_PAGE_AND_DESCENDANTS
# code taken from
# https://github.com/divio/django-cms/issues/1113#issuecomment-3376790
Expand Down
29 changes: 18 additions & 11 deletions cms/models/pagemodel.py
Expand Up @@ -20,6 +20,7 @@
from menus.menu_pool import menu_pool
from mptt.models import MPTTModel
from os.path import join
from datetime import timedelta
import copy


Expand Down Expand Up @@ -71,8 +72,8 @@ class Page(MPTTModel):
# Publisher fields
moderator_state = models.SmallIntegerField(_('moderator state'), default=0, blank=True, editable=False)
publisher_is_draft = models.BooleanField(default=1, editable=False, db_index=True)
#This is misnamed - the one-to-one relation is populated on both ends
publisher_public = models.OneToOneField('self', related_name='publisher_draft', null=True, editable=False)
# This is misnamed - the one-to-one relation is populated on both ends
publisher_public = models.OneToOneField('self', related_name='publisher_draft', null=True, editable=False)
publisher_state = models.SmallIntegerField(default=0, editable=False, db_index=True)

# Managers
Expand Down Expand Up @@ -134,7 +135,7 @@ def move_page(self, target, position='first-child'):
import cms.signals as cms_signals
cms_signals.page_moved.send(sender=Page, instance=self) # titles get saved before moderation
self.save() # always save the page after move, because of publisher
moderator.page_changed(self, force_moderation_action = PageModeratorState.ACTION_MOVE)
moderator.page_changed(self, force_moderation_action=PageModeratorState.ACTION_MOVE)
# check the slugs
page_utils.check_title_slugs(self)

Expand Down Expand Up @@ -302,7 +303,7 @@ def copy_page(self, target, site, position='first-child',

# invalidate the menu for this site
menu_pool.clear(site_id=site.pk)
return page_copy # return the page_copy or None
return page_copy # return the page_copy or None

def save(self, no_signals=False, commit=True, **kwargs):
"""
Expand All @@ -318,7 +319,7 @@ def save(self, no_signals=False, commit=True, **kwargs):
# Published pages should always have a publication date
# if the page is published we set the publish date if not set yet.
if self.publication_date is None and self.published:
self.publication_date = timezone.now()
self.publication_date = timezone.now() - timedelta(seconds=5)

if self.reverse_id == "":
self.reverse_id = None
Expand Down Expand Up @@ -371,6 +372,8 @@ def publish(self):

if not self.pk:
self.save()
if not self.parent_id:
self.clear_home_pk_cache()
if self._publisher_can_publish():
if self.publisher_public_id:
# Ensure we have up to date mptt properties
Expand Down Expand Up @@ -462,7 +465,7 @@ def unpublish(self):
if not self.publisher_is_draft:
raise PublicIsUnmodifiable('The public instance cannot be unpublished. Use draft.')

#First, make sure we are in the correct state
# First, make sure we are in the correct state
self.published = False
self.save()
public_page = self.get_public_object()
Expand Down Expand Up @@ -533,7 +536,7 @@ def delete_with_public(self):
"""
descendants = list(self.get_descendants().order_by('level'))
descendants.reverse()
#TODO: Use a better exception class - PermissionDenied is not quite right
# TODO: Use a better exception class - PermissionDenied is not quite right
for page in descendants:
if not page.delete_requested():
raise PermissionDenied('There are descendant pages not marked for deletion')
Expand Down Expand Up @@ -593,7 +596,7 @@ def get_cached_ancestors(self, ascending=True):
self.ancestors_descending = list(self.get_ancestors(ascending))
return self.ancestors_descending

### Title object access
# ## Title object access

def get_title_obj(self, language=None, fallback=True, version_id=None, force_reload=False):
"""Helper function for accessing wanted / current title.
Expand Down Expand Up @@ -776,7 +779,7 @@ def has_view_permission(self, request):
return (user_perm or generic_perm)

else:
#anonymous user
# anonymous user
if is_restricted or not settings.CMS_PUBLIC_FOR == 'all':
# anyonymous user, page has restriction and global access is permitted
return False
Expand Down Expand Up @@ -860,15 +863,19 @@ def is_home(self):

def get_home_pk_cache(self):
attr = "%s_home_pk_cache_%s" % (self.publisher_is_draft and "draft" or "public", self.site_id)
if not hasattr(self, attr):
if getattr(self, attr, None) is None:
setattr(self, attr, self.get_object_queryset().get_home(self.site).pk)
return getattr(self, attr)

def set_home_pk_cache(self, value):

attr = "%s_home_pk_cache_%s" % (self.publisher_is_draft and "draft" or "public", self.site_id)
setattr(self, attr, value)
home_pk_cache = property(get_home_pk_cache, set_home_pk_cache)

def clear_home_pk_cache(self):
self.home_pk_cache = None

def get_media_path(self, filename):
"""
Returns path (relative to MEDIA_ROOT/MEDIA_URL) to directory for storing page-scope files.
Expand Down Expand Up @@ -1022,7 +1029,7 @@ def _publisher_save_public(self, obj):
prev_sibling = self.get_previous_filtered_sibling(**filters)
public_prev_sib = prev_sibling.publisher_public if prev_sibling else None

if not self.publisher_public_id: # first time published
if not self.publisher_public_id: # first time published
# is there anybody on left side?
if public_prev_sib:
obj.insert_at(public_prev_sib, position='right', save=False)
Expand Down
15 changes: 0 additions & 15 deletions cms/models/query.py
Expand Up @@ -68,21 +68,6 @@ def expired(self):
return self.on_site().filter(
publication_end_date__lte=timezone.now())

# - seems this is not used anymore...
# def get_pages_with_application(self, path, language):
# """Returns all pages containing application for current path, or
# any parrent. Returned list is sorted by path length, longer path first.
# """
# paths = levelize_path(path)
# q = Q()
# for path in paths:
# # build q for all the paths
# q |= Q(title_set__path=path, title_set__language=language)
# app_pages = self.published().filter(q & Q(title_set__application_urls__gt='')).distinct()
# # add proper ordering
# app_pages.query.order_by.extend(('LENGTH(`cms_title`.`path`) DESC',))
# return app_pages

def get_all_pages_with_application(self):
"""Returns all pages containing applications for all sites.
Expand Down
7 changes: 1 addition & 6 deletions cms/models/titlemodels.py
Expand Up @@ -31,12 +31,6 @@ class Meta:
def __unicode__(self):
return u"%s (%s, %s)" % (self.title, self.slug, self.language)

def save(self, *args, **kwargs):
# Update the path attribute before saving
# No longer needed since this is done in signals
#self.update_path()
super(Title, self).save(*args, **kwargs)

def update_path(self):
# Build path from parent page's path and slug
slug = u'%s' % self.slug
Expand All @@ -48,6 +42,7 @@ def update_path(self):
parent_title = Title.objects.get_title(parent_page, language=self.language, language_fallback=True)
if parent_title:
self.path = u'%s/%s' % (parent_title.path, slug)


@property
def overwrite_url(self):
Expand Down
80 changes: 33 additions & 47 deletions cms/signals.py
Expand Up @@ -6,10 +6,11 @@

from cms.cache.permissions import (
clear_user_permission_cache, clear_permission_cache)
from cms.models import (Page, Title, CMSPlugin, PagePermission,
from cms.models import (Page, Title, CMSPlugin, PagePermission,
GlobalPagePermission, PageUser, PageUserGroup)

from menus.menu_pool import menu_pool
from cms.models.permissionmodels import PageUserGroup

# fired after page location is changed - is moved from one node to other
page_moved = Signal(providing_args=["instance"])
Expand All @@ -20,7 +21,7 @@
# fired after page gets published - copied to public model - there may be more
# than one instances published before this signal gets called
post_publish = Signal(providing_args=["instance"])

def update_plugin_positions(**kwargs):
plugin = kwargs['instance']
plugins = CMSPlugin.objects.filter(language=plugin.language, placeholder=plugin.placeholder).order_by("position")
Expand All @@ -39,13 +40,13 @@ def update_title_paths(instance, **kwargs):
"""
for title in instance.title_set.all():
title.save()

page_moved.connect(update_title_paths, sender=Page, dispatch_uid="cms.title.update_path")


def update_title(title):
slug = u'%s' % title.slug

if title.page.is_home():
title.path = ''
elif not title.has_url_overwrite:
Expand All @@ -61,52 +62,55 @@ def update_title(title):
def pre_save_title(instance, raw, **kwargs):
"""Save old state to instance and setup path
"""

if not instance.page.publisher_is_draft:

menu_pool.clear(instance.page.site_id)



if instance.id and not hasattr(instance, "tmp_path"):
instance.tmp_path = None
instance.tmp_application_urls = None
try:
instance.tmp_path, instance.tmp_application_urls = \
Title.objects.filter(pk=instance.id).values_list('path', 'application_urls')[0]
except IndexError:
pass # no Titles exist for this page yet
pass # no Titles exist for this page yet

# Build path from parent page's path and slug
if instance.has_url_overwrite and instance.path:
instance.path = instance.path.strip(" /")
else:
update_title(instance)

signals.pre_save.connect(pre_save_title, sender=Title, dispatch_uid="cms.title.presave")


def post_save_title(instance, raw, created, **kwargs):
# Update descendants only if path changed
application_changed = False
prevent_descendants = hasattr(instance, 'tmp_prevent_descendant_update')
if instance.path != getattr(instance,'tmp_path',None) and not prevent_descendants:
if instance.path != getattr(instance, 'tmp_path', None) and not prevent_descendants:
descendant_titles = Title.objects.filter(
page__lft__gt=instance.page.lft,
page__rght__lt=instance.page.rght,
page__lft__gt=instance.page.lft,
page__rght__lt=instance.page.rght,
page__tree_id__exact=instance.page.tree_id,
language=instance.language,
has_url_overwrite=False,
).order_by('page__tree_id', 'page__parent', 'page__lft')

for descendant_title in descendant_titles:
descendant_title.path = '' # just reset path
descendant_title.path = '' # just reset path
descendant_title.tmp_prevent_descendant_update = True
if descendant_title.application_urls:
application_changed = True
descendant_title.save()

if not prevent_descendants and \
(instance.application_urls != getattr(instance, 'tmp_application_urls', None) or application_changed):
# fire it if we have some application linked to this page or some descendant
application_post_changed.send(sender=Title, instance=instance)

# remove temporary attributes
if hasattr(instance, 'tmp_path'):
del instance.tmp_path
Expand All @@ -115,7 +119,7 @@ def post_save_title(instance, raw, created, **kwargs):
if prevent_descendants:
del instance.tmp_prevent_descendant_update

signals.post_save.connect(post_save_title, sender=Title, dispatch_uid="cms.title.postsave")
signals.post_save.connect(post_save_title, sender=Title, dispatch_uid="cms.title.postsave")


def post_save_user(instance, raw, created, **kwargs):
Expand All @@ -131,22 +135,12 @@ def post_save_user(instance, raw, created, **kwargs):
if not creator or not created or not hasattr(creator, 'pk'):
return
from django.db import connection

# i'm not sure if there is a workaround for this, somebody any ideas? What
# we are doing here is creating PageUser on Top of existing user, i'll do it
# through plain SQL, its not nice, but...

# TODO: find a better way than an raw sql !!

cursor = connection.cursor()
query = "INSERT INTO %s (user_ptr_id, created_by_id) VALUES (%d, %d)" % (
PageUser._meta.db_table,
instance.pk,
creator.pk
)
cursor.execute(query)
cursor.close()


page_user = PageUser(user_ptr_id=instance.pk, created_by=creator)
page_user.__dict__.update(instance.__dict__)
page_user.save()


def post_save_user_group(instance, raw, created, **kwargs):
"""The same like post_save_user, but for Group, required only when
CMS_PERMISSION.
Expand All @@ -160,19 +154,11 @@ def post_save_user_group(instance, raw, created, **kwargs):
creator = get_current_user()
if not creator or not created or creator.is_anonymous():
return
from django.db import connection

# TODO: same as in post_save_user - raw sql is just not nice - workaround...?

cursor = connection.cursor()
query = "INSERT INTO %s (group_ptr_id, created_by_id) VALUES (%d, %d)" % (
PageUserGroup._meta.db_table,
instance.pk,
creator.pk
)
cursor.execute(query)
cursor.close()


page_user = PageUserGroup(user_ptr_id=instance.pk, created_by=creator)
page_user.__dict__.update(instance.__dict__)
page_user.save()

if settings.CMS_PERMISSION:
# only if permissions are in use
from django.contrib.auth.models import User, Group
Expand All @@ -191,7 +177,7 @@ def pre_save_page(instance, raw, **kwargs):
pass


def post_save_page_moderator(instance, raw, created, **kwargs):
def post_save_page_moderator(instance, raw, created, **kwargs):
"""Helper post save signal.
"""
old_page = instance.old_page
Expand All @@ -200,7 +186,7 @@ def post_save_page_moderator(instance, raw, created, **kwargs):
from cms.utils.moderator import page_changed
if not old_page:
page_changed(instance, old_page)

def post_save_page(instance, **kwargs):
if instance.old_page is None or instance.old_page.parent_id != instance.parent_id:
for page in instance.get_descendants():
Expand Down

0 comments on commit 9c70a95

Please sign in to comment.