Commit 8902a89f by Don Mitchell

Have urls.py fully parse locator url

parent 6ba0208f
......@@ -61,7 +61,7 @@ class TestCourseIndex(CourseTestCase):
Test the error conditions for the access
"""
locator = loc_mapper().translate_location(self.course.location.course_id, self.course.location, False, True)
outline_url = reverse('contentstore.views.course_handler', kwargs={'course_url': unicode(locator)})
outline_url = locator.url_reverse('course/', '')
# register a non-staff member and try to delete the course branch
non_staff_client, _ = self.createNonStaffAuthedUserClient()
response = non_staff_client.delete(outline_url, {}, HTTP_ACCEPT='application/json')
......
......@@ -60,7 +60,7 @@ __all__ = ['create_new_course', 'course_info', 'course_handler',
@login_required
def course_handler(request, course_url):
def course_handler(request, tag=None, course_id=None, branch=None, version_guid=None, block=None):
"""
The restful handler for course specific requests.
It provides the course tree with the necessary information for identifying and labeling the parts. The root
......@@ -84,7 +84,10 @@ def course_handler(request, course_url):
if 'application/json' in request.META.get('HTTP_ACCEPT', 'application/json'):
if request.method == 'GET':
raise NotImplementedError('coming soon')
elif not has_access(request.user, BlockUsageLocator(course_url)):
elif not has_access(
request.user,
BlockUsageLocator(course_id=course_id, branch=branch, version_guid=version_guid, usage_id=block)
):
raise PermissionDenied()
elif request.method == 'POST':
raise NotImplementedError()
......@@ -95,7 +98,7 @@ def course_handler(request, course_url):
else:
return HttpResponseBadRequest()
elif request.method == 'GET': # assume html
return course_index(request, course_url)
return course_index(request, course_id, branch, version_guid, block)
else:
return HttpResponseNotFound()
......@@ -108,18 +111,18 @@ def old_course_index_shim(request, org, course, name):
"""
old_location = Location(['i4x', org, course, 'course', name])
locator = loc_mapper().translate_location(old_location.course_id, old_location, False, True)
return course_index(request, locator)
return course_index(request, locator.course_id, locator.branch, locator.version_guid, locator.usage_id)
@login_required
@ensure_csrf_cookie
def course_index(request, course_url):
def course_index(request, course_id, branch, version_guid, block):
"""
Display an editable course overview.
org, course, name: Attributes of the Location for the item to edit
"""
location = BlockUsageLocator(course_url)
location = BlockUsageLocator(course_id=course_id, branch=branch, version_guid=version_guid, usage_id=block)
# TODO: when converting to split backend, if location does not have a usage_id,
# we'll need to get the course's root block_id
if not has_access(request.user, location):
......
......@@ -47,12 +47,13 @@ def index(request):
def format_course_for_view(course):
# published = false b/c studio manipulates draft versions not b/c the course isn't pub'd
course_url = loc_mapper().translate_location(
course_loc = loc_mapper().translate_location(
course.location.course_id, course.location, published=False, add_entry_if_missing=True
)
return (
course.display_name,
reverse("contentstore.views.course_handler", kwargs={'course_url': course_url}),
# note, couldn't get django reverse to work; so, wrote workaround
course_loc.url_reverse('course/', ''),
get_lms_link_for_item(
course.location
),
......
......@@ -15,10 +15,7 @@
% if context_course:
<%
ctx_loc = context_course.location
index_url = reverse(
'contentstore.views.course_handler',
kwargs={'course_url': loc_mapper().translate_location(ctx_loc.course_id, ctx_loc, False, True)}
)
index_url = loc_mapper().translate_location(ctx_loc.course_id, ctx_loc, False, True).url_reverse('course/', '')
%>
<h2 class="info-course">
<span class="sr">${_("Current Course:")}</span>
......
import re
from django.conf import settings
from django.conf.urls import patterns, include, url
# TODO: This should be removed once the CMS is running via wsgi on all production servers
import cms.startup as startup
from xmodule.modulestore import parsers
startup.run()
# There is a course creators admin table.
......@@ -136,7 +138,8 @@ urlpatterns += patterns(
),
url(r'^course$', 'index'),
url(r'^course/(?P<course_url>.*)$', 'course_handler'),
# (?ix) == ignore case and verbose (multiline regex)
url(r'(?ix)^course/{}$'.format(parsers.URL_RE_SOURCE), 'course_handler'),
)
js_info_dict = {
......
......@@ -266,8 +266,8 @@ class CourseLocator(Locator):
def url_reverse(self, prefix, postfix):
"""
Do what reverse is supposed to do but seems unable to do. Generate a url using prefix unicode(self) postfix
:param prefix: the beginning of the url (should begin and end with / if non-empty)
:param postfix: the part to append to the url (should begin w/ / if non-empty)
:param prefix: the beginning of the url (will be forced to begin and end with / if non-empty)
:param postfix: the part to append to the url (will be forced to begin w/ / if non-empty)
"""
if prefix:
if not prefix.endswith('/'):
......@@ -278,14 +278,10 @@ class CourseLocator(Locator):
prefix = '/'
if postfix and not postfix.startswith('/'):
postfix = '/' + postfix
elif postfix is None:
postfix = ''
return prefix + unicode(self) + postfix
def reverse_kwargs(self):
"""
Get the kwargs list to supply to reverse (basically, a dict of the set properties)
"""
return {key: value for key, value in self.__dict__.iteritems() if value is not None}
def init_from_url(self, url):
"""
url must be a string beginning with 'edx://' and containing
......@@ -452,16 +448,6 @@ class BlockUsageLocator(CourseLocator):
branch=self.branch,
usage_id=self.usage_id)
def reverse_kwargs(self):
"""
Get the kwargs list to supply to reverse (basically, a dict of the set properties)
"""
result = super(BlockUsageLocator, self).reverse_kwargs()
if self.usage_id:
del result['usage_id']
result['block'] = self.usage_id
return result
def set_usage_id(self, new):
"""
Initialize usage_id to new value.
......
......@@ -285,6 +285,28 @@ class LocatorTest(TestCase):
Locator.to_locator_or_location("hello.world.not.a.url")
self.assertIsNone(Locator.parse_url("unknown://foo.bar/baz"))
def test_url_reverse(self):
"""
Test the url_reverse method
"""
locator = CourseLocator(course_id="a.fancy_course-id", branch="branch_1.2-3")
self.assertEqual(
'/expression/{}/format'.format(unicode(locator)),
locator.url_reverse('expression', 'format')
)
self.assertEqual(
'/expression/{}/format'.format(unicode(locator)),
locator.url_reverse('/expression', '/format')
)
self.assertEqual(
'/expression/{}'.format(unicode(locator)),
locator.url_reverse('expression/', None)
)
self.assertEqual(
'/expression/{}'.format(unicode(locator)),
locator.url_reverse('/expression/', '')
)
def test_description_locator_url(self):
object_id = '{:024x}'.format(random.randrange(16 ** 24))
definition_locator = DefinitionLocator(object_id)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment