Commit 9c9a2e7737d14e583db322267a6cd9e4ec813510
Exists in
master
and in
13 other branches
Merge branch 'master' of github.com:TracyWebTech/colab
Showing
12 changed files
with
11 additions
and
140 deletions
Show diff stats
requirements.txt
src/colab/custom_settings.py
| ... | ... | @@ -107,6 +107,7 @@ INSTALLED_APPS = INSTALLED_APPS + ( |
| 107 | 107 | 'django_browserid', |
| 108 | 108 | 'conversejs', |
| 109 | 109 | 'haystack', |
| 110 | + 'hitcounter', | |
| 110 | 111 | |
| 111 | 112 | # Own apps |
| 112 | 113 | 'super_archives', |
| ... | ... | @@ -116,7 +117,6 @@ INSTALLED_APPS = INSTALLED_APPS + ( |
| 116 | 117 | 'accounts', |
| 117 | 118 | 'proxy', |
| 118 | 119 | 'search', |
| 119 | - 'hitcount', | |
| 120 | 120 | |
| 121 | 121 | # Feedzilla and deps |
| 122 | 122 | 'feedzilla', | ... | ... |
src/hitcount/__init__.py
src/hitcount/admin.py
src/hitcount/migrations/0001_initial.py
| ... | ... | @@ -1,53 +0,0 @@ |
| 1 | -# -*- coding: utf-8 -*- | |
| 2 | -import datetime | |
| 3 | -from south.db import db | |
| 4 | -from south.v2 import SchemaMigration | |
| 5 | -from django.db import models | |
| 6 | - | |
| 7 | - | |
| 8 | -class Migration(SchemaMigration): | |
| 9 | - | |
| 10 | - def forwards(self, orm): | |
| 11 | - # Adding model 'Hit' | |
| 12 | - db.create_table(u'hitcount_hit', ( | |
| 13 | - (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), | |
| 14 | - ('created', self.gf('django.db.models.fields.DateField')(auto_now_add=True, db_index=True, blank=True)), | |
| 15 | - ('updated', self.gf('django.db.models.fields.DateField')(auto_now=True, db_index=True, blank=True)), | |
| 16 | - ('hits', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)), | |
| 17 | - ('content_type', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['contenttypes.ContentType'])), | |
| 18 | - ('object_pk', self.gf('django.db.models.fields.CharField')(max_length=256)), | |
| 19 | - )) | |
| 20 | - db.send_create_signal(u'hitcount', ['Hit']) | |
| 21 | - | |
| 22 | - # Adding unique constraint on 'Hit', fields ['content_type', 'object_pk'] | |
| 23 | - db.create_unique(u'hitcount_hit', ['content_type_id', 'object_pk']) | |
| 24 | - | |
| 25 | - | |
| 26 | - def backwards(self, orm): | |
| 27 | - # Removing unique constraint on 'Hit', fields ['content_type', 'object_pk'] | |
| 28 | - db.delete_unique(u'hitcount_hit', ['content_type_id', 'object_pk']) | |
| 29 | - | |
| 30 | - # Deleting model 'Hit' | |
| 31 | - db.delete_table(u'hitcount_hit') | |
| 32 | - | |
| 33 | - | |
| 34 | - models = { | |
| 35 | - u'contenttypes.contenttype': { | |
| 36 | - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, | |
| 37 | - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | |
| 38 | - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | |
| 39 | - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | |
| 40 | - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) | |
| 41 | - }, | |
| 42 | - u'hitcount.hit': { | |
| 43 | - 'Meta': {'unique_together': "(('content_type', 'object_pk'),)", 'object_name': 'Hit'}, | |
| 44 | - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), | |
| 45 | - 'created': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}), | |
| 46 | - 'hits': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), | |
| 47 | - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | |
| 48 | - 'object_pk': ('django.db.models.fields.CharField', [], {'max_length': '256'}), | |
| 49 | - 'updated': ('django.db.models.fields.DateField', [], {'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}) | |
| 50 | - } | |
| 51 | - } | |
| 52 | - | |
| 53 | - complete_apps = ['hitcount'] | |
| 54 | 0 | \ No newline at end of file |
src/hitcount/migrations/__init__.py
src/hitcount/models.py
| ... | ... | @@ -1,55 +0,0 @@ |
| 1 | - | |
| 2 | -from django.db import models | |
| 3 | -from django.core.cache import cache | |
| 4 | -from django.contrib.contenttypes import generic | |
| 5 | -from django.contrib.contenttypes.models import ContentType | |
| 6 | - | |
| 7 | - | |
| 8 | -class Hit(models.Model): | |
| 9 | - created = models.DateField(auto_now_add=True, db_index=True) | |
| 10 | - updated = models.DateField(auto_now=True, db_index=True) | |
| 11 | - hits = models.PositiveIntegerField(default=0) | |
| 12 | - content_type = models.ForeignKey(ContentType) | |
| 13 | - object_pk = models.CharField(max_length=256) | |
| 14 | - | |
| 15 | - class Meta: | |
| 16 | - unique_together = ('content_type', 'object_pk') | |
| 17 | - | |
| 18 | - | |
| 19 | -class HitCountModelMixin(object): | |
| 20 | - | |
| 21 | - @property | |
| 22 | - def hits(self): | |
| 23 | - content_type = ContentType.objects.get_for_model(self.__class__, | |
| 24 | - for_concrete_model=False) | |
| 25 | - try: | |
| 26 | - hit = Hit.objects.get(content_type=content_type, | |
| 27 | - object_pk=self.pk) | |
| 28 | - except Hit.DoesNotExist: | |
| 29 | - return 0 | |
| 30 | - | |
| 31 | - return hit.hits | |
| 32 | - | |
| 33 | - def hit(self, request=None): | |
| 34 | - content_type = ContentType.objects.get_for_model(self.__class__) | |
| 35 | - | |
| 36 | - # Here we cache the user's IP to ensure that the same | |
| 37 | - # IP won't hit the same page again for while | |
| 38 | - if request: | |
| 39 | - ip_addr = request.META.get('REMOTE_ADDR') | |
| 40 | - cache_key = u'page_hits-{}-{}-{}'.format(ip_addr, | |
| 41 | - content_type, self.pk) | |
| 42 | - duplicate = cache.get(cache_key) | |
| 43 | - if duplicate: | |
| 44 | - return | |
| 45 | - cache.set(cache_key, True) | |
| 46 | - | |
| 47 | - # Everything ok, so just increment the page count | |
| 48 | - hit_pk = Hit.objects.get_or_create(content_type=content_type, | |
| 49 | - object_pk=self.pk)[0].pk | |
| 50 | - | |
| 51 | - # Using this way instead of hits += 1 forces django to | |
| 52 | - # call the UPDATE directly in the database avoiding | |
| 53 | - # cuncurrency problems | |
| 54 | - Hit.objects.filter(pk=hit_pk).update(hits=models.F("hits") + 1) | |
| 55 | - |
src/hitcount/tests.py
src/hitcount/views.py
| ... | ... | @@ -1,16 +0,0 @@ |
| 1 | -from django.shortcuts import render | |
| 2 | - | |
| 3 | -class HitCountViewMixin(object): | |
| 4 | - def get_object(self, *args, **kwargs): | |
| 5 | - try: | |
| 6 | - super(HitCountViewMixin, self).get_object(*args, **kwargs) | |
| 7 | - except AttributeError: | |
| 8 | - raise NotImplementedError | |
| 9 | - | |
| 10 | - def dispatch(self, request, *args, **kwargs): | |
| 11 | - response = super(HitCountViewMixin, self).dispatch(request, | |
| 12 | - *args, **kwargs) | |
| 13 | - if 200 <= response.status_code < 300: | |
| 14 | - obj = self.get_object() | |
| 15 | - if obj: obj.hit(request) | |
| 16 | - return response |
src/proxy/models.py
| ... | ... | @@ -7,10 +7,10 @@ from django.conf import settings |
| 7 | 7 | from django.db import models |
| 8 | 8 | |
| 9 | 9 | from accounts.models import User |
| 10 | -from hitcount.models import HitCountModelMixin | |
| 10 | +from hitcounter.models import HitCounterModelMixin | |
| 11 | 11 | |
| 12 | 12 | |
| 13 | -class Attachment(models.Model, HitCountModelMixin): | |
| 13 | +class Attachment(models.Model, HitCounterModelMixin): | |
| 14 | 14 | url = models.TextField(primary_key=True) |
| 15 | 15 | attach_id = models.TextField() |
| 16 | 16 | used_by = models.TextField() |
| ... | ... | @@ -44,7 +44,7 @@ class Attachment(models.Model, HitCountModelMixin): |
| 44 | 44 | return None |
| 45 | 45 | |
| 46 | 46 | |
| 47 | -class Revision(models.Model, HitCountModelMixin): | |
| 47 | +class Revision(models.Model, HitCounterModelMixin): | |
| 48 | 48 | key = models.TextField(blank=True, primary_key=True) |
| 49 | 49 | rev = models.TextField(blank=True) |
| 50 | 50 | author = models.TextField(blank=True) |
| ... | ... | @@ -65,7 +65,7 @@ class Revision(models.Model, HitCountModelMixin): |
| 65 | 65 | except User.DoesNotExist: |
| 66 | 66 | return None |
| 67 | 67 | |
| 68 | -class Ticket(models.Model, HitCountModelMixin): | |
| 68 | +class Ticket(models.Model, HitCounterModelMixin): | |
| 69 | 69 | id = models.IntegerField(primary_key=True) |
| 70 | 70 | summary = models.TextField(blank=True) |
| 71 | 71 | description = models.TextField(blank=True) |
| ... | ... | @@ -96,7 +96,7 @@ class Ticket(models.Model, HitCountModelMixin): |
| 96 | 96 | return None |
| 97 | 97 | |
| 98 | 98 | |
| 99 | -class Wiki(models.Model, HitCountModelMixin): | |
| 99 | +class Wiki(models.Model, HitCounterModelMixin): | |
| 100 | 100 | name = models.TextField(primary_key=True) |
| 101 | 101 | wiki_text = models.TextField(blank=True) |
| 102 | 102 | author = models.TextField(blank=True) | ... | ... |
src/proxy/views.py
| ... | ... | @@ -5,13 +5,13 @@ from django.conf import settings |
| 5 | 5 | |
| 6 | 6 | from revproxy.views import ProxyView |
| 7 | 7 | from .models import Wiki, Ticket, Revision |
| 8 | -from hitcount.views import HitCountViewMixin | |
| 8 | +from hitcounter.views import HitCounterViewMixin | |
| 9 | 9 | |
| 10 | 10 | |
| 11 | 11 | CWD = os.path.abspath(os.path.dirname(__file__)) |
| 12 | 12 | DIAZO_RULES_DIR = os.path.join(CWD, 'diazo') |
| 13 | 13 | |
| 14 | -class TracProxyView(HitCountViewMixin, ProxyView): | |
| 14 | +class TracProxyView(HitCounterViewMixin, ProxyView): | |
| 15 | 15 | base_url = settings.COLAB_TRAC_URL |
| 16 | 16 | add_remote_user = settings.REVPROXY_ADD_REMOTE_USER |
| 17 | 17 | diazo_theme_template = 'proxy/trac.html' | ... | ... |
src/super_archives/models.py
| ... | ... | @@ -14,7 +14,7 @@ from django.utils.translation import ugettext_lazy as _ |
| 14 | 14 | from html2text import html2text |
| 15 | 15 | from haystack.query import SearchQuerySet |
| 16 | 16 | from taggit.managers import TaggableManager |
| 17 | -from hitcount.models import HitCountModelMixin | |
| 17 | +from hitcounter.models import HitCounterModelMixin | |
| 18 | 18 | |
| 19 | 19 | from .utils import blocks |
| 20 | 20 | from .utils.etiquetador import etiquetador |
| ... | ... | @@ -108,7 +108,7 @@ class Keyword(models.Model): |
| 108 | 108 | return self.keyword |
| 109 | 109 | |
| 110 | 110 | |
| 111 | -class Thread(models.Model, HitCountModelMixin): | |
| 111 | +class Thread(models.Model, HitCounterModelMixin): | |
| 112 | 112 | |
| 113 | 113 | subject_token = models.CharField(max_length=512) |
| 114 | 114 | mailinglist = models.ForeignKey(MailingList, | ... | ... |