diff --git a/djangoapps/student/views.py b/djangoapps/student/views.py index 298df617e4..a7b02b5bb1 100644 --- a/djangoapps/student/views.py +++ b/djangoapps/student/views.py @@ -23,7 +23,7 @@ from django_future.csrf import ensure_csrf_cookie from models import Registration, UserProfile, PendingNameChange, PendingEmailChange -log = logging.getLogger("mitx.user") +log = logging.getLogger("mitx.student") def csrf_token(context): ''' A csrf token that can be included in a form. diff --git a/envs/README.txt b/envs/README.txt new file mode 100644 index 0000000000..7a527b290f --- /dev/null +++ b/envs/README.txt @@ -0,0 +1,14 @@ +Transitional for moving to new settings scheme. + +To use: + django-admin.py runserver --settings=envs.dev --pythonpath=. + +NOTE: Using manage.py will automatically run mitx/settings.py first, regardless +of what you send it for an explicit --settings flag. It still works, but might +have odd side effects. Using django-admin.py avoids that problem. +django-admin.py is installed by default when you install Django. + +To use with gunicorn_django in debug mode: + + gunicorn_django envs/dev.py + diff --git a/settings2/__init__.py b/envs/__init__.py similarity index 100% rename from settings2/__init__.py rename to envs/__init__.py diff --git a/settings2/askbotsettings.py b/envs/askbotsettings.py similarity index 93% rename from settings2/askbotsettings.py rename to envs/askbotsettings.py index 8b04726a00..681e65763d 100644 --- a/settings2/askbotsettings.py +++ b/envs/askbotsettings.py @@ -1,4 +1,10 @@ -# askbot livesettings +""" +There are other askbot settings in common.py that covers things like where the +templates are located, etc. This file is purely for askbot forum *behavior*. +This means things like karma limits, the ability to post questions as wikis, +anonymous questions, etc. +""" + LIVESETTINGS_OPTIONS = { 1: { 'DB' : False, @@ -88,9 +94,9 @@ LIVESETTINGS_OPTIONS = { 'MIN_TITLE_LENGTH' : 1, 'MIN_QUESTION_BODY_LENGTH' : 1, 'MIN_ANSWER_BODY_LENGTH' : 1, - 'WIKI_ON' : True, + 'WIKI_ON' : False, 'ALLOW_ASK_ANONYMOUSLY' : True, - 'ALLOW_POSTING_BEFORE_LOGGING_IN' : True, + 'ALLOW_POSTING_BEFORE_LOGGING_IN' : False, 'ALLOW_SWAPPING_QUESTION_WITH_ANSWER' : False, 'MAX_TAG_LENGTH' : 20, 'MIN_TITLE_LENGTH' : 1, @@ -172,8 +178,8 @@ LIVESETTINGS_OPTIONS = { }, 'MARKUP' : { 'MARKUP_CODE_FRIENDLY' : False, - 'ENABLE_MATHJAX' : False, # FIXME: Test with this enabled - 'MATHJAX_BASE_URL' : u'', + 'ENABLE_MATHJAX' : True, + 'MATHJAX_BASE_URL' : u'/static/js/mathjax-MathJax-c9db6ac/', 'ENABLE_AUTO_LINKING' : False, 'AUTO_LINK_PATTERNS' : u'', 'AUTO_LINK_URLS' : u'', @@ -181,21 +187,21 @@ LIVESETTINGS_OPTIONS = { 'MIN_REP' : { 'MIN_REP_TO_ACCEPT_OWN_ANSWER' : 1, 'MIN_REP_TO_ANSWER_OWN_QUESTION' : 1, - 'MIN_REP_TO_CLOSE_OTHERS_QUESTIONS' : 100, + 'MIN_REP_TO_CLOSE_OTHERS_QUESTIONS' : 1200, 'MIN_REP_TO_CLOSE_OWN_QUESTIONS' : 1, - 'MIN_REP_TO_DELETE_OTHERS_COMMENTS' : 2000, - 'MIN_REP_TO_DELETE_OTHERS_POSTS' : 5000, - 'MIN_REP_TO_EDIT_OTHERS_POSTS' : 2000, - 'MIN_REP_TO_EDIT_WIKI' : 1, + 'MIN_REP_TO_DELETE_OTHERS_COMMENTS' : 5000, + 'MIN_REP_TO_DELETE_OTHERS_POSTS' : 10000, + 'MIN_REP_TO_EDIT_OTHERS_POSTS' : 5000, + 'MIN_REP_TO_EDIT_WIKI' : 200, 'MIN_REP_TO_FLAG_OFFENSIVE' : 1, 'MIN_REP_TO_HAVE_STRONG_URL' : 250, 'MIN_REP_TO_LEAVE_COMMENTS' : 1, - 'MIN_REP_TO_LOCK_POSTS' : 4000, + 'MIN_REP_TO_LOCK_POSTS' : 10000, 'MIN_REP_TO_REOPEN_OWN_QUESTIONS' : 1, - 'MIN_REP_TO_RETAG_OTHERS_QUESTIONS' : 1, + 'MIN_REP_TO_RETAG_OTHERS_QUESTIONS' : 100, 'MIN_REP_TO_UPLOAD_FILES' : 1, 'MIN_REP_TO_VIEW_OFFENSIVE_FLAGS' : 2000, - 'MIN_REP_TO_VOTE_DOWN' : 1, + 'MIN_REP_TO_VOTE_DOWN' : 15, 'MIN_REP_TO_VOTE_UP' : 1, }, 'QA_SITE_SETTINGS' : { @@ -275,7 +281,7 @@ LIVESETTINGS_OPTIONS = { 'VOTE_RULES' : { 'MAX_VOTES_PER_USER_PER_DAY' : 30, 'MAX_FLAGS_PER_USER_PER_DAY' : 5, - 'MIN_DAYS_FOR_STAFF_TO_ACCEPT_ANSWER' : 7, + 'MIN_DAYS_FOR_STAFF_TO_ACCEPT_ANSWER' : 0, 'MIN_DAYS_TO_ANSWER_OWN_QUESTION' : 0, 'MIN_FLAGS_TO_DELETE_POST' : 5, 'MIN_FLAGS_TO_HIDE_POST' : 3, @@ -284,4 +290,4 @@ LIVESETTINGS_OPTIONS = { }, }, }, -} +} \ No newline at end of file diff --git a/envs/aws.py b/envs/aws.py new file mode 100644 index 0000000000..9ce621c2bd --- /dev/null +++ b/envs/aws.py @@ -0,0 +1,50 @@ +""" +This is the default template for our main set of AWS servers. This does NOT +cover the content machines, which use content.py + +Common traits: +* Use memcached, and cache-backed sessions +* Use a MySQL 5.1 database +""" +import json + +from common import * + +############################### ALWAYS THE SAME ################################ +DEBUG = False +TEMPLATE_DEBUG = False + +EMAIL_BACKEND = 'django_ses.SESBackend' +SESSION_ENGINE = 'django.contrib.sessions.backends.cache' +DEFAULT_FILE_STORAGE = 'storages.backends.s3boto.S3BotoStorage' + +########################### NON-SECURE ENV CONFIG ############################## +# Things like server locations, ports, etc. +with open(ENV_ROOT / "env.json") as env_file: + ENV_TOKENS = json.load(env_file) + +SITE_NAME = ENV_TOKENS['SITE_NAME'] +CSRF_COOKIE_DOMAIN = ENV_TOKENS['CSRF_COOKIE_DOMAIN'] + +BOOK_URL = ENV_TOKENS['BOOK_URL'] +MEDIA_URL = ENV_TOKENS['MEDIA_URL'] +LOG_DIR = ENV_TOKENS['LOG_DIR'] + +CACHES = ENV_TOKENS['CACHES'] + +LOGGING = logsettings.get_logger_config(LOG_DIR, + logging_env=ENV_TOKENS['LOGGING_ENV'], + syslog_addr=(ENV_TOKENS['SYSLOG_SERVER'], 514), + debug=False) + +############################## SECURE AUTH ITEMS ############################### +# Secret things: passwords, access keys, etc. +with open(ENV_ROOT / "auth.json") as auth_file: + AUTH_TOKENS = json.load(auth_file) + +SECRET_KEY = AUTH_TOKENS['SECRET_KEY'] + +AWS_ACCESS_KEY_ID = AUTH_TOKENS["AWS_ACCESS_KEY_ID"] +AWS_SECRET_ACCESS_KEY = AUTH_TOKENS["AWS_SECRET_ACCESS_KEY"] + +DATABASES = AUTH_TOKENS['DATABASES'] \ No newline at end of file diff --git a/settings2/common.py b/envs/common.py similarity index 53% rename from settings2/common.py rename to envs/common.py index 5d5dffb084..2b01a0911e 100644 --- a/settings2/common.py +++ b/envs/common.py @@ -2,15 +2,15 @@ This is the common settings file, intended to set sane defaults. If you have a piece of configuration that's dependent on a set of feature flags being set, then create a function that returns the calculated value based on the value of -MITX_FEATURES[...]. That classes that extend this one can change the feature +MITX_FEATURES[...]. Modules that extend this one can change the feature configuration in an environment specific config file and re-calculate those values. We should make a method that calls all these config methods so that you just -make one call at the end of your site-specific dev file and it reset all the +make one call at the end of your site-specific dev file to reset all the dependent variables (like INSTALLED_APPS) for you. -TODO: +Longer TODO: 1. Right now our treatment of static content in general and in particular course-specific static content is haphazard. 2. We should have a more disciplined approach to feature flagging, even if it @@ -18,15 +18,14 @@ TODO: 3. We need to handle configuration for multiple courses. This could be as multiple sites, but we do need a way to map their data assets. """ -import os -import platform import sys import tempfile import djcelery from path import path -from askbotsettings import LIVESETTINGS_OPTIONS +from askbotsettings import * # this is where LIVESETTINGS_OPTIONS comes from +import logsettings ################################### FEATURES ################################### COURSEWARE_ENABLED = True @@ -39,21 +38,21 @@ MITX_FEATURES = { 'SAMPLE' : False } +# Used for A/B testing +DEFAULT_GROUPS = [] + +# If this is true, random scores will be generated for the purpose of debugging the profile graphs +GENERATE_PROFILE_SCORES = False + ############################# SET PATH INFORMATION ############################# PROJECT_ROOT = path(__file__).abspath().dirname().dirname() # /mitxweb ENV_ROOT = PROJECT_ROOT.dirname() # virtualenv dir /mitxweb is in -#ASKBOT_ROOT = ENV_ROOT / "3rdparty" / "askbot-devel" ASKBOT_ROOT = ENV_ROOT / "askbot-devel" -#COURSES_ROOT = ENV_ROOT / "courses" COURSES_ROOT = ENV_ROOT / "data" -# FIXME: code shouldn't expect trailing "/" # FIXME: To support multiple courses, we should walk the courses dir at startup -#DATA_DIR = COURSES_ROOT / "6002x" / "" DATA_DIR = COURSES_ROOT -#print DATA_DIR, COURSES_ROOT, ASKBOT_ROOT, ENV_ROOT, PROJECT_ROOT - sys.path.append(ENV_ROOT) sys.path.append(ASKBOT_ROOT) sys.path.append(ASKBOT_ROOT / "askbot" / "deps") @@ -61,35 +60,50 @@ sys.path.append(PROJECT_ROOT / 'djangoapps') sys.path.append(PROJECT_ROOT / 'lib') ################################## MITXWEB ##################################### -# This is where we stick our compiled template files +# This is where we stick our compiled template files. Most of the app uses Mako +# templates MAKO_MODULE_DIR = tempfile.mkdtemp('mako') MAKO_TEMPLATES = {} MAKO_TEMPLATES['course'] = [DATA_DIR] -MAKO_TEMPLATES['sections'] = [DATA_DIR+'/sections'] -MAKO_TEMPLATES['custom_tags'] = [DATA_DIR+'/custom_tags'] -MAKO_TEMPLATES['main'] = [ENV_ROOT+'/templates/'] +MAKO_TEMPLATES['sections'] = [DATA_DIR / 'sections'] +MAKO_TEMPLATES['custom_tags'] = [DATA_DIR / 'custom_tags'] +MAKO_TEMPLATES['main'] = [PROJECT_ROOT / 'templates', + DATA_DIR / 'info', + DATA_DIR / 'problems'] -TEXTBOOK_DIR = ENV_ROOT / "books" / "circuits_agarwal_lang" +# This is where Django Template lookup is defined. There are a few of these +# still left lying around. +TEMPLATE_DIRS = ( + PROJECT_ROOT / "templates", + DATA_DIR / "problems", +) -# FIXME ???????? -- +TEMPLATE_CONTEXT_PROCESSORS = ( + 'django.core.context_processors.request', + 'askbot.context.application_settings', + #'django.core.context_processors.i18n', + 'askbot.user_messages.context_processors.user_messages',#must be before auth + 'django.core.context_processors.auth', #this is required for admin + 'django.core.context_processors.csrf', #necessary for csrf protection +) + + +# FIXME: # We should have separate S3 staged URLs in case we need to make changes to # these assets and test them. -LIB_URL = '/static/lib/' -# LIB_URL = 'https://mitxstatic.s3.amazonaws.com/js/' # For AWS deploys +LIB_URL = '/static/js/' # Dev machines shouldn't need the book # BOOK_URL = '/static/book/' BOOK_URL = 'https://mitxstatic.s3.amazonaws.com/book_images/' # For AWS deploys -# FIXME ??????? What are these exactly? # Configuration option for when we want to grab server error pages STATIC_GRAB = False DEV_CONTENT = True # FIXME: Should we be doing this truncation? -TRACK_MAX_EVENT = 1000 - -GENERATE_PROFILE_SCORES = False +TRACK_MAX_EVENT = 10000 +DEBUG_TRACK_LOG = False ############################### DJANGO BUILT-INS ############################### # Change DEBUG/TEMPLATE_DEBUG in your environment settings files, not here @@ -101,8 +115,8 @@ SITE_ID = 1 SITE_NAME = "localhost:8000" CSRF_COOKIE_DOMAIN = '127.0.0.1' HTTPS = 'on' -#ROOT_URLCONF = 'mitxweb.urls' ROOT_URLCONF = 'mitx.urls' +IGNORABLE_404_ENDS = ('favicon.ico') # Email EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' @@ -116,47 +130,16 @@ MANAGERS = ADMINS # Static content STATIC_URL = '/static/' ADMIN_MEDIA_PREFIX = '/static/admin/' -STATIC_ROOT = ENV_ROOT / "staticfiles" # FIXME: Should this and uploads be moved out of the repo? +STATIC_ROOT = ENV_ROOT / "staticfiles" # We don't run collectstatic -- this is to appease askbot checks # FIXME: We should iterate through the courses we have, adding the static -# contents for each of them. +# contents for each of them. (Right now we just use symlinks.) STATICFILES_DIRS = ( - # FIXME: Need to add entries for book, data/images, etc. -# PROJECT_ROOT / "static", - ENV_ROOT / "static", + PROJECT_ROOT / "static", ASKBOT_ROOT / "askbot" / "skins", -# ("circuits", DATA_DIR / "images"), -# ("handouts", DATA_DIR / "handouts"), -# ("subs", DATA_DIR / "subs"), -# ("book", TEXTBOOK_DIR) -) -print STATICFILES_DIRS - -# Templates -TEMPLATE_DIRS = ( - ENV_ROOT / "templates", -# PROJECT_ROOT / "templates", -# DATA_DIR / "problems", -) - -TEMPLATE_CONTEXT_PROCESSORS = ( - 'django.core.context_processors.request', - 'askbot.context.application_settings', - #'django.core.context_processors.i18n', - 'askbot.user_messages.context_processors.user_messages',#must be before auth - 'django.core.context_processors.auth', #this is required for admin - 'django.core.context_processors.csrf', #necessary for csrf protection -) - -# Storage -DEFAULT_FILE_STORAGE = 'django.core.files.storage.FileSystemStorage' -MEDIA_ROOT = ENV_ROOT / "uploads" -MEDIA_URL = "/discussion/upfiles/" -FILE_UPLOAD_TEMP_DIR = os.path.join(os.path.dirname(__file__), 'tmp').replace('\\','/') -FILE_UPLOAD_HANDLERS = ( - 'django.core.files.uploadhandler.MemoryFileUploadHandler', - 'django.core.files.uploadhandler.TemporaryFileUploadHandler', +# This is how you would use the textbook images locally +# ("book", ENV_ROOT / "book_images") ) # Locale/Internationalization @@ -165,80 +148,6 @@ LANGUAGE_CODE = 'en' # http://www.i18nguy.com/unicode/language-identifiers.html USE_I18N = True USE_L10N = True -################################### LOGGING #################################### -# Might want to rewrite this to use logger code and push more things to the root -# logger. -pid = os.getpid() # So we can log which process is creating the log -hostname = platform.node().split(".")[0] -SYSLOG_ADDRESS = ('syslog.m.i4x.org', 514) - -handlers = ['console'] -# FIXME: re-enable syslogger later -# if not DEBUG: -# handlers.append('syslogger') - -LOGGING = { - 'version': 1, - 'disable_existing_loggers': True, - 'formatters' : { - 'standard' : { - 'format' : '%(asctime)s %(levelname)s %(process)d [%(name)s] %(filename)s:%(lineno)d - %(message)s', - }, - 'syslog_format' : { - 'format' : '[%(name)s] %(levelname)s [' + hostname + ' %(process)d] [%(filename)s:%(lineno)d] - %(message)s', - }, - 'raw' : { - 'format' : '%(message)s', - } - }, - 'handlers' : { - 'console' : { - 'level' : 'DEBUG', - 'class' : 'logging.StreamHandler', - 'formatter' : 'standard', - 'stream' : sys.stdout, - }, - 'console_err' : { - 'level' : 'ERROR', - 'class' : 'logging.StreamHandler', - 'formatter' : 'standard', - 'stream' : sys.stderr, - }, - 'syslogger' : { - 'level' : 'INFO', - 'class' : 'logging.handlers.SysLogHandler', - 'address' : SYSLOG_ADDRESS, - 'formatter' : 'syslog_format', - }, - 'mail_admins' : { - 'level': 'ERROR', - 'class': 'django.utils.log.AdminEmailHandler', - }, - }, - 'loggers' : { - 'django' : { - 'handlers' : handlers + ['mail_admins'], - 'propagate' : True, - 'level' : 'INFO' - }, - 'tracking' : { - 'handlers' : [] if DEBUG else ['syslogger'], # handlers, - 'level' : 'DEBUG', - 'propagate' : False, - }, - 'root' : { - 'handlers' : handlers, - 'level' : 'DEBUG', - 'propagate' : False - }, - 'mitx' : { - 'handlers' : handlers, - 'level' : 'DEBUG', - 'propagate' : False - }, - } -} - #################################### AWS ####################################### # S3BotoStorage insists on a timeout for uploaded assets. We should make it # permanent instead, but rather than trying to figure out exactly where that @@ -288,14 +197,19 @@ TEMPLATE_LOADERS = ( MIDDLEWARE_CLASSES = ( 'util.middleware.ExceptionLoggingMiddleware', + 'django.middleware.cache.UpdateCacheMiddleware', 'django.middleware.common.CommonMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', + + # Instead of AuthenticationMiddleware, we use a cached backed version + #'django.contrib.auth.middleware.AuthenticationMiddleware', + 'cache_toolbox.middleware.CacheBackedAuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', 'track.middleware.TrackMiddleware', 'mitxmako.middleware.MakoMiddleware', - # 'debug_toolbar.middleware.DebugToolbarMiddleware', + 'askbot.middleware.anon_user.ConnectToSessionMessagesMiddleware', 'askbot.middleware.forum_mode.ForumModeMiddleware', 'askbot.middleware.cancel.CancelActionMiddleware', @@ -303,46 +217,41 @@ MIDDLEWARE_CLASSES = ( 'askbot.middleware.view_log.ViewLogMiddleware', 'askbot.middleware.spaceless.SpacelessMiddleware', # 'askbot.middleware.pagesize.QuestionsPageSizeMiddleware', + # 'debug_toolbar.middleware.DebugToolbarMiddleware', ) ################################### APPS ####################################### -def installed_apps(): - """If you want to get a different set of INSTALLED_APPS out of this, you'll - have to set ASKBOT_ENABLED and COURSEWARE_ENABLED to True/False and call - this method. We can't just take these as params because other pieces of the - code check fo the value of these constants. - """ - # We always install these - STANDARD_APPS = ['django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.humanize', - 'django.contrib.sessions', - 'django.contrib.sites', - 'django.contrib.messages', - 'django.contrib.staticfiles', - 'track', - 'util'] - COURSEWARE_APPS = ['circuit', - 'courseware', - 'student', - 'static_template_view', - 'staticbook', - 'simplewiki', - 'perfstats'] - ASKBOT_APPS = ['django.contrib.sitemaps', - 'django.contrib.admin', - 'south', - 'askbot.deps.livesettings', - 'askbot', - 'keyedcache', - 'robots', - 'django_countries', - 'djcelery', - 'djkombu', - 'followit'] - - return tuple(STANDARD_APPS + - (COURSEWARE_APPS if COURSEWARE_ENABLED else []) + - (ASKBOT_APPS if ASKBOT_ENABLED else [])) +INSTALLED_APPS = ( + # Standard ones that are always installed... + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.humanize', + 'django.contrib.messages', + 'django.contrib.sessions', + 'django.contrib.sites', + 'django.contrib.staticfiles', + 'south', -INSTALLED_APPS = installed_apps() + # Our courseware + 'circuit', + 'courseware', + 'perfstats', + 'student', + 'static_template_view', + 'staticbook', + 'simplewiki', + 'track', + 'util', + + # For Askbot + 'django.contrib.sitemaps', + 'django.contrib.admin', + 'django_countries', + 'djcelery', + 'djkombu', + 'askbot', + 'askbot.deps.livesettings', + 'followit', + 'keyedcache', + 'robots', +) diff --git a/envs/content.py b/envs/content.py new file mode 100644 index 0000000000..c02e7bb72e --- /dev/null +++ b/envs/content.py @@ -0,0 +1,31 @@ +""" +These are debug machines used for content creators, so they're kind of a cross +between dev machines and AWS machines. +""" +from aws import * + +DEBUG = True +TEMPLATE_DEBUG = True + +EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' + +################################ DEBUG TOOLBAR ################################# +INSTALLED_APPS += ('debug_toolbar',) +MIDDLEWARE_CLASSES += ('debug_toolbar.middleware.DebugToolbarMiddleware',) + +DEBUG_TOOLBAR_PANELS = ( + 'debug_toolbar.panels.version.VersionDebugPanel', + 'debug_toolbar.panels.timer.TimerDebugPanel', + 'debug_toolbar.panels.settings_vars.SettingsVarsDebugPanel', + 'debug_toolbar.panels.headers.HeaderDebugPanel', + 'debug_toolbar.panels.request_vars.RequestVarsDebugPanel', + 'debug_toolbar.panels.sql.SQLDebugPanel', + 'debug_toolbar.panels.signals.SignalDebugPanel', + 'debug_toolbar.panels.logger.LoggingPanel', + +# Enabling the profiler has a weird bug as of django-debug-toolbar==0.9.4 and +# Django=1.3.1/1.4 where requests to views get duplicated (your method gets +# hit twice). So you can uncomment when you need to diagnose performance +# problems, but you shouldn't leave it on. +# 'debug_toolbar.panels.profiling.ProfilingDebugPanel', +) diff --git a/envs/dev.py b/envs/dev.py new file mode 100644 index 0000000000..1a62eaf382 --- /dev/null +++ b/envs/dev.py @@ -0,0 +1,81 @@ +""" +This config file runs the simplest dev environment using sqlite, and db-based +sessions. Assumes structure: + +/envroot/ + /db # This is where it'll write the database file + /mitx # The location of this repo + /log # Where we're going to write log files +""" +from common import * + +DEBUG = True +TEMPLATE_DEBUG = True + +LOGGING = logsettings.get_logger_config(ENV_ROOT / "log", + logging_env="dev", + tracking_filename="tracking.log", + debug=True) + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': ENV_ROOT / "db" / "mitx.db", + } +} + +CACHES = { + # This is the cache used for most things. Askbot will not work without a + # functioning cache -- it relies on caching to load its settings in places. + # In staging/prod envs, the sessions also live here. + 'default': { + 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', + 'LOCATION': 'mitx_loc_mem_cache' + }, + + # The general cache is what you get if you use our util.cache. It's used for + # things like caching the course.xml file for different A/B test groups. + # We set it to be a DummyCache to force reloading of course.xml in dev. + # In staging environments, we would grab VERSION from data uploaded by the + # push process. + 'general': { + 'BACKEND': 'django.core.cache.backends.dummy.DummyCache', + 'KEY_PREFIX': 'general', + 'VERSION': 4, + } +} + +# Dummy secret key for dev +SECRET_KEY = '85920908f28904ed733fe576320db18cabd7b6cd' + +################################ DEBUG TOOLBAR ################################# +INSTALLED_APPS += ('debug_toolbar',) +MIDDLEWARE_CLASSES += ('debug_toolbar.middleware.DebugToolbarMiddleware',) +INTERNAL_IPS = ('127.0.0.1',) + +DEBUG_TOOLBAR_PANELS = ( + 'debug_toolbar.panels.version.VersionDebugPanel', + 'debug_toolbar.panels.timer.TimerDebugPanel', + 'debug_toolbar.panels.settings_vars.SettingsVarsDebugPanel', + 'debug_toolbar.panels.headers.HeaderDebugPanel', + 'debug_toolbar.panels.request_vars.RequestVarsDebugPanel', + 'debug_toolbar.panels.sql.SQLDebugPanel', + 'debug_toolbar.panels.signals.SignalDebugPanel', + 'debug_toolbar.panels.logger.LoggingPanel', + +# Enabling the profiler has a weird bug as of django-debug-toolbar==0.9.4 and +# Django=1.3.1/1.4 where requests to views get duplicated (your method gets +# hit twice). So you can uncomment when you need to diagnose performance +# problems, but you shouldn't leave it on. +# 'debug_toolbar.panels.profiling.ProfilingDebugPanel', +) + +############################ FILE UPLOADS (ASKBOT) ############################# +DEFAULT_FILE_STORAGE = 'django.core.files.storage.FileSystemStorage' +MEDIA_ROOT = ENV_ROOT / "uploads" +MEDIA_URL = "/discussion/upfiles/" +FILE_UPLOAD_TEMP_DIR = ENV_ROOT / "uploads" +FILE_UPLOAD_HANDLERS = ( + 'django.core.files.uploadhandler.MemoryFileUploadHandler', + 'django.core.files.uploadhandler.TemporaryFileUploadHandler', +) diff --git a/envs/devplus.py b/envs/devplus.py new file mode 100644 index 0000000000..2ec38b53a0 --- /dev/null +++ b/envs/devplus.py @@ -0,0 +1,42 @@ +""" +This config file tries to mimic the production environment more closely than the +normal dev.py. It assumes you're running a local instance of MySQL 5.1 and that +you're running memcached. You'll want to use this to test caching and database +migrations. + +Assumptions: +* MySQL 5.1 (version important -- askbot breaks on 5.5) + +Dir structure: +/envroot/ + /mitx # The location of this repo + /log # Where we're going to write log files + +""" +from dev import * + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.mysql', + 'NAME': 'wwc', + 'USER': 'root', + 'PASSWORD': '', + 'HOST': '127.0.0.1', + 'PORT': '3306', + } +} + +CACHES = { + 'default': { + 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', + 'LOCATION': '127.0.0.1:11211', + }, + 'general': { + 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', + 'LOCATION': '127.0.0.1:11211', + 'KEY_PREFIX' : 'general', + 'VERSION' : 5, + } +} + +SESSION_ENGINE = 'django.contrib.sessions.backends.cache' diff --git a/envs/logsettings.py b/envs/logsettings.py new file mode 100644 index 0000000000..9edf9ad0b3 --- /dev/null +++ b/envs/logsettings.py @@ -0,0 +1,86 @@ +import os +import os.path +import platform +import sys + +def get_logger_config(log_dir, + logging_env="no_env", + tracking_filename=None, + syslog_addr=None, + debug=False): + """Return the appropriate logging config dictionary. You should assign the + result of this to the LOGGING var in your settings. The reason it's done + this way instead of registering directly is because I didn't want to worry + about resetting the logging state if this is called multiple times when + settings are extended.""" + + # If we're given an explicit place to put tracking logs, we do that (say for + # debugging). However, logging is not safe for multiple processes hitting + # the same file. So if it's left blank, we dynamically create the filename + # based on the PID of this worker process. + if tracking_filename: + tracking_file_loc = os.path.join(log_dir, tracking_filename) + else: + pid = os.getpid() # So we can log which process is creating the log + tracking_file_loc = os.path.join(log_dir, "tracking_{0}.log".format(pid)) + + hostname = platform.node().split(".")[0] + syslog_format = ("[%(name)s][env:{logging_env}] %(levelname)s [{hostname} " + + " %(process)d] [%(filename)s:%(lineno)d] - %(message)s").format( + logging_env=logging_env, hostname=hostname) + + handlers = ['console'] if debug else ['console', 'syslogger'] + + return { + 'version': 1, + 'disable_existing_loggers': True, + 'formatters' : { + 'standard' : { + 'format' : '%(asctime)s %(levelname)s %(process)d [%(name)s] %(filename)s:%(lineno)d - %(message)s', + }, + 'syslog_format' : { 'format' : syslog_format }, + 'raw' : { 'format' : '%(message)s' }, + }, + 'handlers' : { + 'console' : { + 'level' : 'DEBUG' if debug else 'INFO', + 'class' : 'logging.StreamHandler', + 'formatter' : 'standard', + 'stream' : sys.stdout, + }, + 'syslogger' : { + 'level' : 'INFO', + 'class' : 'logging.handlers.SysLogHandler', + 'address' : syslog_addr, + 'formatter' : 'syslog_format', + }, + 'tracking' : { + 'level' : 'DEBUG', + 'class' : 'logging.handlers.WatchedFileHandler', + 'filename' : tracking_file_loc, + 'formatter' : 'raw', + }, + }, + 'loggers' : { + 'django' : { + 'handlers' : handlers, + 'propagate' : True, + 'level' : 'INFO' + }, + 'tracking' : { + 'handlers' : ['tracking'], + 'level' : 'DEBUG', + 'propagate' : False, + }, + 'root' : { + 'handlers' : handlers, + 'level' : 'DEBUG', + 'propagate' : False + }, + 'mitx' : { + 'handlers' : handlers, + 'level' : 'DEBUG', + 'propagate' : False + }, + } + } \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index a9fc71e6c9..f589c7c732 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,5 @@ django<1.4 pip -flup scipy matplotlib markdown @@ -12,3 +11,6 @@ boto mako python-memcached django-celery +path.py +django_debug_toolbar + diff --git a/settings2/README.txt b/settings2/README.txt deleted file mode 100644 index 64a4c910df..0000000000 --- a/settings2/README.txt +++ /dev/null @@ -1,4 +0,0 @@ -Transitional for moving to new settings scheme. - -To use: -django-admin runserver --settings=settings2.dev --pythonpath="." diff --git a/settings2/aws.py b/settings2/aws.py deleted file mode 100644 index 138f52c255..0000000000 --- a/settings2/aws.py +++ /dev/null @@ -1,18 +0,0 @@ -from common import * - -EMAIL_BACKEND = 'django_ses.SESBackend' -SESSION_ENGINE = 'django.contrib.sessions.backends.cache' -DEFAULT_FILE_STORAGE = 'storages.backends.s3boto.S3BotoStorage' - -CSRF_COOKIE_DOMAIN = '.mitx.mit.edu' -LIB_URL = 'https://mitxstatic.s3.amazonaws.com/js/' -BOOK_URL = 'https://mitxstatic.s3.amazonaws.com/book_images/' - -CACHES = { - 'default': { - 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', - } -} - -DEBUG = False -TEMPLATE_DEBUG = False diff --git a/settings2/dev.py b/settings2/dev.py deleted file mode 100644 index 925f9ac02f..0000000000 --- a/settings2/dev.py +++ /dev/null @@ -1,28 +0,0 @@ -""" -This config file runs the simplest dev environment using sqlite, and db-based -sessions. -""" -from common import * - -CSRF_COOKIE_DOMAIN = 'localhost' - -DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': ENV_ROOT / "db" / "mitx.db", - } -} - -# Make this unique, and don't share it with anybody. -SECRET_KEY = '85920908f28904ed733fe576320db18cabd7b6cd' - -DEBUG = True -TEMPLATE_DEBUG = False - -# This is disabling ASKBOT, but not properly overwriting INSTALLED_APPS. ??? -# It's because our ASKBOT_ENABLED here is actually shadowing the real one. -# -# ASKBOT_ENABLED = True -# MITX_FEATURES['SAMPLE'] = True # Switch to this system so we get around the shadowing -# -# INSTALLED_APPS = installed_apps() diff --git a/settings2/devplus.py b/settings2/devplus.py deleted file mode 100644 index 9cc9a67779..0000000000 --- a/settings2/devplus.py +++ /dev/null @@ -1,35 +0,0 @@ -""" -This config file tries to mimic the production environment more closely than the -normal dev.py. It assumes you're running a local instance of MySQL 5.1 and that -you're running memcached. -""" -from common import * - -CSRF_COOKIE_DOMAIN = 'localhost' - -DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.mysql', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'. - 'NAME': 'wwc', # Or path to database file if using sqlite3. - 'USER': 'root', # Not used with sqlite3. - 'PASSWORD': '', # Not used with sqlite3. - 'HOST': '127.0.0.1', # Set to empty string for localhost. Not used with sqlite3. - 'PORT': '3306', # Set to empty string for default. Not used with sqlite3. - } -} - -# Make this unique, and don't share it with anybody. -SECRET_KEY = '85920908f28904ed733fe576320db18cabd7b6cd' - -CACHES = { - 'default': { - 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', - 'LOCATION': '127.0.0.1:11211', - } -} - - -SESSION_ENGINE = 'django.contrib.sessions.backends.cache' - -DEBUG = True -TEMPLATE_DEBUG = True \ No newline at end of file diff --git a/settings2/loadtest.py b/settings2/loadtest.py deleted file mode 100644 index 172fbcc125..0000000000 --- a/settings2/loadtest.py +++ /dev/null @@ -1,3 +0,0 @@ -from common import * - -GENERATE_RANDOM_USER_CREDENTIALS = True diff --git a/settings2/staging.py b/settings2/staging.py deleted file mode 100644 index 0c7dba41b6..0000000000 --- a/settings2/staging.py +++ /dev/null @@ -1,13 +0,0 @@ -from aws import * - -# Staging specific overrides -SITE_NAME = "staging.mitx.mit.edu" -AWS_STORAGE_BUCKET_NAME = 'mitx_askbot_stage' -CACHES['default']['LOCATION'] = ['***REMOVED***', - '***REMOVED***'] - -### Secure Data Below Here ### -SECRET_KEY = "" -AWS_ACCESS_KEY_ID = "" -AWS_SECRET_ACCESS_KEY = "" - diff --git a/static/js/mathjax b/static/js/mathjax new file mode 120000 index 0000000000..b33a920293 --- /dev/null +++ b/static/js/mathjax @@ -0,0 +1 @@ +mathjax-MathJax-c9db6ac/ \ No newline at end of file diff --git a/urls.py b/urls.py index def5bac7de..329d500ea0 100644 --- a/urls.py +++ b/urls.py @@ -1,6 +1,8 @@ from django.conf import settings from django.conf.urls.defaults import patterns, include, url from django.contrib import admin +from django.contrib.staticfiles.urls import staticfiles_urlpatterns + import django.contrib.auth.views # Uncomment the next two lines to enable the admin: @@ -40,38 +42,43 @@ urlpatterns = ('', ) if settings.PERFSTATS: - urlpatterns=urlpatterns + (url(r'^reprofile$','perfstats.views.end_profile'),) + urlpatterns += (url(r'^reprofile$','perfstats.views.end_profile'),) if settings.COURSEWARE_ENABLED: - urlpatterns=urlpatterns + (url(r'^courseware/$', 'courseware.views.index', name="courseware"), - url(r'^info$', 'util.views.info'), - url(r'^wiki/', include('simplewiki.urls')), - url(r'^courseware/(?P[^/]*)/(?P[^/]*)/(?P
[^/]*)/$', 'courseware.views.index', name="courseware_section"), - url(r'^courseware/(?P[^/]*)/(?P[^/]*)/$', 'courseware.views.index', name="courseware_chapter"), - url(r'^courseware/(?P[^/]*)/$', 'courseware.views.index', name="courseware_course"), - url(r'^section/(?P
[^/]*)/$', 'courseware.views.render_section'), - url(r'^modx/(?P[^/]*)/(?P[^/]*)/(?P[^/]*)$', 'courseware.views.modx_dispatch'), #reset_problem'), - url(r'^profile$', 'courseware.views.profile'), - url(r'^profile/(?P[^/]*)/$', 'courseware.views.profile'), - url(r'^change_setting$', 'student.views.change_setting'), - url(r'^s/(?P