Repository: ckan/ckan

Issue:
Unnecessary db request
In the package controller, self._get_package_type is used to determine which plugin to use when calling setup_template_variables.  _get_package_type does a model.Package.get() which is unnecessary, especially in cases where the controller action will fetch the package anyway.  

Should work out if we can remove the unnecessary call in each action, instead using package type from package_show results if it was called. 



Discussion:

Resolving patch:
diff --git a/ckan/controllers/package.py b/ckan/controllers/package.py
--- a/ckan/controllers/package.py
+++ b/ckan/controllers/package.py
@@ -325,7 +325,6 @@ def _content_type_from_accept(self):
         return ct, ext
 
     def resources(self, id):
-        package_type = self._get_package_type(id.split('@')[0])
         context = {'model': model, 'session': model.Session,
                    'user': c.user or c.author, 'for_view': True,
                    'auth_user_obj': c.userobj}
@@ -346,6 +345,7 @@ def resources(self, id):
         except NotAuthorized:
             abort(401, _('Unauthorized to read package %s') % id)
 
+        package_type = c.pkg_dict['type'] or 'dataset'
         self._setup_template_variables(context, {'id': id},
                                        package_type=package_type)
 
@@ -366,7 +366,6 @@ def read(self, id, format='html'):
 
         response.headers['Content-Type'] = ctype
 
-        package_type = self._get_package_type(id.split('@')[0])
         context = {'model': model, 'session': model.Session,
                    'user': c.user or c.author, 'for_view': True,
                    'auth_user_obj': c.userobj}
@@ -413,6 +412,7 @@ def read(self, id, format='html'):
                 context, {'id': resource['id']})
             resource['has_views'] = len(resource_views) > 0
 
+        package_type = c.pkg_dict['type'] or 'dataset'
         self._setup_template_variables(context, {'id': id},
                                        package_type=package_type)
 
@@ -432,7 +432,6 @@ def read(self, id, format='html'):
 
 
     def history(self, id):
-        package_type = self._get_package_type(id.split('@')[0])
 
         if 'diff' in request.params or 'selected1' in request.params:
             try:
@@ -508,6 +507,8 @@ def history(self, id):
             response.headers['Content-Type'] = 'application/atom+xml'
             return feed.writeString('utf-8')
 
+        package_type = c.pkg_dict['type'] or 'dataset'
+
         c.related_count = c.pkg.related_count
         return render(
             self._history_template(c.pkg_dict.get('type', package_type)),
@@ -581,7 +582,7 @@ def new(self, data=None, errors=None, error_summary=None):
 
     def resource_edit(self, id, resource_id, data=None, errors=None,
                       error_summary=None):
-        package_type = self._get_package_type(id)
+
         if request.method == 'POST' and not data:
             data = data or clean_dict(dict_fns.unflatten(tuplize_dict(parse_params(
                 request.POST))))
@@ -636,6 +637,8 @@ def resource_edit(self, id, resource_id, data=None, errors=None,
         if not data:
             data = resource_dict
 
+        package_type = pkg_dict['type'] or 'dataset'
+
         errors = errors or {}
         error_summary = error_summary or {}
         vars = {'data': data, 'errors': errors,
@@ -647,7 +650,6 @@ def resource_edit(self, id, resource_id, data=None, errors=None,
     def new_resource(self, id, data=None, errors=None, error_summary=None):
         ''' FIXME: This is a temporary action to allow styling of the
         forms. '''
-        package_type = self._get_package_type(id)
         if request.method == 'POST' and not data:
             save_action = request.params.get('save')
             data = data or clean_dict(dict_fns.unflatten(tuplize_dict(parse_params(
@@ -733,13 +735,7 @@ def new_resource(self, id, data=None, errors=None, error_summary=None):
                 # add more resources
                 redirect(h.url_for(controller='package',
                                    action='new_resource', id=id))
-        errors = errors or {}
-        error_summary = error_summary or {}
-        vars = {'data': data, 'errors': errors,
-                'error_summary': error_summary, 'action': 'new',
-                'resource_form_snippet': self._resource_form(package_type),
-                'dataset_type': package_type}
-        vars['pkg_name'] = id
+
         # get resources for sidebar
         context = {'model': model, 'session': model.Session,
                    'user': c.user or c.author, 'auth_user_obj': c.userobj}
@@ -752,6 +748,15 @@ def new_resource(self, id, data=None, errors=None, error_summary=None):
         except NotAuthorized:
             abort(401, _('Unauthorized to create a resource for this package'))
 
+        package_type = pkg_dict['type'] or 'dataset'
+
+        errors = errors or {}
+        error_summary = error_summary or {}
+        vars = {'data': data, 'errors': errors,
+                'error_summary': error_summary, 'action': 'new',
+                'resource_form_snippet': self._resource_form(package_type),
+                'dataset_type': package_type}
+        vars['pkg_name'] = id
         # required for nav menu
         vars['pkg_dict'] = pkg_dict
         template = 'package/new_resource_not_draft.html'
@@ -879,10 +884,8 @@ def history_ajax(self, id):
 
     def _get_package_type(self, id):
         """
-        Given the id of a package it determines the plugin to load
-        based on the package's type name (type). The plugin found
-        will be returned, or None if there is no plugin associated with
-        the type.
+        Given the id of a package this method will return the type of the
+        package, or 'dataset' if no type is currently set
         """
         pkg = model.Package.get(id)
         if pkg:


Test patch: