Permalink
Browse files

Merge remote branch 'origin/master' into rpgplanet

  • Loading branch information...
2 parents 4e487d6 + b3029f7 commit 21d1fb33d1c22514200b5c241f89688a02c9cce3 @Almad committed Aug 3, 2010
Showing with 6,365 additions and 1,478 deletions.
  1. +2 −1 ella/articles/models.py
  2. +1 −0 ella/core/box.py
  3. BIN ella/core/locale/cs/LC_MESSAGES/django.mo
  4. +1 −1 ella/core/locale/cs/LC_MESSAGES/django.po
  5. +60 −26 ella/core/managers.py
  6. +26 −4 ella/core/middleware.py
  7. +1 −0 ella/core/models/main.py
  8. +44 −0 ella/core/models/publishable.py
  9. +46 −8 ella/core/newman_admin.py
  10. +16 −6 ella/core/templatetags/core.py
  11. +33 −12 ella/core/templatetags/hits.py
  12. +4 −2 ella/core/views.py
  13. +5 −0 ella/ellaadmin/admin_media/js/editor.js
  14. +1 −1 ella/ellaadmin/fields.py
  15. +1 −1 ella/ellacomments/admin.py
  16. +0 −3 ella/ellacomments/views.py
  17. BIN ella/ellaexports/locale/cs/LC_MESSAGES/django.mo
  18. +83 −26 ella/ellaexports/locale/cs/LC_MESSAGES/django.po
  19. +37 −10 ella/ellaexports/managers.py
  20. +209 −0 ella/ellaexports/migrations/0004_aggregated_added.py
  21. +23 −0 ella/ellaexports/models.py
  22. +70 −14 ella/ellaexports/newman_admin.py
  23. +26 −10 ella/ellaexports/timeline.py
  24. +1 −1 ella/ellaexports/urls.py
  25. +15 −35 ella/ellaexports/views.py
  26. +33 −1 ella/newman/changelist.py
  27. +24 −11 ella/newman/config.py
  28. +1 −0 ella/newman/context_processors.py
  29. +1 −1 ella/newman/fields.py
  30. +157 −44 ella/newman/filterspecs.py
  31. +7 −0 ella/newman/forms.py
  32. BIN ella/newman/locale/cs/LC_MESSAGES/django.mo
  33. +264 −258 ella/newman/locale/cs/LC_MESSAGES/django.po
  34. BIN ella/newman/locale/cs/LC_MESSAGES/djangojs.mo
  35. +8 −0 ella/newman/locale/cs/LC_MESSAGES/djangojs.po
  36. +1 −1 ella/newman/management/commands/syncroles.py
  37. +121 −14 ella/newman/media/css/base.css
  38. +22 −0 ella/newman/media/css/frontend-tools.css
  39. BIN ella/newman/media/ico/64/application-exit.png
  40. BIN ella/newman/media/jquery/images/alerts/help.gif
  41. BIN ella/newman/media/jquery/images/alerts/important.gif
  42. BIN ella/newman/media/jquery/images/alerts/info.gif
  43. BIN ella/newman/media/jquery/images/alerts/title.gif
  44. +57 −0 ella/newman/media/jquery/jquery.alerts.css
  45. +235 −0 ella/newman/media/jquery/jquery.alerts.js
  46. +25 −15 ella/newman/media/js/datetime.js
  47. +17 −7 ella/newman/media/js/flash_image.js
  48. +309 −0 ella/newman/media/js/fuckitup.js
  49. +777 −0 ella/newman/media/js/fuckitup_install.js
  50. +40 −30 ella/newman/media/js/generic.suggest.js
  51. +84 −18 ella/newman/media/js/inheritance.js
  52. +601 −285 ella/newman/media/js/inlines.js
  53. +120 −72 ella/newman/media/js/kobayashi.js
  54. +158 −72 ella/newman/media/js/markitup/sets/markdown/set.js
  55. +14 −14 ella/newman/media/js/markitup/sets/markdown/style.css
  56. +456 −190 ella/newman/media/js/newman.js
  57. +102 −34 ella/newman/media/js/polls.js
  58. +73 −16 ella/newman/media/js/related_lookup.js
  59. +312 −0 ella/newman/media/js/utils.js
  60. +3 −3 ella/newman/middleware.py
  61. +70 −12 ella/newman/newman_admin.py
  62. +66 −27 ella/newman/options.py
  63. +39 −14 ella/newman/sites.py
  64. +12 −3 ella/newman/templates/newman/base.html
  65. +5 −5 ella/newman/templates/newman/change_form.html
  66. +42 −4 ella/newman/templates/newman/change_list.html
  67. +45 −0 ella/newman/templates/newman/edit_inline/exportmeta_inline.html
  68. +22 −15 ella/newman/templates/newman/edit_inline/gallery_item.html
  69. +0 −1 ella/newman/templates/newman/edit_inline/placement.html
  70. +0 −1 ella/newman/templates/newman/edit_inline/poll_question.html
  71. +2 −0 ella/newman/templates/newman/edit_inline/stacked.html
  72. +33 −24 ella/newman/templates/newman/ellaexports/timeline.html
  73. +10 −0 ella/newman/templates/newman/filters.html
  74. +28 −22 ella/newman/templates/newman/login.html
  75. +13 −0 ella/newman/templates/newman/main-categories-filter.html
  76. +4 −20 ella/newman/templates/newman/newman-index.html
  77. +60 −0 ella/newman/templates/newman/tpl_tags/newman_frontend_admin.html
  78. +3 −0 ella/newman/templates/newman/tpl_tags/search_form.html
  79. +1 −1 ella/newman/templates/newman/tpl_tags/submit_line.html
  80. +8 −3 ella/newman/templates/newman/widget/editor_box.html
  81. +24 −7 ella/newman/templatetags/newman.py
  82. +70 −0 ella/newman/templatetags/newman_frontend_tags.py
  83. +4 −2 ella/newman/widgets.py
  84. +16 −0 ella/newman/xoptions.py
  85. +2 −2 ella/photos/formatter.py
  86. +4 −2 ella/photos/models.py
  87. +25 −2 ella/photos/newman_admin.py
  88. +2 −0 ella/polls/models.py
  89. +3 −1 ella/series/models.py
  90. +3 −2 ella/series/newman_admin.py
  91. +2 −2 ella/series/templatetags/series.py
  92. +21 −0 ella/utils/text.py
  93. +86 −0 tests/example_project/services/fixtures/example_data.xml
  94. +22 −28 tests/example_project/settings/base.py
  95. BIN tests/example_project/static/photos/2010/05/10/eighth_example.jpg
  96. BIN tests/example_project/static/photos/2010/05/10/fifth_example.jpg
  97. BIN tests/example_project/static/photos/2010/05/10/first_example.jpg
  98. BIN tests/example_project/static/photos/2010/05/10/fourth_example.jpg
  99. BIN tests/example_project/static/photos/2010/05/10/second_example.jpg
  100. BIN tests/example_project/static/photos/2010/05/10/seventh_example.jpg
  101. BIN tests/example_project/static/photos/2010/05/10/sixth_example.jpg
  102. BIN tests/example_project/static/photos/2010/05/10/third_example.jpg
  103. BIN tests/example_project/static/photos/2010/05/10/thumb-first_example.jpg
  104. BIN tests/example_project/static/photos/2010/05/10/thumb-fourth_example.jpg
  105. BIN tests/example_project/static/photos/2010/05/10/thumb-second_example.jpg
  106. BIN tests/example_project/static/photos/2010/05/10/thumb-third_example.jpg
  107. +20 −5 tests/example_project/tests/test_newman/helpers.py
  108. +67 −4 tests/example_project/tests/test_newman/test_articles.py
  109. +473 −2 tests/example_project/tests/test_newman/test_galleries.py
  110. +111 −0 tests/example_project/tests/test_newman/test_surveys.py
  111. +1 −4 tests/example_project/urls.py
  112. +97 −1 tests/unit_project/test_core/__init__.py
  113. +34 −0 tests/unit_project/test_core/test_placement.py
  114. +74 −1 tests/unit_project/test_core/test_templatetags.py
  115. +14 −14 tests/unit_project/test_exports/test_exports.py
View
@@ -7,9 +7,9 @@
from ella.core.models import Publishable
from ella.core.cache import get_cached_list
-
class InfoBox(models.Model):
"""Defines embedable text model."""
+
title = models.CharField(_('Title'), max_length=255)
created = models.DateTimeField(_('Created'), default=datetime.now, editable=False)
updated = models.DateTimeField(_('Updated'), blank=True, null=True)
@@ -23,6 +23,7 @@ class Meta:
verbose_name = _('Info box')
verbose_name_plural = _('Info boxes')
+
class Article(Publishable):
"""Defines article model."""
upper_title = models.CharField(_('Upper title'), max_length=255, blank=True)
View
@@ -93,6 +93,7 @@ def get_context(self):
'css_class' : self.params.get('css_class', ''),
'name' : self.params.get('name', ''),
'text' : self.params.get('text', ''),
+ 'align' : self.params.get('align', 'left'),
'box' : self,
}
Binary file not shown.
@@ -50,7 +50,7 @@ msgid ""
"There is already a Placement object published in\n"
" category %(category)s with the same URL referring to %(target)s.\n"
" Please change the slug or publish date."
-msgstr ""
+msgstr "Zkuste změnit slug nebo datum publikace. Publikace se shodnou URL již existuje v kategorii \"%(category)s\" pro objekt \"%(target)s\" ."
#: admin.py:189
#: newman_admin.py:197
View
@@ -1,7 +1,7 @@
-from datetime import datetime
+from datetime import datetime, timedelta
from django.db import models
-from django.db.models import F
+from django.db.models import F, Q
from django.conf import settings
from django.contrib.contenttypes.models import ContentType
from django.utils.encoding import smart_str
@@ -11,6 +11,7 @@
DEFAULT_LISTING_PRIORITY = getattr(settings, 'DEFAULT_LISTING_PRIORITY', 0)
+USE_PRIORITIES = getattr(settings, 'USE_PRIORITIES', False)
class RelatedManager(models.Manager):
@@ -158,8 +159,30 @@ def get_listing(self, category=None, children=NONE, count=10, offset=1, mods=[],
offset - starting with object number... 1-based
mods - list of Models, if empty, object from all models are included
[now] - datetime used instead of default datetime.now() value
+ [unique] - set of already listed Placement IDs
**kwargs - rest of the parameter are passed to the queryset unchanged
"""
+ def mark_before_output(output):
+ for l in output:
+ listed_targets.add(l.placement_id)
+
+ def make_items_unique(qset):
+
+ out = []
+ listed_targets_now = set()
+ for l in qset:
+ tgt = l.placement_id
+ if tgt in listed_targets or tgt in listed_targets_now:
+ continue
+ listed_targets_now.add(tgt)
+ out.append(l)
+ if len(out) == limit:
+ result = out[offset:limit]
+ mark_before_output(result)
+ return result
+ mark_before_output(out)
+ return out
+
# TODO try to write SQL (.extra())
assert offset > 0, "Offset must be a positive integer"
assert count >= 0, "Count must be a positive integer"
@@ -176,8 +199,16 @@ def get_listing(self, category=None, children=NONE, count=10, offset=1, mods=[],
offset -= 1
limit = offset + count
+ # take out unwanted objects
+ if unique:
+ listed_targets = unique.copy()
+ else:
+ listed_targets = set([])
+
# only use priorities if somebody wants them
- if not getattr(settings, 'USE_PRIORITIES', False):
+ if not USE_PRIORITIES:
+ if unique:
+ return make_items_unique(qset)
return qset[offset:limit]
@@ -200,24 +231,17 @@ def get_listing(self, category=None, children=NONE, count=10, offset=1, mods=[],
out = []
- # take out not unwanted objects
- if unique:
- listed_targets = unique.copy()
- else:
- listed_targets = set([])
-
# iterate through qsets until we have enough objects
for q in qsets:
- data = q[:limit]
- if data:
- for l in data:
- tgt = l.placement_id
- if tgt in listed_targets:
- continue
- listed_targets.add(tgt)
- out.append(l)
- if len(out) == limit:
- return out[offset:limit]
+ data = q.iterator()
+ for l in data:
+ tgt = l.placement_id
+ if tgt in listed_targets:
+ continue
+ listed_targets.add(tgt)
+ out.append(l)
+ if len(out) == limit:
+ return out[offset:limit]
return out[offset:offset + count]
def get_queryset_wrapper(self, kwargs):
@@ -243,9 +267,9 @@ def count(self):
return self._count
-def get_top_objects_key(func, self, count, mods=[]):
- return 'ella.core.managers.HitCountManager.get_top_objects_key:%d:%d:%s' % (
- settings.SITE_ID, count, ','.join('.'.join(str(model._meta) for model in mods))
+def get_top_objects_key(func, self, count, days=None, mods=[]):
+ return 'ella.core.managers.HitCountManager.get_top_objects_key:%d:%d:%s:%s' % (
+ settings.SITE_ID, count, str(days), ','.join('.'.join(str(model._meta) for model in mods))
)
class HitCountManager(models.Manager):
@@ -257,11 +281,21 @@ def hit(self, placement):
hc = self.create(placement=placement, hits=1)
@cache_this(get_top_objects_key)
- def get_top_objects(self, count, mods=[]):
+ def get_top_objects(self, count, days=None, mods=[]):
"""
Return count top rated objects. Cache this for 10 minutes without any chance of cache invalidation.
"""
- kwa = {}
+ qset = self.filter(placement__category__site=settings.SITE_ID).order_by('-hits')
+
if mods:
- kwa['placement__publishable__content_type__in'] = [ ContentType.objects.get_for_model(m) for m in mods ]
- return list(self.filter(placement__category__site=settings.SITE_ID, **kwa).order_by('-hits')[:count])
+ qset = qset.filter(placement__publishable__content_type__in = [ ContentType.objects.get_for_model(m) for m in mods ])
+
+ now = datetime.now()
+ if days is None:
+ qset = qset.filter(placement__publish_from__lte=now)
+ else:
+ start = now - timedelta(days=days)
+ qset = qset.filter(placement__publish_from__range=(start, now,))
+ qset = qset.filter(Q(placement__publish_to__gt=now) | Q(placement__publish_to__isnull=True))
+
+ return list(qset[:count])
View
@@ -1,4 +1,5 @@
import time
+import re
import logging
log = logging.getLogger('ella.core.middleware')
@@ -8,23 +9,44 @@
from django.utils.cache import get_cache_key, add_never_cache_headers, learn_cache_key
from django.conf import settings
-
-
ECACHE_INFO = 'ella.core.middleware.ECACHE_INFO'
DOUBLE_RENDER = getattr(settings, 'DOUBLE_RENDER', False)
+DOUBLE_RENDER_EXCLUDE_URLS = getattr(settings, 'DOUBLE_RENDER_EXCLUDE_URLS', None)
class DoubleRenderMiddleware(object):
+
+ def _get_excluded_urls(self):
+ if hasattr(self, '_excluded_urls'):
+ return self._excluded_urls
+
+ if DOUBLE_RENDER_EXCLUDE_URLS is None:
+ self._excluded_urls = None
+ return None
+
+ self._excluded_urls = ()
+ for url in DOUBLE_RENDER_EXCLUDE_URLS:
+ self._excluded_urls += (re.compile(url),)
+
+ return self._excluded_urls
+
def process_response(self, request, response):
- if response.status_code != 200 or not response['Content-Type'].startswith('text') or not DOUBLE_RENDER:
+ if response.status_code != 200 \
+ or not response['Content-Type'].startswith('text') \
+ or not DOUBLE_RENDER:
return response
+ if self._get_excluded_urls() is not None:
+ for pattern in self._get_excluded_urls():
+ if pattern.match(request.path):
+ return response
+
try:
c = template.RequestContext(request, {'SECOND_RENDER': True})
t = template.Template(response.content)
response.content = t.render(c)
except Exception, e:
- log.warning('Failed to double render on (%s)', e)
+ log.warning('Failed to double render on (%s)', unicode(e).encode('utf8'))
return response
class CacheMiddleware(DjangoCacheMiddleware):
View
@@ -159,6 +159,7 @@ class Meta:
unique_together = (('site', 'tree_path'),)
verbose_name = _('Category')
verbose_name_plural = _('Categories')
+ ordering = ('site__name', 'tree_path',)
@cache_this(get_category_key)
def __unicode__(self):
@@ -206,8 +206,52 @@ def delete(self):
self.publishable.publish_from = publish_from
Publishable.objects.filter(pk=self.publishable_id).update(publish_from=publish_from)
+ @staticmethod
+ def check_placement_is_unique(placement):
+ obj = placement
+ cat = None
+ if obj.pk:
+ cat = getattr(obj, 'category', None)
+ obj_slug = getattr(obj, 'slug', obj.pk)
+ # if Placement has no slug, slug from Publishable object should be considered in following checks:
+ if not obj_slug:
+ obj_slug = obj.publishable.slug
+
+ # try and find conflicting placement
+ qset = Placement.objects.filter(
+ category=obj.category,
+ slug=obj_slug,
+ static=obj.static
+ )
+ if obj.static: # allow placements that do not overlap
+ q = models.Q(publish_to__lt=obj.publish_from)
+ if obj.publish_to:
+ q |= models.Q(publish_from__gt=obj.publish_to)
+ qset = qset.exclude(q)
+ # check for same date in URL
+ if not obj.static:
+ qset = qset.filter(
+ publish_from__year=obj.publish_from.year,
+ publish_from__month=obj.publish_from.month,
+ publish_from__day=obj.publish_from.day,
+ )
+ # exclude current object from search
+ if obj.pk:
+ qset = qset.exclude(pk=obj.pk)
+ if qset:
+ plac = qset[0]
+ raise ValueError(
+ _('''There is already a Placement object published in
+ category %(category)s with the same URL referring to %(target)s.
+ Please change the slug or publish date.''') % {
+ 'category' : plac.category,
+ 'target' : plac.publishable,
+ })
+
def save(self, **kwargs):
" If Listing is created, we create HitCount object "
+ # perform validation here
+ Placement.check_placement_is_unique(self)
if not self.slug:
self.slug = self.publishable.slug
Oops, something went wrong.

0 comments on commit 21d1fb3

Please sign in to comment.