Browse Source

Separated flaskbb’s settings from flask’s settings

sh4nks 11 years ago
parent
commit
1ac7148ec0

+ 14 - 11
flaskbb/admin/models.py

@@ -1,7 +1,8 @@
+import sys
 from wtforms import (TextField, IntegerField, FloatField, BooleanField,
                      SelectField, SelectMultipleField, validators)
 from flask.ext.wtf import Form
-from flaskbb.extensions import db
+from flaskbb.extensions import db, cache
 
 
 class SettingsGroup(db.Model):
@@ -164,26 +165,21 @@ class Setting(db.Model):
 
     @classmethod
     def update(cls, settings, app=None):
-        """Updates the current_app's config and stores the changes in the
+        """Updates the cache and stores the changes in the
         database.
 
         :param settings: A dictionary with setting items.
         """
-        updated_settings = {}
+        # update the database
         for key, value in settings.iteritems():
             setting = cls.query.filter(Setting.key == key.lower()).first()
 
             setting.value = value
 
-            updated_settings[setting.key.upper()] = setting.value
-
             db.session.add(setting)
             db.session.commit()
 
-        # update cache here
-
-        if app is not None:
-            app.config.update(updated_settings)
+        cls.invalidate_cache()
 
     @classmethod
     def get_settings(cls, from_group=None):
@@ -212,8 +208,10 @@ class Setting(db.Model):
         return settings
 
     @classmethod
-    def as_dict(cls, from_group=None, upper=False):
-        """Returns all settings as a dict
+    @cache.memoize(timeout=sys.maxint)
+    def as_dict(cls, from_group=None, upper=True):
+        """Returns all settings as a dict. This method is cached. If you want
+        to invalidate the cache, simply execute ``self.invalidate_cache()``.
 
         :param from_group: Returns only the settings from the group as a dict.
         :param upper: If upper is ``True``, the key will use upper-case
@@ -239,6 +237,11 @@ class Setting(db.Model):
 
         return settings
 
+    @classmethod
+    def invalidate_cache(cls):
+        """Invalidates this objects cached metadata."""
+        cache.delete_memoized(cls.as_dict, cls)
+
     def save(self):
         """Saves a setting"""
         db.session.add(self)

+ 15 - 13
flaskbb/app.py

@@ -15,8 +15,6 @@ import datetime
 from flask import Flask, request
 from flask.ext.login import current_user
 
-from sqlalchemy.exc import OperationalError
-
 # Import the user blueprint
 from flaskbb.user.views import user
 from flaskbb.user.models import User, Guest, PrivateMessage
@@ -24,7 +22,6 @@ from flaskbb.user.models import User, Guest, PrivateMessage
 from flaskbb.auth.views import auth
 # Import the admin blueprint
 from flaskbb.admin.views import admin
-from flaskbb.admin.models import Setting
 # Import the forum blueprint
 from flaskbb.forum.views import forum
 from flaskbb.forum.models import Post, Topic, Category, Forum
@@ -40,6 +37,8 @@ from flaskbb.utils.helpers import format_date, time_since, crop_title, \
 from flaskbb.utils.permissions import can_post_reply, can_post_topic, \
     can_delete_topic, can_delete_post, can_edit_post, can_lock_topic, \
     can_move_topic
+# app specific configurations
+from flaskbb.utils.settings import flaskbb_config
 
 
 def create_app(config=None):
@@ -59,10 +58,10 @@ def create_app(config=None):
     configure_blueprints(app)
     configure_extensions(app)
     configure_template_filters(app)
+    configure_context_processors(app)
     configure_before_handlers(app)
     configure_errorhandlers(app)
     configure_logging(app)
-    update_settings_from_db(app)
 
     return app
 
@@ -135,15 +134,6 @@ def configure_extensions(app):
     login_manager.init_app(app)
 
 
-def update_settings_from_db(app):
-    try:
-        if not app.config["TESTING"]:
-            with app.app_context():
-                app.config.update(Setting.as_dict(upper=True))
-    except OperationalError:
-        pass
-
-
 def configure_template_filters(app):
     """
     Configures the template filters
@@ -165,6 +155,18 @@ def configure_template_filters(app):
     app.jinja_env.filters['post_topic'] = can_post_topic
 
 
+def configure_context_processors(app):
+    """
+    Configures the context processors
+    """
+    @app.context_processor
+    def inject_flaskbb_config():
+        """
+        Injects the ``flaskbb_config`` config variable into the templates.
+        """
+        return dict(flaskbb_config=flaskbb_config)
+
+
 def configure_before_handlers(app):
     """
     Configures the before request handlers

+ 3 - 2
flaskbb/forum/models.py

@@ -14,6 +14,7 @@ from flask import current_app, url_for, abort
 
 from flaskbb.extensions import db
 from flaskbb.utils.helpers import slugify, get_categories_and_forums, get_forums
+from flaskbb.utils.settings import flaskbb_config
 
 
 moderators = db.Table(
@@ -345,9 +346,9 @@ class Topic(db.Model):
                            a new post in the topic.
         """
         read_cutoff = None
-        if current_app.config['TRACKER_LENGTH'] > 0:
+        if ['TRACKER_LENGTH'] > 0:
             read_cutoff = datetime.utcnow() - timedelta(
-                days=current_app.config['TRACKER_LENGTH'])
+                days=flaskbb_config['TRACKER_LENGTH'])
 
         # The tracker is disabled - abort
         if read_cutoff is None:

+ 7 - 6
flaskbb/forum/views.py

@@ -17,6 +17,7 @@ from flask import (Blueprint, redirect, url_for, current_app,
 from flask.ext.login import login_required, current_user
 
 from flaskbb.extensions import db
+from flaskbb.utils.settings import flaskbb_config
 from flaskbb.utils.helpers import get_online_users, time_diff, render_template
 from flaskbb.utils.permissions import (can_post_reply, can_post_topic,
                                        can_delete_topic, can_delete_post,
@@ -79,7 +80,7 @@ def view_forum(forum_id, slug=None):
 
     forum, forumsread = Forum.get_forum(forum_id=forum_id, user=current_user)
     topics = Forum.get_topics(forum_id=forum.id, user=current_user, page=page,
-                              per_page=current_app.config["TOPICS_PER_PAGE"])
+                              per_page=flaskbb_config["TOPICS_PER_PAGE"])
 
     return render_template("forum/forum.html", forum=forum, topics=topics,
                            forumsread=forumsread,)
@@ -92,7 +93,7 @@ def view_topic(topic_id, slug=None):
 
     topic = Topic.query.filter_by(id=topic_id).first()
     posts = Post.query.filter_by(topic_id=topic.id).\
-        paginate(page, current_app.config['POSTS_PER_PAGE'], False)
+        paginate(page, flaskbb_config['POSTS_PER_PAGE'], False)
 
     # Count the topic views
     topic.views += 1
@@ -127,7 +128,7 @@ def view_topic(topic_id, slug=None):
 def view_post(post_id):
     post = Post.query.filter_by(id=post_id).first_or_404()
     count = post.topic.post_count
-    page = math.ceil(count / current_app.config["POSTS_PER_PAGE"])
+    page = math.ceil(count / flaskbb_config["POSTS_PER_PAGE"])
     if count > 10:
         page += 1
     else:
@@ -427,12 +428,12 @@ def memberlist():
 
     if search_form.validate():
         users = search_form.get_results().\
-            paginate(page, current_app.config['USERS_PER_PAGE'], False)
+            paginate(page, flaskbb_config['USERS_PER_PAGE'], False)
         return render_template("forum/memberlist.html", users=users,
                                search_form=search_form)
     else:
         users = User.query.\
-            paginate(page, current_app.config['USERS_PER_PAGE'], False)
+            paginate(page, flaskbb_config['USERS_PER_PAGE'], False)
         return render_template("forum/memberlist.html", users=users,
                                search_form=search_form)
 
@@ -446,7 +447,7 @@ def topictracker():
                           TopicsRead.user_id == current_user.id)).\
         add_entity(TopicsRead).\
         order_by(Post.id.desc()).\
-        paginate(page, current_app.config['TOPICS_PER_PAGE'], True)
+        paginate(page, flaskbb_config['TOPICS_PER_PAGE'], True)
 
     return render_template("forum/topictracker.html", topics=topics)
 

+ 2 - 2
flaskbb/plugins/portal/views.py

@@ -4,7 +4,7 @@ from flaskbb.utils.helpers import render_template
 from flaskbb.forum.models import Topic, Post
 from flaskbb.user.models import User
 from flaskbb.utils.helpers import time_diff, get_online_users
-
+from flaskbb.utils.settings import flaskbb_config
 
 portal = Blueprint("portal", __name__, template_folder="templates")
 
@@ -16,7 +16,7 @@ def inject_portal_link():
 @portal.route("/")
 def index():
     try:
-        forum_ids = current_app.config["PLUGIN_PORTAL_FORUM_IDS"]
+        forum_ids = flaskbb_config["PLUGIN_PORTAL_FORUM_IDS"]
     except KeyError:
         forum_ids = [1]
         flash("Please install the plugin first to configure the forums "

+ 1 - 1
flaskbb/templates/forum/forum.html

@@ -74,7 +74,7 @@
                 <div>
                     <a href="{{ topic.url }}">{{ topic.title }}</a>
                     <!-- Topic Pagination -->
-                    {{ topic_pages(topic, config["POSTS_PER_PAGE"]) }}
+                    {{ topic_pages(topic, flaskbb_config["POSTS_PER_PAGE"]) }}
                     <br />
                     {% if topic.user_id %}
                     <small>by <a href="{{ topic.user.url }}">{{ topic.user.username }}</a></small>

+ 1 - 1
flaskbb/templates/forum/search_result.html

@@ -135,7 +135,7 @@
                         <div>
                             <a href="{{ topic.url }}">{{ topic.title }}</a>
                             <!-- Topic Pagination -->
-                            {{ topic_pages(topic, config["POSTS_PER_PAGE"]) }}
+                            {{ topic_pages(topic, flaskbb_config["POSTS_PER_PAGE"]) }}
                             <br />
                             {% if topic.user_id %}
                                 <small>by <a href="{{ topic.user.url }}">{{ topic.user.username }}</a></small>

+ 1 - 1
flaskbb/templates/forum/topic.html

@@ -63,7 +63,7 @@
         <tr>
             <td >
                 <span class="pull-right">
-                    <strong>#{%- if posts.page == 1 -%} {{ loop.index }} {%- else -%} {{ loop.index + (posts.page - 1) * config["POSTS_PER_PAGE"] }} {%- endif -%}</strong>
+                    <strong>#{%- if posts.page == 1 -%} {{ loop.index }} {%- else -%} {{ loop.index + (posts.page - 1) * flaskbb_config["POSTS_PER_PAGE"] }} {%- endif -%}</strong>
                 </span>
                 <span class="pull-left">
                     <a href="

+ 2 - 2
flaskbb/templates/layout.html

@@ -5,9 +5,9 @@
         <title>
         {% block title %}
             {%- if not page_title -%}
-                {{ config["PROJECT_TITLE"] }} - {{ config["PROJECT_SUBTITLE"] }}
+                {{ flaskbb_config["PROJECT_TITLE"] }} - {{ flaskbb_config["PROJECT_SUBTITLE"] }}
             {%- else -%}
-                {{ page_title }} - {{ config["PROJECT_TITLE"] }}
+                {{ page_title }} - {{ flaskbb_config["PROJECT_TITLE"] }}
             {%- endif -%}
         {% endblock %}
         </title>

+ 2 - 2
flaskbb/themes/bootstrap2/templates/layout.html

@@ -5,9 +5,9 @@
         <title>
         {% block title %}
             {%- if not page_title -%}
-                {{ config["PROJECT_TITLE"] }} - {{ config["PROJECT_SUBTITLE"] }}
+                {{ flaskbb_config["PROJECT_TITLE"] }} - {{ flaskbb_config["PROJECT_SUBTITLE"] }}
             {%- else -%}
-                {{ page_title }} - {{ config["PROJECT_TITLE"] }}
+                {{ page_title }} - {{ flaskbb_config["PROJECT_TITLE"] }}
             {%- endif -%}
         {% endblock %}
         </title>

+ 2 - 2
flaskbb/themes/bootstrap3/templates/layout.html

@@ -5,9 +5,9 @@
         <title>
         {% block title %}
             {%- if not page_title -%}
-                {{ config["PROJECT_TITLE"] }} - {{ config["PROJECT_SUBTITLE"] }}
+                {{ flaskbb_config["PROJECT_TITLE"] }} - {{ flaskbb_config["PROJECT_SUBTITLE"] }}
             {%- else -%}
-                {{ page_title }} - {{ config["PROJECT_TITLE"] }}
+                {{ page_title }} - {{ flaskbb_config["PROJECT_TITLE"] }}
             {%- endif -%}
         {% endblock %}
         </title>

+ 0 - 1
flaskbb/user/__init__.py

@@ -1 +0,0 @@
-

+ 3 - 2
flaskbb/user/models.py

@@ -17,6 +17,7 @@ from werkzeug import generate_password_hash, check_password_hash
 from flask import current_app, url_for
 from flask.ext.login import UserMixin, AnonymousUserMixin
 from flaskbb.extensions import db, cache
+from flaskbb.utils.settings import flaskbb_config
 from flaskbb.forum.models import (Post, Topic, topictracker, TopicsRead,
                                   ForumsRead)
 
@@ -218,13 +219,13 @@ class User(db.Model, UserMixin):
         return Topic.query.filter(Topic.user_id == self.id).\
             filter(Post.topic_id == Topic.id).\
             order_by(Post.id.desc()).\
-            paginate(page, current_app.config['TOPICS_PER_PAGE'], False)
+            paginate(page, flaskbb_config['TOPICS_PER_PAGE'], False)
 
     def all_posts(self, page):
         """Returns a paginated result with all posts the user has created."""
 
         return Post.query.filter(Post.user_id == self.id).\
-            paginate(page, current_app.config['TOPICS_PER_PAGE'], False)
+            paginate(page, flaskbb_config['TOPICS_PER_PAGE'], False)
 
     def track_topic(self, topic):
         """Tracks the specified topic

+ 7 - 6
flaskbb/utils/helpers.py

@@ -22,6 +22,7 @@ from flask.ext.login import current_user
 from postmarkup import render_bbcode
 
 from flaskbb.extensions import redis
+from flaskbb.utils.settings import flaskbb_config
 
 _punct_re = re.compile(r'[\t !"#$%&\'()*\-/<=>?@\[\\\]^_`{|},.]+')
 
@@ -48,7 +49,7 @@ def render_template(template, **context):
     if current_user.is_authenticated() and current_user.theme:
         theme = current_user.theme
     else:
-        theme = session.get('theme', current_app.config['DEFAULT_THEME'])
+        theme = session.get('theme', flaskbb_config['DEFAULT_THEME'])
     return render_theme_template(theme, template, **context)
 
 
@@ -139,7 +140,7 @@ def forum_is_unread(forum, forumsread, user):
         return False
 
     read_cutoff = datetime.utcnow() - timedelta(
-        days=current_app.config["TRACKER_LENGTH"])
+        days=flaskbb_config["TRACKER_LENGTH"])
 
     # If there are no topics in the forum, mark it as read
     if forum and forum.topic_count == 0:
@@ -173,7 +174,7 @@ def topic_is_unread(topic, topicsread, user, forumsread=None):
         return False
 
     read_cutoff = datetime.utcnow() - timedelta(
-        days=current_app.config["TRACKER_LENGTH"])
+        days=flaskbb_config["TRACKER_LENGTH"])
 
     # topicsread is none if the user has marked the forum as read
     # or if he hasn't visited yet
@@ -238,7 +239,7 @@ def get_online_users(guest=False):
     :param guest: If True, it will return the online guests
     """
     current = int(time.time()) // 60
-    minutes = xrange(current_app.config['ONLINE_LAST_MINUTES'])
+    minutes = xrange(flaskbb_config['ONLINE_LAST_MINUTES'])
     if guest:
         return redis.sunion(['online-guests/%d' % (current - x)
                              for x in minutes])
@@ -251,7 +252,7 @@ def crop_title(title):
 
     :param title: The title that should be cropped
     """
-    length = current_app.config['TITLE_LENGTH']
+    length = flaskbb_config['TITLE_LENGTH']
     if len(title) > length:
         return title[:length] + "..."
     return title
@@ -279,7 +280,7 @@ def time_diff():
     variable from the configuration.
     """
     now = datetime.utcnow()
-    diff = now - timedelta(minutes=current_app.config['ONLINE_LAST_MINUTES'])
+    diff = now - timedelta(minutes=flaskbb_config['ONLINE_LAST_MINUTES'])
     return diff
 
 

+ 41 - 0
flaskbb/utils/settings.py

@@ -0,0 +1,41 @@
+# -*- coding: utf-8 -*-
+"""
+    flaskbb.utils.settings
+    ~~~~~~~~~~~~~~~~~~~~~~
+
+    This module contains the interface for interacting with FlaskBB's
+    configuration.
+
+    :copyright: (c) 2014 by the FlaskBB Team.
+    :license: BSD, see LICENSE for more details.
+"""
+import collections
+
+from flaskbb.admin.models import Setting
+
+
+class FlaskBBConfig(collections.MutableMapping):
+    """Provides a dictionary like interface for interacting with FlaskBB's
+    Settings cache.
+    """
+
+    def __init__(self, *args, **kwargs):
+        self.update(dict(*args, **kwargs))
+
+    def __getitem__(self, key):
+        return Setting.as_dict()[key]
+
+    def __setitem__(self, key, value):
+        Setting.update({key.lower(): value})
+
+    def __delitem__(self, key):
+        pass
+
+    def __iter__(self):
+        return iter(Setting.as_dict())
+
+    def __len__(self):
+        return len(Setting.as_dict())
+
+
+flaskbb_config = FlaskBBConfig()