From fd2979fa38868aaad5385c4eed30996d12142a5e Mon Sep 17 00:00:00 2001 From: Evgeny Fadeev Date: Sun, 19 May 2013 21:55:40 -0400 Subject: added an optional service url prefix to later support namespaces --- askbot/startup_procedures.py | 9 + askbot/tests/search_state_tests.py | 20 +- askbot/urls.py | 422 ++++++++++++++++++------------------- askbot/utils/url_utils.py | 13 ++ 4 files changed, 237 insertions(+), 227 deletions(-) diff --git a/askbot/startup_procedures.py b/askbot/startup_procedures.py index 621c9e8b..b7ad47bf 100644 --- a/askbot/startup_procedures.py +++ b/askbot/startup_procedures.py @@ -896,6 +896,14 @@ def test_messages_framework(): errors = ('Add to the INSTALLED_APPS section of your settings.py:\n "django.contrib.messages"', ) print_errors(errors) +def test_service_url_prefix(): + errors = list() + prefix = getattr(django_settings, 'ASKBOT_SERVICE_URL_PREFIX', '') + message = 'Service url prefix must have > 1 letters and must end with /' + if prefix: + if len(prefix) == 1 or (not prefix.endswith('/')): + print_errors((message,)) + def run_startup_tests(): """function that runs all startup tests, mainly checking settings config so far @@ -922,6 +930,7 @@ def run_startup_tests(): test_multilingual() #test_csrf_cookie_domain() test_secret_key() + test_service_url_prefix() test_staticfiles() test_template_loader() test_template_context_processors() diff --git a/askbot/tests/search_state_tests.py b/askbot/tests/search_state_tests.py index 27622629..44074441 100644 --- a/askbot/tests/search_state_tests.py +++ b/askbot/tests/search_state_tests.py @@ -54,11 +54,11 @@ class SearchStateTests(AskbotTestCase): user_logged_in=False ) self.assertEqual( - 'scope:unanswered/sort:age-desc/query:alfa/tags:miki,mini/author:12/page:2/', + 'scope:unanswered/sort:age-desc/tags:miki,mini/author:12/page:2/query:alfa/', ss.query_string() ) self.assertEqual( - 'scope:unanswered/sort:age-desc/query:alfa/tags:miki,mini/author:12/page:2/', + 'scope:unanswered/sort:age-desc/tags:miki,mini/author:12/page:2/query:alfa/', ss.deepcopy().query_string() ) @@ -74,11 +74,11 @@ class SearchStateTests(AskbotTestCase): user_logged_in=False ) self.assertEqual( - 'scope:all/sort:age-desc/query:alfa/tags:miki,mini/author:12/page:2/', + 'scope:all/sort:age-desc/tags:miki,mini/author:12/page:2/query:alfa/', ss.query_string() ) self.assertEqual( - 'scope:all/sort:age-desc/query:alfa/tags:miki,mini/author:12/page:2/', + 'scope:all/sort:age-desc/tags:miki,mini/author:12/page:2/query:alfa/', ss.deepcopy().query_string() ) @@ -93,11 +93,11 @@ class SearchStateTests(AskbotTestCase): user_logged_in=True ) self.assertEqual( - 'scope:followed/sort:age-desc/query:alfa/tags:miki,mini/author:12/page:2/', + 'scope:followed/sort:age-desc/tags:miki,mini/author:12/page:2/query:alfa/', ss.query_string() ) self.assertEqual( - 'scope:followed/sort:age-desc/query:alfa/tags:miki,mini/author:12/page:2/', + 'scope:followed/sort:age-desc/tags:miki,mini/author:12/page:2/query:alfa/', ss.deepcopy().query_string() ) @@ -116,7 +116,7 @@ class SearchStateTests(AskbotTestCase): user_logged_in=False ) self.assertEqual( - 'scope:all/sort:relevance-desc/query:hejho/tags:miki,mini/author:12/page:2/', + 'scope:all/sort:relevance-desc/tags:miki,mini/author:12/page:2/query:hejho/', ss.query_string() ) @@ -148,7 +148,7 @@ class SearchStateTests(AskbotTestCase): user_logged_in=False ) self.assertEqual( - 'scope:all/sort:activity-desc/query:hejho/tags:miki,mini/author:12/page:2/', + 'scope:all/sort:activity-desc/tags:miki,mini/author:12/page:2/query:hejho/', ss.query_string() ) @@ -157,7 +157,7 @@ class SearchStateTests(AskbotTestCase): def test_query_escaping(self): ss = self._ss(query=' alfa miki maki +-%#?= lalala/: ') # query coming from URL is already unescaped - qs = 'scope:all/sort:activity-desc/query:alfa%20miki%20maki%20+-%25%23%3F%3D%20lalala%2F%3A/page:1/' + qs = 'scope:all/sort:activity-desc/page:1/query:alfa%20miki%20maki%20+-%25%23%3F%3D%20lalala%2F%3A/' self.assertEqual(qs, ss.query_string()) self.assertEqual(qs, ss.deepcopy().query_string()) @@ -180,7 +180,7 @@ class SearchStateTests(AskbotTestCase): self.assertEqual(ss.stripped_query, ss.deepcopy().stripped_query) self.assertEqual( - 'scope:all/sort:activity-desc/query:%22%40anna%20haha%20%40%22maria%20fernanda%22%20%40%27diego%20maradona%27%20hehe%20%5Buser%3Akarl%20%20marx%5D%20hoho%20%20user%3A%27%20george%20bush%20%20%27/page:1/', + 'scope:all/sort:activity-desc/page:1/query:%22%40anna%20haha%20%40%22maria%20fernanda%22%20%40%27diego%20maradona%27%20hehe%20%5Buser%3Akarl%20%20marx%5D%20hoho%20%20user%3A%27%20george%20bush%20%20%27/', ss.query_string() ) diff --git a/askbot/urls.py b/askbot/urls.py index 32867615..f71962f1 100644 --- a/askbot/urls.py +++ b/askbot/urls.py @@ -11,6 +11,7 @@ from askbot import views from askbot.feed import RssLastestQuestionsFeed, RssIndividualQuestionFeed from askbot.sitemap import QuestionsSitemap from askbot.skins.utils import update_media_revision +from askbot.utils.url_utils import service_url admin.autodiscover() #update_media_revision()#needs to be run once, so put it here @@ -28,562 +29,549 @@ sitemaps = { 'questions': QuestionsSitemap } +#prefix is optional, recommended when a variable url prefix +#is used to subdivide the forum into namespaces +#in this case it is safer to use a special prefix to all urls +#except those that are namespaced +PREFIX = getattr(settings, 'ASKBOT_SERVICE_URL_PREFIX', '') + APP_PATH = os.path.dirname(__file__) urlpatterns = patterns('', url(r'^$', views.readers.index, name='index'), + # BEGIN Questions (main page) urls. All this urls work both normally and through ajax + url( + # Note that all parameters, even if optional, are provided to the view. Non-present ones have None value. + (r'^%s' % _('questions') + + r'(%s)?' % r'/scope:(?P\w+)' + + r'(%s)?' % r'/sort:(?P[\w\-]+)' + + r'(%s)?' % r'/tags:(?P[\w+.#,-]+)' + # Should match: const.TAG_CHARS + ','; TODO: Is `#` char decoded by the time URLs are processed ?? + r'(%s)?' % r'/author:(?P\d+)' + + r'(%s)?' % r'/page:(?P\d+)' + + r'(%s)?' % r'/query:(?P.+)' + # INFO: query is last, b/c it can contain slash!!! + r'/$'), + views.readers.questions, + name='questions' + ), + url( + r'^%s(?P\d+)/' % _('question/'), + views.readers.question, + name='question' + ), + url( + r'^%s$' % _('tags/'), + views.readers.tags, + name='tags' + ), + url( + r'^%s$' % _('users/'), + views.users.show_users, + name='users' + ), + url( + r'^%s%s(?P\d+)/(?P.*)/$' % (_('users/'), _('by-group/')), + views.users.show_users, + kwargs = {'by_group': True}, + name = 'users_by_group' + ), + #todo: rename as user_edit, b/c that's how template is named + url( + r'^%s(?P\d+)/%s$' % (_('users/'), _('edit/')), + views.users.edit_user, + name ='edit_user' + ), + url( + r'^%s(?P\d+)/(?P.+)/%s$' % ( + _('users/'), + _('subscriptions/'), + ), + views.users.user, + kwargs = {'tab_name': 'email_subscriptions'}, + name = 'user_subscriptions' + ), + url( + r'^%s(?P\d+)/(?P.+)/%s$' % ( + _('users/'), + _('select_languages/'), + ), + views.users.user_select_languages, + name = 'user_select_languages' + ), + url( + r'^%s(?P\d+)/(?P.+)/$' % _('users/'), + views.users.user, + name='user_profile' + ), + url( + r'^%s$' % _('groups/'), + views.users.groups, + name='groups' + ), + url( + r'^%s$' % _('users/update_has_custom_avatar/'), + views.users.update_has_custom_avatar, + name='user_update_has_custom_avatar' + ), + url( + r'^%s$' % _('badges/'), + views.meta.badges, + name='badges' + ), + url( + r'^%s(?P\d+)//*' % _('badges/'), + views.meta.badge, + name='badge' + ), url( r'^sitemap.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps}, name='sitemap' ), - #no translation for this url!! - url(r'^import-data/$', views.writers.import_data, name='import_data'), - url(r'^%s$' % _('about/'), views.meta.about, name='about'), - url(r'^%s$' % _('faq/'), views.meta.faq, name='faq'), - url(r'^%s$' % _('privacy/'), views.meta.privacy, name='privacy'), - url(r'^%s$' % _('help/'), views.meta.help, name='help'), + #feeds + url(r'^feeds/rss/$', RssLastestQuestionsFeed(), name="latest_questions_feed"), + url(r'^feeds/question/(?P\d+)/$', RssIndividualQuestionFeed(), name="individual_question_feed"), + url(r'^%s$' % _('feedback/'), views.meta.feedback, name='feedback'), url( + '^custom\.css$', + views.meta.config_variable, + kwargs = { + 'variable_name': 'CUSTOM_CSS', + 'mimetype': 'text/css' + }, + name = 'custom_css' + ), + url( + '^custom\.js$', + views.meta.config_variable, + kwargs = { + 'variable_name': 'CUSTOM_JS', + 'mimetype': 'text/javascript' + }, + name = 'custom_js' + ), + #no translation for this url!! + service_url(r'^import-data/$', views.writers.import_data, name='import_data'), + service_url(r'^%s$' % _('about/'), views.meta.about, name='about'), + service_url(r'^%s$' % _('faq/'), views.meta.faq, name='faq'), + service_url(r'^%s$' % _('privacy/'), views.meta.privacy, name='privacy'), + service_url(r'^%s$' % _('help/'), views.meta.help, name='help'), + service_url( r'^%s(?P\d+)/%s$' % (_('answers/'), _('edit/')), views.writers.edit_answer, name='edit_answer' ), - url( + service_url( r'^%s(?P\d+)/%s$' % (_('answers/'), _('revisions/')), views.readers.revisions, kwargs = {'post_type': 'answer'}, name='answer_revisions' ), - - # BEGIN Questions (main page) urls. All this urls work both normally and through ajax - - url( - # Note that all parameters, even if optional, are provided to the view. Non-present ones have None value. - (r'^%s' % _('questions') + - r'(%s)?' % r'/scope:(?P\w+)' + - r'(%s)?' % r'/sort:(?P[\w\-]+)' + - r'(%s)?' % r'/tags:(?P[\w+.#,-]+)' + # Should match: const.TAG_CHARS + ','; TODO: Is `#` char decoded by the time URLs are processed ?? - r'(%s)?' % r'/author:(?P\d+)' + - r'(%s)?' % r'/page:(?P\d+)' + - r'(%s)?' % r'/query:(?P.+)' + # INFO: query is last, b/c it can contain slash!!! - r'/$'), - views.readers.questions, - name='questions' - ), # END main page urls - - url( + service_url( r'^api/get_questions/', views.commands.api_get_questions, name='api_get_questions' ), - url( + service_url( r'^get-thread-shared-users/', views.commands.get_thread_shared_users, name='get_thread_shared_users' ), - url( + service_url( r'^get-thread-shared-groups/', views.commands.get_thread_shared_groups, name='get_thread_shared_groups' ), - url( + service_url( r'^moderate-group-join-request/', views.commands.moderate_group_join_request, name='moderate_group_join_request' ), - url( + service_url( r'^save-draft-question/', views.commands.save_draft_question, name = 'save_draft_question' ), - url( + service_url( r'^save-draft-answer/', views.commands.save_draft_answer, name = 'save_draft_answer' ), - url( + service_url( r'^share-question-with-group/', views.commands.share_question_with_group, name='share_question_with_group' ), - url( + service_url( r'^share-question-with-user/', views.commands.share_question_with_user, name='share_question_with_user' ), - url( + service_url( r'^get-users-info/', views.commands.get_users_info, name='get_users_info' ), - url( + service_url( r'^get-editor/', views.commands.get_editor, name='get_editor' ), - url( + service_url( r'^%s%s$' % (_('questions/'), _('ask/')), views.writers.ask, name='ask' ), - url( + service_url( r'^%s(?P\d+)/%s$' % (_('questions/'), _('edit/')), views.writers.edit_question, name='edit_question' ), - url(#this url is both regular and ajax + service_url(#this url is both regular and ajax r'^%s(?P\d+)/%s$' % (_('questions/'), _('retag/')), views.writers.retag_question, name='retag_question' ), - url( + service_url( r'^%s(?P\d+)/%s$' % (_('questions/'), _('close/')), views.commands.close, name='close' ), - url( + service_url( r'^%s(?P\d+)/%s$' % (_('questions/'), _('reopen/')), views.commands.reopen, name='reopen' ), - url( + service_url( r'^%s(?P\d+)/%s$' % (_('questions/'), _('answer/')), views.writers.answer, name='answer' ), - url(#ajax only + service_url(#ajax only r'^vote$', views.commands.vote, name='vote' ), - url( + service_url( r'^%s(?P\d+)/%s$' % (_('questions/'), _('revisions/')), views.readers.revisions, kwargs = {'post_type': 'question'}, name='question_revisions' ), - url(#ajax only + service_url(#ajax only r'^comment/upvote/$', views.commands.upvote_comment, name = 'upvote_comment' ), - url(#ajax only + service_url(#ajax only r'^post/delete/$', views.commands.delete_post, name = 'delete_post' ), - url(#ajax only + service_url(#ajax only r'^post_comments/$', views.writers.post_comments, name='post_comments' ), - url(#ajax only + service_url(#ajax only r'^edit_comment/$', views.writers.edit_comment, name='edit_comment' ), - url(#ajax only + service_url(#ajax only r'^comment/delete/$', views.writers.delete_comment, name='delete_comment' ), - url(#ajax only + service_url(#ajax only r'^comment/get_text/$', views.readers.get_comment, name='get_comment' ), - url( + service_url( r'^comment/convert/$', views.writers.comment_to_answer, name='comment_to_answer' ), - url( + service_url( r'^answer/repost-as-comment-under-question/$', views.writers.repost_answer_as_comment, kwargs={'destination': 'comment_under_question'}, name='repost_answer_as_comment_under_question' ), - url(#post only + service_url(#post only '^answer/repost-as-comment-under-previous-answer/$', views.writers.repost_answer_as_comment, kwargs={'destination': 'comment_under_previous_answer'}, name='repost_answer_as_comment_under_previous_answer' ), - url(#post only + service_url(#post only r'^answer/publish/$', views.commands.publish_answer, name='publish_answer' ), - url( - r'^%s$' % _('tags/'), - views.readers.tags, - name='tags' - ), - url( + service_url( r'^%s$' % _('tags/subscriptions/'), views.commands.list_bulk_tag_subscription, name='list_bulk_tag_subscription' ), - url(#post only + service_url(#post only r'^%s$' % _('tags/subscriptions/delete/'), views.commands.delete_bulk_tag_subscription, name='delete_bulk_tag_subscription' ), - url( + service_url( r'^%s$' % _('tags/subscriptions/create/'), views.commands.create_bulk_tag_subscription, name='create_bulk_tag_subscription' ), - url( + service_url( r'^%s(?P\d+)/$' % _('tags/subscriptions/edit/'), views.commands.edit_bulk_tag_subscription, name='edit_bulk_tag_subscription' ), - - url( + service_url( r'^%s$' % _('suggested-tags/'), views.meta.list_suggested_tags, name = 'list_suggested_tags' ), - - #feeds - url(r'^feeds/rss/$', RssLastestQuestionsFeed(), name="latest_questions_feed"), - url(r'^feeds/question/(?P\d+)/$', RssIndividualQuestionFeed(), name="individual_question_feed"), - - url(#ajax only + service_url(#ajax only r'^%s$' % 'moderate-suggested-tag', views.commands.moderate_suggested_tag, name = 'moderate_suggested_tag' ), #todo: collapse these three urls and use an extra json data var - url(#ajax only + service_url(#ajax only r'^%s%s$' % ('mark-tag/', 'interesting/'), views.commands.mark_tag, kwargs={'reason':'good','action':'add'}, name='mark_interesting_tag' ), - url(#ajax only + service_url(#ajax only r'^%s%s$' % ('mark-tag/', 'ignored/'), views.commands.mark_tag, kwargs={'reason':'bad','action':'add'}, name='mark_ignored_tag' ), - url(#ajax only + service_url(#ajax only r'^%s%s$' % ('mark-tag/', 'subscribed/'), views.commands.mark_tag, kwargs={'reason':'subscribed','action':'add'}, name='mark_subscribed_tag' ), - url(#ajax only + service_url(#ajax only r'^unmark-tag/', views.commands.mark_tag, kwargs={'action':'remove'}, name='unmark_tag' ), - url(#ajax only + service_url(#ajax only r'^set-tag-filter-strategy/', views.commands.set_tag_filter_strategy, name = 'set_tag_filter_strategy' ), - url( + service_url( r'^get-tags-by-wildcard/', views.commands.get_tags_by_wildcard, name = 'get_tags_by_wildcard' ), - url( + service_url( r'^get-tag-list/', views.commands.get_tag_list, name = 'get_tag_list' ), - url( + service_url( r'^load-object-description/', views.commands.load_object_description, name = 'load_object_description' ), - url(#ajax only + service_url(#ajax only r'^save-object-description/', views.commands.save_object_description, name = 'save_object_description' ), - url(#ajax only + service_url(#ajax only r'^add-tag-category/', views.commands.add_tag_category, name = 'add_tag_category' ), - url(#ajax only + service_url(#ajax only r'^rename-tag/', views.commands.rename_tag, name = 'rename_tag' ), - url(# + service_url(# r'^delete-tag/', views.commands.delete_tag, name = 'delete_tag' ), - url(#ajax only + service_url(#ajax only r'^save-group-logo-url/', views.commands.save_group_logo_url, name = 'save_group_logo_url' ), - url(#ajax only + service_url(#ajax only r'^delete-group-logo/', views.commands.delete_group_logo, name = 'delete_group_logo' ), - url(#ajax only + service_url(#ajax only r'^add-group/', views.commands.add_group, name = 'add_group' ), - url(#ajax only + service_url(#ajax only r'^toggle-group-profile-property/', views.commands.toggle_group_profile_property, name='toggle_group_profile_property' ), - url(#ajax only + service_url(#ajax only r'^set-group-openness/', views.commands.set_group_openness, name='set_group_openness' ), - url(#ajax only + service_url(#ajax only r'^edit-object-property-text/', views.commands.edit_object_property_text, name = 'edit_object_property_text' ), - url( + service_url( r'^get-groups-list/', views.commands.get_groups_list, name = 'get_groups_list' ), - url( + service_url( r'^swap-question-with-answer/', views.commands.swap_question_with_answer, name = 'swap_question_with_answer' ), - url( - r'^%s$' % _('subscribe-for-tags/'), + service_url( + r'^subscribe-for-tags/$', views.commands.subscribe_for_tags, name = 'subscribe_for_tags' ), - url( - r'^%s$' % _('users/'), - views.users.show_users, - name='users' - ), - url( - r'^%s%s(?P\d+)/(?P.*)/$' % (_('users/'), _('by-group/')), - views.users.show_users, - kwargs = {'by_group': True}, - name = 'users_by_group' - ), - #todo: rename as user_edit, b/c that's how template is named - url( - r'^%s(?P\d+)/%s$' % (_('users/'), _('edit/')), - views.users.edit_user, - name ='edit_user' - ), - url( - r'^%s(?P\d+)/(?P.+)/%s$' % ( - _('users/'), - _('subscriptions/'), - ), - views.users.user, - kwargs = {'tab_name': 'email_subscriptions'}, - name = 'user_subscriptions' - ), - url( - r'^%s(?P\d+)/(?P.+)/%s$' % ( - _('users/'), - _('select_languages/'), - ), - views.users.user_select_languages, - name = 'user_select_languages' - ), - url( - r'^%s(?P\d+)/(?P.+)/$' % _('users/'), - views.users.user, - name='user_profile' - ), - url( - r'^%s$' % _('groups/'), - views.users.groups, - name='groups' - ), - url( - r'^%s$' % _('users/update_has_custom_avatar/'), - views.users.update_has_custom_avatar, - name='user_update_has_custom_avatar' - ), - url( - r'^%s$' % _('badges/'), - views.meta.badges, - name='badges' - ), - url( - r'^%s(?P\d+)//*' % _('badges/'), - views.meta.badge, - name='badge' - ), - url( + service_url( r'get-html-template/', views.commands.get_html_template, name='get_html_template' ), - url(#ajax only + service_url(#ajax only r'^%s%s$' % (_('messages/'), _('markread/')), views.commands.read_message, name='read_message' ), - url(#ajax only + service_url(#ajax only r'^manage-inbox/$', views.commands.manage_inbox, name='manage_inbox' ), - url(#ajax only + service_url(#ajax only r'^save-post-reject-reason/$', views.commands.save_post_reject_reason, name='save_post_reject_reason' ), - url(#ajax only + service_url(#ajax only r'^delete-post-reject-reason/$', views.commands.delete_post_reject_reason, name='delete_post_reject_reason' ), - url(#ajax only + service_url(#ajax only r'^edit-group-membership/$', views.commands.edit_group_membership, name='edit_group_membership' ), - url(#ajax only + service_url(#ajax only r'^join-or-leave-group/$', views.commands.join_or_leave_group, name = 'join_or_leave_group' ), #widgets url! - url( + service_url( r'^%s$' % (_('widgets/')), views.widgets.widgets, name = 'widgets' ), - - url( + service_url( r'^%s%s(?P\d+)/$' % (_('widgets/'), _('ask/')), views.widgets.ask_widget, name = 'ask_by_widget' ), - url( + service_url( r'^%s%s(?P\d+).js$' % (_('widgets/'), _('ask/')), views.widgets.render_ask_widget_js, name = 'render_ask_widget' ), - url( + service_url( r'^%s%s(?P\d+).css$' % (_('widgets/'), _('ask/')), views.widgets.render_ask_widget_css, name = 'render_ask_widget_css' ), - - url( + service_url( r'^%s%s%s$' % (_('widgets/'), _('ask/'), _('complete/')), views.widgets.ask_widget_complete, name = 'ask_by_widget_complete' ), - url( + service_url( r'^%s(?P\w+)/%s$' % (_('widgets/'), _('create/')), views.widgets.create_widget, name = 'create_widget' ), - url( + service_url( r'^%s(?P\w+)/%s(?P\d+)/$' % (_('widgets/'), _('edit/')), views.widgets.edit_widget, name = 'edit_widget' ), - url( + service_url( r'^%s(?P\w+)/%s(?P\d+)/$' % (_('widgets/'), _('delete/')), views.widgets.delete_widget, name = 'delete_widget' ), - - url( + service_url( r'^%s(?P\w+)/$' % (_('widgets/')), views.widgets.list_widgets, name = 'list_widgets' ), - url( + service_url( r'^widgets/questions/(?P\d+)/$', views.widgets.question_widget, name = 'question_widget' ), - url( + service_url( r'^start-sharing-twitter/$', views.sharing.start_sharing_twitter, name='start_sharing_twitter' ), - url( + service_url( r'^save-twitter-access-token/$', views.sharing.save_twitter_access_token, name='save_twitter_access_token' ), - url(#ajax post only + service_url(#ajax post only r'^change-social-sharing-mode/$', views.sharing.change_social_sharing_mode, name='change_social_sharing_mode' ), #upload url is ajax only - url( r'^%s$' % _('upload/'), views.writers.upload, name='upload'), - url(r'^%s$' % _('feedback/'), views.meta.feedback, name='feedback'), - url( + service_url( r'^%s$' % _('upload/'), views.writers.upload, name='upload'), + service_url( r'^doc/(?P.*)$', 'django.views.static.serve', {'document_root': os.path.join(APP_PATH,'doc','build','html').replace('\\','/')}, name='askbot_docs', ), - url( - '^custom\.css$', - views.meta.config_variable, - kwargs = { - 'variable_name': 'CUSTOM_CSS', - 'mimetype': 'text/css' - }, - name = 'custom_css' - ), - url( - '^custom\.js$', - views.meta.config_variable, - kwargs = { - 'variable_name': 'CUSTOM_JS', - 'mimetype': 'text/javascript' - }, - name = 'custom_js' - ), - url( + service_url( r'^jsi18n/$', 'django.views.i18n.javascript_catalog', {'domain': 'djangojs','packages': ('askbot',)}, name = 'askbot_jsi18n' ), - url('^messages/', include('group_messaging.urls')), - url('^settings/', include('livesettings.urls')), + service_url('^messages/', include('group_messaging.urls')), + service_url('^settings/', include('livesettings.urls')), ) -#todo - this url below won't work, because it is defined above -#therefore the stackexchange urls feature won't work -if getattr(settings, 'ASKBOT_USE_STACKEXCHANGE_URLS', False): - urlpatterns += (url( - r'^%s(?P\d+)/' % _('questions/'), - views.readers.question, - name='question' - ),) -else: - urlpatterns += (url( - r'^%s(?P\d+)/' % _('question/'), - views.readers.question, - name='question' - ),) - if 'askbot.deps.django_authopenid' in settings.INSTALLED_APPS: urlpatterns += ( - url(r'^%s' % _('account/'), include('askbot.deps.django_authopenid.urls')), + service_url(r'^%s' % _('account/'), include('askbot.deps.django_authopenid.urls')), ) if 'avatar' in settings.INSTALLED_APPS: @@ -591,18 +579,18 @@ if 'avatar' in settings.INSTALLED_APPS: #because views add and change are adapted to #use jinja2 templates urlpatterns += ( - url('^avatar/add/$', views.avatar_views.add, name='avatar_add'), - url( + service_url('^avatar/add/$', views.avatar_views.add, name='avatar_add'), + service_url( '^avatar/change/$', views.avatar_views.change, name='avatar_change' ), - url( + service_url( '^avatar/delete/$', views.avatar_views.delete, name='avatar_delete' ), - url(#this urs we inherit from the original avatar app + service_url(#this urs we inherit from the original avatar app '^avatar/render_primary/(?P[\+\d]+)/(?P[\d]+)/$', views.avatar_views.render_primary, name='avatar_render_primary' diff --git a/askbot/utils/url_utils.py b/askbot/utils/url_utils.py index c58239c5..3c4fa7b5 100644 --- a/askbot/utils/url_utils.py +++ b/askbot/utils/url_utils.py @@ -2,6 +2,19 @@ import os import urlparse from django.core.urlresolvers import reverse from django.conf import settings +from django.conf.urls.defaults import url + +def service_url(*args, **kwargs): + """adds the service prefix to the url""" + pattern = args[0] + if pattern[0] == '^': + pattern = pattern[1:] + + prefix = getattr(settings, 'ASKBOT_SERVICE_URL_PREFIX', '') + pattern = '^' + prefix + pattern + new_args = list(args) + new_args[0] = pattern + return url(*new_args, **kwargs) def strip_path(url): """srips path, params and hash fragments of the url""" -- cgit v1.2.3-1-g7c22