Skip to content

Commit

Permalink
[#2941] Add /dataset/follow/* and /dataset/unfollow/*
Browse files Browse the repository at this point in the history
So you can follow and unfollow datasets without javascript.
  • Loading branch information
Sean Hammond committed Oct 4, 2012
1 parent f6a5271 commit 76d7013
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 12 deletions.
2 changes: 2 additions & 0 deletions ckan/config/routing.py
Expand Up @@ -195,6 +195,8 @@ def make_map():
'read_ajax',
'history_ajax',
'followers',
'follow',
'unfollow',
'delete',
'api_data',
]))
Expand Down
35 changes: 35 additions & 0 deletions ckan/controllers/package.py
Expand Up @@ -1188,6 +1188,41 @@ def api_data(self, id=None):
url = h.url_for('datastore_read', id=id, qualified=True)
return render('package/resource_api_data.html', {'datastore_root_url': url})

def follow(self, id):
'''Start following this dataset.'''
context = {'model': model,
'session': model.Session,
'user': c.user or c.author}
data_dict = {'id': id}
try:
get_action('follow_dataset')(context, data_dict)
h.flash_success(_("You are now following {0}").format(id))
except ValidationError as e:
error_message = (e.extra_msg or e.message or e.error_summary
or e.error_dict)
h.flash_error(error_message)
except NotAuthorized as e:
h.flash_error(e.extra_msg)
h.redirect_to(controller='package', action='read', id=id)

def unfollow(self, id):
'''Stop following this dataset.'''
context = {'model': model,
'session': model.Session,
'user': c.user or c.author}
data_dict = {'id': id}
try:
get_action('unfollow_dataset')(context, data_dict)
h.flash_success(_("You are no longer following {0}").format(id))
except ValidationError as e:
error_message = (e.extra_msg or e.message or e.error_summary
or e.error_dict)
h.flash_error(error_message)
except (NotFound, NotAuthorized) as e:
error_message = e.extra_msg or e.message
h.flash_error(error_message)
h.redirect_to(controller='package', action='read', id=id)

def followers(self, id=None):
context = {'model': model, 'session': model.Session,
'user': c.user or c.author, 'for_view': True}
Expand Down
23 changes: 13 additions & 10 deletions ckan/logic/action/create.py
Expand Up @@ -968,41 +968,44 @@ def follow_dataset(context, data_dict):
'''

if not context.has_key('user'):
raise logic.NotAuthorized
raise logic.NotAuthorized(
_("You must be logged in to follow a dataset."))

model = context['model']
session = context['session']

userobj = model.User.get(context['user'])
if not userobj:
raise logic.NotAuthorized
raise logic.NotAuthorized(
_("You must be logged in to follow a dataset."))

schema = (context.get('schema')
or ckan.logic.schema.default_follow_dataset_schema())

data_dict, errors = _validate(data_dict, schema, context)
validated_data_dict, errors = _validate(data_dict, schema, context)

if errors:
model.Session.rollback()
raise ValidationError(errors)

# Don't let a user follow a dataset she is already following.
if model.UserFollowingDataset.get(userobj.id, data_dict['id']) is not None:
if model.UserFollowingDataset.is_following(userobj.id,
validated_data_dict['id']):
message = _(
'You are already following {id}').format(id=data_dict['id'])
raise ValidationError({'message': message})

'You are already following {0}').format(data_dict['id'])
raise ValidationError({'message': message}, error_summary=message)

follower = model_save.user_following_dataset_dict_save(data_dict, context)
follower = model_save.user_following_dataset_dict_save(
validated_data_dict, context)

activity_dict = {
'user_id': userobj.id,
'object_id': data_dict['id'],
'object_id': validated_data_dict['id'],
'activity_type': 'follow dataset',
}
activity_dict['data'] = {
'dataset': ckan.lib.dictization.table_dictize(
model.Package.get(data_dict['id']), context),
model.Package.get(validated_data_dict['id']), context),
}
activity_create_context = {
'model': model,
Expand Down
25 changes: 25 additions & 0 deletions ckan/logic/converters.py
Expand Up @@ -105,3 +105,28 @@ def convert_user_name_or_id_to_id(user_name_or_id, context):
if not result:
raise Invalid('%s: %s' % (_('Not found'), _('User')))
return result.id

def convert_package_name_or_id_to_id(package_name_or_id, context):
'''Return the package id for the given package name or id.
The point of this function is to convert package names to ids. If you have
something that may be a package name or id you can pass it into this
function and get the id out either way.
Also validates that a package with the given name or id exists.
:returns: the id of the package with the given name or id
:rtype: string
:raises: ckan.lib.navl.dictization_functions.Invalid if there is no
package with the given name or id
'''
session = context['session']
result = session.query(model.Package).filter_by(
id=package_name_or_id).first()
if not result:
result = session.query(model.Package).filter_by(
name=package_name_or_id).first()
if not result:
raise Invalid('%s: %s' % (_('Not found'), _('Dataset')))
return result.id
5 changes: 3 additions & 2 deletions ckan/logic/schema.py
Expand Up @@ -40,7 +40,8 @@
activity_type_exists,
tag_not_in_vocabulary,
url_validator)
from ckan.logic.converters import (convert_user_name_or_id_to_id,)
from ckan.logic.converters import (convert_user_name_or_id_to_id,
convert_package_name_or_id_to_id,)
from formencode.validators import OneOf
import ckan.model

Expand Down Expand Up @@ -425,5 +426,5 @@ def default_follow_user_schema():

def default_follow_dataset_schema():
schema = {'id': [not_missing, not_empty, unicode,
package_id_or_name_exists]}
convert_package_name_or_id_to_id]}
return schema

0 comments on commit 76d7013

Please sign in to comment.