Skip to content
This repository has been archived by the owner on Feb 21, 2020. It is now read-only.

Commit

Permalink
making room for django-activity-stream
Browse files Browse the repository at this point in the history
  • Loading branch information
Eduardo Robles Elvira committed Apr 5, 2012
1 parent 6877350 commit 9a2a7bb
Show file tree
Hide file tree
Showing 11 changed files with 173 additions and 70 deletions.
5 changes: 5 additions & 0 deletions INSTALL
Expand Up @@ -40,6 +40,11 @@ available yet

$ ./manage.py loaddata initial-data.json

Agora relies in django-reversion for storing historical data. To make it work,
you first need to create the initialize it:

$ ./manage.py createinitialrevisions

That's it! Start the webserver with:

$ ./manage.py runserver
Expand Down
38 changes: 20 additions & 18 deletions VISION.txt
Expand Up @@ -2,28 +2,29 @@

These are the different things that should be registered as activity:

* Agora X was created by User Y
* Agora X was closed by User Y
* Agora X biography was modified by User Y
* Agora X settings were modified by User Y

* User X joined Agora Y
* User X leaved Agora Y
* Agora X was created by User Y: actor=userY, verb="created", object=agoraX
* Agora X was closed by User Y: actor=user, verb="closed", object=agoraX
* Agora X biography was modified by User Y: actor=userY, verb="modified biography", object=agoraX
* Agora X settings were modified by User Y: actor=userY, verb="modified settings", object=agoraX

* Election Y in Agora Z created by User X
* Election Y in Agora Z modified by User X
* Election Y in Agora Z was confirmed by User X
* Election X in Agora Y finished, winning option was Z with ZZ % of votes
* User X joined Agora Y: actor=userX, verb="joined", object=agoraY
* User X leaved Agora Y: actor=userX, verb="leaved", object=agoraY

* User X voted in election Y in Agora Z
* User X updated his vote in election Y in Agora Z
* User X delegated in User Y in Agora Z
* User X removed his delegation in User Y in Agora Z
* Election Y in Agora Z created by User X: actor=userX, verb="created", object=electionY, target=agoraZ
* Election Y in Agora Z modified by User X: actor=userX, verb="modifed", object=electionY, target=agoraZ
* Election Y in Agora Z was confirmed by User X: actor=userX, verb="confirmed", object=electionY, target=agoraZ
* Election X in Agora Y finished, winning option was Z with ZZ % of votes: actor=adminsX, verb="published results", object=electionY, target=agoraZ

* User X commented on Agora Y
* User X commented on Voting Y from Agora Z
* User X commented on User Y
* User X updated his biography
* User X voted in election Y in Agora Z: actor=userX, verb="voted", object=electionY, target=agoraZ
* User X updated his vote in election Y in Agora Z: actor=userX, verb="changed his vote", object=electionY, target=agoraZ
* User X delegated in User Y in Agora Z: actor=userX, verb="delegated", object=userY, target=agoraZ
* User X removed his delegation in User Y in Agora Z: actor=userX, verb="removed delegation", object=userY, target=agoraZ

* User X commented on Agora Y: actor=userX, verb="commented", object=agoraY
* User X commented on Voting Y from Agora Z: actor=userX, verb="commented", object=votingY, target=agoraZ
* User X commented on User Y: actor=userX, verb="commented", object=userY
* User X updated his biography: actor=userX, verb="updated his biography"

Filtering can be done from relevant log items. Relevant log items are:

Expand All @@ -39,3 +40,4 @@ For an agora timeline:
For an election timeline:
* updates related to the election
* delegations in the agora related to the election

10 changes: 6 additions & 4 deletions agora_site/agora_core/admin.py
Expand Up @@ -20,14 +20,16 @@
from django.contrib.auth.models import User, Group
from django.contrib.auth.admin import UserAdmin
from agora_site.agora_core.models import Profile, Agora, Election, CastVote
from reversion.admin import VersionAdmin

admin.site.unregister(User)

class ProfileInline(admin.StackedInline):
model = Profile

class ProfileAdmin(UserAdmin):
class ProfileAdmin(VersionAdmin):
inlines = [ProfileInline]
model = User
fieldsets = (
(None, {'fields': ('username', 'password')}),
(_('Personal info'), {'fields': ('first_name', 'last_name', 'email')}),
Expand All @@ -38,8 +40,8 @@ class ProfileAdmin(UserAdmin):

admin.site.register(User, ProfileAdmin)

admin.site.register(Agora)
admin.site.register(Agora, VersionAdmin)

admin.site.register(Election)
admin.site.register(Election, VersionAdmin)

admin.site.register(CastVote)
admin.site.register(CastVote, VersionAdmin)
56 changes: 18 additions & 38 deletions agora_site/agora_core/migrations/0001_initial.py
Expand Up @@ -15,18 +15,11 @@ def forwards(self, orm):
('short_description', self.gf('django.db.models.fields.CharField')(max_length=140)),
('biography', self.gf('django.db.models.fields.TextField')()),
('user_type', self.gf('django.db.models.fields.CharField')(default='PASSWORD', max_length=50)),
('last_activity_read_date', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
('extra', self.gf('agora_site.misc.utils.JSONField')(null=True)),
))
db.send_create_signal('agora_core', ['Profile'])

# Adding M2M table for field followers on 'Profile'
db.create_table('agora_core_profile_followers', (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('from_profile', models.ForeignKey(orm['agora_core.profile'], null=False)),
('to_profile', models.ForeignKey(orm['agora_core.profile'], null=False))
))
db.create_unique('agora_core_profile_followers', ['from_profile_id', 'to_profile_id'])

# Adding model 'Agora'
db.create_table('agora_core_agora', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
Expand Down Expand Up @@ -63,14 +56,6 @@ def forwards(self, orm):
))
db.create_unique('agora_core_agora_admins', ['agora_id', 'user_id'])

# Adding M2M table for field followers on 'Agora'
db.create_table('agora_core_agora_followers', (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('agora', models.ForeignKey(orm['agora_core.agora'], null=False)),
('user', models.ForeignKey(orm['auth.user'], null=False))
))
db.create_unique('agora_core_agora_followers', ['agora_id', 'user_id'])

# Adding model 'Election'
db.create_table('agora_core_election', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
Expand Down Expand Up @@ -103,14 +88,6 @@ def forwards(self, orm):
))
db.send_create_signal('agora_core', ['Election'])

# Adding M2M table for field followers on 'Election'
db.create_table('agora_core_election_followers', (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('election', models.ForeignKey(orm['agora_core.election'], null=False)),
('user', models.ForeignKey(orm['auth.user'], null=False))
))
db.create_unique('agora_core_election_followers', ['election_id', 'user_id'])

# Adding M2M table for field electorate on 'Election'
db.create_table('agora_core_election_electorate', (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
Expand Down Expand Up @@ -144,9 +121,6 @@ def backwards(self, orm):
# Deleting model 'Profile'
db.delete_table('agora_core_profile')

# Removing M2M table for field followers on 'Profile'
db.delete_table('agora_core_profile_followers')

# Deleting model 'Agora'
db.delete_table('agora_core_agora')

Expand All @@ -156,15 +130,9 @@ def backwards(self, orm):
# Removing M2M table for field admins on 'Agora'
db.delete_table('agora_core_agora_admins')

# Removing M2M table for field followers on 'Agora'
db.delete_table('agora_core_agora_followers')

# Deleting model 'Election'
db.delete_table('agora_core_election')

# Removing M2M table for field followers on 'Election'
db.delete_table('agora_core_election_followers')

# Removing M2M table for field electorate on 'Election'
db.delete_table('agora_core_election_electorate')

Expand All @@ -173,6 +141,20 @@ def backwards(self, orm):


models = {
'actstream.action': {
'Meta': {'ordering': "('-timestamp',)", 'object_name': 'Action'},
'action_object_content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'action_object'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
'action_object_object_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
'actor_content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actor'", 'to': "orm['contenttypes.ContentType']"}),
'actor_object_id': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'target_content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'target'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
'target_object_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
'timestamp': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'verb': ('django.db.models.fields.CharField', [], {'max_length': '255'})
},
'agora_core.agora': {
'Meta': {'object_name': 'Agora'},
'admins': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'adminstrated_agoras'", 'symmetrical': 'False', 'to': "orm['auth.User']"}),
Expand All @@ -184,7 +166,6 @@ def backwards(self, orm):
'election_type': ('django.db.models.fields.CharField', [], {'default': "'ONCE_CHOICE'", 'max_length': '50'}),
'eligibility': ('agora_site.misc.utils.JSONField', [], {'null': 'True'}),
'extra_data': ('agora_site.misc.utils.JSONField', [], {'null': 'True'}),
'followers': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'followed_agoras'", 'symmetrical': 'False', 'to': "orm['auth.User']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'image_url': ('django.db.models.fields.URLField', [], {'default': "''", 'max_length': '200', 'blank': 'True'}),
'is_vote_secret': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
Expand Down Expand Up @@ -220,7 +201,6 @@ def backwards(self, orm):
'electorate': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'elections'", 'symmetrical': 'False', 'to': "orm['auth.User']"}),
'eligibility': ('agora_site.misc.utils.JSONField', [], {'null': 'True'}),
'extra_data': ('agora_site.misc.utils.JSONField', [], {'null': 'True'}),
'followers': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'followed_elections'", 'symmetrical': 'False', 'to': "orm['auth.User']"}),
'frozen_at_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
'hash': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
Expand All @@ -241,8 +221,8 @@ def backwards(self, orm):
'Meta': {'object_name': 'Profile'},
'biography': ('django.db.models.fields.TextField', [], {}),
'extra': ('agora_site.misc.utils.JSONField', [], {'null': 'True'}),
'followers': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'followers_rel_+'", 'to': "orm['agora_core.Profile']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'last_activity_read_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'short_description': ('django.db.models.fields.CharField', [], {'max_length': '140'}),
'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}),
'user_type': ('django.db.models.fields.CharField', [], {'default': "'PASSWORD'", 'max_length': '50'})
Expand All @@ -262,15 +242,15 @@ def backwards(self, orm):
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2012, 4, 4, 23, 52, 48, 983915)'}),
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2012, 4, 5, 16, 40, 44, 310482)'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2012, 4, 4, 23, 52, 48, 983824)'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2012, 4, 5, 16, 40, 44, 310405)'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
Expand Down
20 changes: 11 additions & 9 deletions agora_site/agora_core/models.py
@@ -1,4 +1,4 @@
# Copyright (C) 2010 Eduardo Robles Elvira <edulix AT wadobo DOT com>
# Copyright (C) 2012 Eduardo Robles Elvira <edulix AT wadobo DOT com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
Expand All @@ -17,6 +17,12 @@
from django.contrib.auth.models import User
from django.utils.translation import ugettext_lazy as _
from agora_site.misc.utils import JSONField
from reversion.models import Revision

import reversion
from actstream.models import Follow
if reversion.is_registered(Follow):
reversion.unregister(Follow)

class Profile(models.Model):
'''
Expand All @@ -41,8 +47,10 @@ class Profile(models.Model):

user_type = models.CharField(max_length=50, choices=USER_TYPES, default=USER_TYPES[0][0])

followers = models.ManyToManyField('self', related_name='followed_users',
verbose_name=_('Followers'))
# This marks the date of the last activity item known to be read by the user
# so that later on we can for example send to the user update email only
# showing activity from this date on
last_activity_read_date = models.DateTimeField(_(u'Last Activity Read Date'), auto_now_add=True, editable=True)

# Stores extra data
# it will something like:
Expand Down Expand Up @@ -117,9 +125,6 @@ class Agora(models.Model):
admins = models.ManyToManyField(User, related_name='adminstrated_agoras',
verbose_name=_('Administrators'))

followers = models.ManyToManyField(User, related_name='followed_agoras',
verbose_name=_('Followers'))

# Stores extra data
# it will something like:
#{
Expand Down Expand Up @@ -148,9 +153,6 @@ class Election(models.Model):
creator = models.ForeignKey(User, related_name='created_elections',
verbose_name=_('Creator'), blank=False)

followers = models.ManyToManyField(User, related_name='followed_elections',
verbose_name=_('Followers'))

# We might need to freeze the list of voters so that if someone signs in,
# he cannot vote.
# NOTE that on a voting of type SIMPLE_DELEGATION, the list is unused,
Expand Down
21 changes: 21 additions & 0 deletions agora_site/agora_core/urls.py
@@ -0,0 +1,21 @@
# Copyright (C) 2012 Eduardo Robles Elvira <edulix AT wadobo DOT com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

from django.conf.urls.defaults import *
from agora_site.agora_core.views import TestView

urlpatterns = patterns('',
(r'^test_view', TestView.as_view()),
)
43 changes: 43 additions & 0 deletions agora_site/agora_core/views.py
@@ -0,0 +1,43 @@
# Copyright (C) 2012 Eduardo Robles Elvira <edulix AT wadobo DOT com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

from django.conf.urls import patterns, url, include
from django.views.generic import TemplateView
from django.views.generic import ListView
from django import http
from django.utils import simplejson as json
from django.contrib.auth.models import User
import reversion

class TestView(TemplateView):
template_name = 'base.html'

def render_to_response(self, context):

#user = User.objects.all()[0]
#print reversion.get_unique_for_object(user)
#with reversion.create_revision():
#user.last_name = user.last_name + ", aa"
#user.save()
#reversion.set_user(user)
#reversion.set_comment("Comment text...")

#print reversion.get_unique_for_object(user)

return super(TestView, self).render_to_response(context)

#@method_decorator(login_required)
def dispatch(self, *args, **kwargs):
return super(TestView, self).dispatch(*args, **kwargs)
14 changes: 14 additions & 0 deletions agora_site/settings.py
Expand Up @@ -104,13 +104,27 @@
'django.contrib.messages',
'django.contrib.admin',
'django.contrib.admindocs',
'django.contrib.comments',
'reversion',
'south',
'guardian',
'rosetta',
'actstream',
'agora_site.agora_core',
)

# A list the models that you want to enable actions for. Models must be in the
# format app_label.model_name . In the background, django-activity-stream sets
# up GenericRelations to handle stream generation.
# More info: http://justquick.github.com/django-activity-stream/configuration.html

ACTSTREAM_ACTION_MODELS = [
'auth.User',
'agora_core.Agora',
'agora_core.Election',
'agora_core.CastVote',
]

# Modify the defaults to use BCrypt by default, because it's more secure, better
# for long term password storage
PASSWORD_HASHERS = (
Expand Down

0 comments on commit 9a2a7bb

Please sign in to comment.