From 303b118d8ffc0ed2285166e362a91774f64ad807 Mon Sep 17 00:00:00 2001 From: hernani Date: Fri, 9 Jul 2010 02:25:38 +0000 Subject: [PATCH] Adds a user preferences page. Not much to see yet, only the preference to make sorts sticky. git-svn-id: http://svn.osqa.net/svnroot/osqa/trunk@510 0cfe37f9-358a-4d5e-be75-b63607b5c754 --- forum/forms/qanda.py | 3 ++ forum/models/base.py | 4 +- forum/models/user.py | 14 ++++++- forum/registry.py | 5 +++ .../default/templates/users/preferences.html | 29 ++++++++++++++ forum/urls.py | 2 + forum/utils/pagination.py | 38 ++++++++++++++----- forum/views/readers.py | 7 +++- forum/views/users.py | 23 ++++++++++- 9 files changed, 107 insertions(+), 18 deletions(-) create mode 100644 forum/skins/default/templates/users/preferences.html diff --git a/forum/forms/qanda.py b/forum/forms/qanda.py index ade6d5d..672ffd8 100644 --- a/forum/forms/qanda.py +++ b/forum/forms/qanda.py @@ -291,5 +291,8 @@ class SubscriptionSettingsForm(forms.ModelForm): class Meta: model = SubscriptionSettings +class UserPreferencesForm(forms.Form): + sticky_sorts = forms.BooleanField(required=False, initial=False) + diff --git a/forum/models/base.py b/forum/models/base.py index fff741c..3d54d75 100644 --- a/forum/models/base.py +++ b/forum/models/base.py @@ -151,10 +151,10 @@ class BaseModel(models.Model): (f.name, getattr(self, f.name)) for f in self._meta.fields if self._original_state[f.attname] != self.__dict__[f.attname] ]) - def save(self, *args, **kwargs): + def save(self, full_save=False, *args, **kwargs): put_back = [k for k, v in self.__dict__.items() if isinstance(v, models.expressions.ExpressionNode)] - if self.id: + if self.id and not full_save: self.__class__.objects.filter(id=self.id).update(**self._get_update_kwargs()) else: super(BaseModel, self).save() diff --git a/forum/models/user.py b/forum/models/user.py index 34c6b36..2e71868 100644 --- a/forum/models/user.py +++ b/forum/models/user.py @@ -364,7 +364,7 @@ class User(BaseModel, DjangoUser): class Meta: app_label = 'forum' -class UserProperty(models.Model): +class UserProperty(BaseModel): user = models.ForeignKey(User, related_name='properties') key = models.CharField(max_length=16) value = PickledObjectField() @@ -373,6 +373,16 @@ class UserProperty(models.Model): app_label = 'forum' unique_together = ('user', 'key') + def cache_key(self): + return self._generate_cache_key("%s:%s" % (self.user.id, self.key)) + + @classmethod + def infer_cache_key(cls, querydict): + if 'user' in querydict and 'key' in querydict: + return cls._generate_cache_key("%s:%s" % (querydict['user'].id, querydict['key'])) + + return None + class UserPropertyDict(object): def __init__(self, user): self.__dict__['_user'] = user @@ -408,7 +418,7 @@ class UserPropertyDict(object): if current: current.value = value self.__dict__[name] = value - current.save() + current.save(full_save=True) else: user = self.__dict__['_user'] prop = UserProperty(user=user, value=value, key=name) diff --git a/forum/registry.py b/forum/registry.py index 6fad2f0..95aea18 100644 --- a/forum/registry.py +++ b/forum/registry.py @@ -73,6 +73,11 @@ ui.register(ui.USER_MENU, span_attrs={'class': 'user-subscriptions'}, weight=200 ), + ui.UserMenuItem( + label=_("other preferences"), + url=lambda u, c: reverse('user_preferences', kwargs={'id': c['user'].id, 'slug': slugify(c['user'].username)}), + weight=200 + ), ModerationMenuGroup(_("Moderation tools"), items=( ui.UserMenuItem( label=lambda u, c: c['user'].is_suspended() and _("withdraw suspension") or _("suspend this user"), diff --git a/forum/skins/default/templates/users/preferences.html b/forum/skins/default/templates/users/preferences.html new file mode 100644 index 0000000..f9393ac --- /dev/null +++ b/forum/skins/default/templates/users/preferences.html @@ -0,0 +1,29 @@ +{% extends "user.html" %} +{% load i18n %} +{% load extra_tags %} + +{% block usercontent %} +

{% trans "Preferences" %}

+
+
+

+ {% trans "Here you can set some personal preferences." %} +

+ {{ form.errors }} + + + + + + + + +
+ {% trans "Navigation:" %} +
{{ form.sticky_sorts }}{% trans "Allways remember the sort order I apply to the lists I view" %}
+
+ +
+
+
+{% endblock %} \ No newline at end of file diff --git a/forum/urls.py b/forum/urls.py index 5f3fbc5..4598ddc 100644 --- a/forum/urls.py +++ b/forum/urls.py @@ -124,6 +124,8 @@ urlpatterns += patterns('', app.users.user_powers, name='user_powers'), url(r'^%s(?P\d+)/(?P.+)/%s$' % (_('users/'), _('subscriptions/')), app.users.user_subscriptions, name='user_subscriptions'), + url(r'^%s(?P\d+)/(?P.+)/%s$' % (_('users/'), _('preferences/')), app.users.user_preferences, + name='user_preferences'), url(r'^%s(?P\d+)/(?P.+)/%s$' % (_('users/'), _('favorites/')), app.users.user_favorites, name='user_favorites'), url(r'^%s(?P\d+)/(?P.+)/%s$' % (_('users/'), _('reputation/')), diff --git a/forum/utils/pagination.py b/forum/utils/pagination.py index 641c549..f955e60 100644 --- a/forum/utils/pagination.py +++ b/forum/utils/pagination.py @@ -35,7 +35,7 @@ class PaginatorContext(object): base_path = None - def __init__(self, id, sort_methods=None, default_sort=None, force_sort = None, sticky_sort=False, + def __init__(self, id, sort_methods=None, default_sort=None, force_sort = None, pagesizes=None, default_pagesize=None, prefix=''): self.id = id if sort_methods: @@ -62,15 +62,30 @@ class PaginatorContext(object): self.has_pagesize = False self.force_sort = force_sort - self.sticky_sort = sticky_sort self.prefix = prefix - def session_preferences(self, request): - return request.session.get('paginator_%s%s' % (self.prefix, self.id), {}) + def preferences(self, request): + if request.user.is_authenticated(): + if request.user.prop.pagination: + preferences = request.user.prop.pagination.get(self.id, {}) + else: + preferences = {} + else: + preferences = request.session.get('paginator_%s%s' % (self.prefix, self.id), {}) + + return preferences + + def set_preferences(self, request, preferences): + if request.user.is_authenticated(): + all_preferences = request.user.prop.pagination or {} + all_preferences[self.id] = preferences + request.user.prop.pagination = all_preferences + else: + request.session['paginator_%s%s' % (self.prefix, self.id)] = preferences def pagesize(self, request, session_prefs=None): if not session_prefs: - session_prefs = self.session_preferences(request) + session_prefs = self.preferences(request) if self.has_pagesize: @@ -105,16 +120,19 @@ class PaginatorContext(object): def sort(self, request, session_prefs=None): if not session_prefs: - session_prefs = self.session_preferences(request) + session_prefs = self.preferences(request) sort = None + sticky = request.user.is_authenticated() and request.user.prop.preferences and request.user.prop.preferences.get('sticky_sorts', False) + if self.has_sort: if request.GET.get(self.SORT, None): sort = request.GET[self.SORT] - if self.sticky_sort or session_prefs.get('sticky_sort', False): + + if sticky: session_prefs[self.SORT] = sort else: - sort = self.force_sort or session_prefs.get(self.SORT, self.default_sort) + sort = self.force_sort or (sticky and session_prefs.get(self.SORT, None)) or self.default_sort if not sort in self.sort_methods: sort = self.default_sort @@ -155,7 +173,7 @@ def paginated(request, paginators, tpl_context): return tpl_context def _paginated(request, objects, context): - session_prefs = context.session_preferences(request) + session_prefs = context.preferences(request) pagesize = context.pagesize(request, session_prefs) page = context.page(request) @@ -278,6 +296,6 @@ def _paginated(request, objects, context): else: paginator.sort_tabs = '' - request.session['paginator_%s' % context.id] = session_prefs + context.set_preferences(request, session_prefs) objects.paginator = paginator return objects \ No newline at end of file diff --git a/forum/views/readers.py b/forum/views/readers.py index 5748aa8..0d282b8 100644 --- a/forum/views/readers.py +++ b/forum/views/readers.py @@ -46,7 +46,7 @@ class AnswerPaginatorContext(pagination.PaginatorContext): (_('oldest'), pagination.SimpleSort(_('oldest answers'), ('-marked', 'added_at'), _("oldest answers will be shown first"))), (_('newest'), pagination.SimpleSort(_('newest answers'), ('-marked', '-added_at'), _("newest answers will be shown first"))), (_('votes'), pagination.SimpleSort(_('popular answers'), ('-marked', '-score', 'added_at'), _("most voted answers will be shown first"))), - ), default_sort=_('votes'), sticky_sort = True, pagesizes=(5, 10, 20), default_pagesize=default_pagesize, prefix=prefix) + ), default_sort=_('votes'), pagesizes=(5, 10, 20), default_pagesize=default_pagesize, prefix=prefix) class TagPaginatorContext(pagination.PaginatorContext): def __init__(self): @@ -66,11 +66,14 @@ def feed(request): @decorators.render('index.html') def index(request): + paginator_context = QuestionListPaginatorContext() + paginator_context.base_path = reverse('questions') return question_list(request, Question.objects.all(), sort=request.utils.set_sort_method('active'), base_path=reverse('questions'), - feed_url=reverse('latest_questions_feed')) + feed_url=reverse('latest_questions_feed'), + paginator_context=paginator_context) @decorators.render('questions.html', 'unanswered', _('unanswered'), weight=400) def unanswered(request): diff --git a/forum/views/users.py b/forum/views/users.py index 8bea106..7cb3224 100644 --- a/forum/views/users.py +++ b/forum/views/users.py @@ -46,7 +46,7 @@ class UserAnswersPaginatorContext(pagination.PaginatorContext): (_('oldest'), pagination.SimpleSort(_('oldest answers'), 'added_at', _("oldest answers will be shown first"))), (_('newest'), pagination.SimpleSort(_('newest answers'), '-added_at', _("newest answers will be shown first"))), (_('votes'), pagination.SimpleSort(_('popular answers'), '-score', _("most voted answers will be shown first"))), - ), default_sort=_('votes'), sticky_sort = True, pagesizes=(5, 10, 20), default_pagesize=20, prefix=_('answers')) + ), default_sort=_('votes'), pagesizes=(5, 10, 20), default_pagesize=20, prefix=_('answers')) USERS_PAGE_SIZE = 35# refactor - move to some constants file @@ -55,7 +55,7 @@ def users(request): suser = request.REQUEST.get('q', "") users = User.objects.all() - if suser == "": + if suser != "": users = users.filter(username__icontains=suser) return pagination.paginated(request, ('users', UserListPaginatorContext()), { @@ -321,6 +321,25 @@ def user_subscriptions(request, user): return {'view_user':user, 'notificatons_on': enabled, 'form':form} +@user_view('users/preferences.html', 'preferences', _('preferences'), _('preferences'), True, tabbed=False) +def user_preferences(request, user): + if request.POST: + form = UserPreferencesForm(request.POST) + + if form.is_valid(): + user.prop.preferences = form.cleaned_data + request.user.message_set.create(message=_('New preferences saved')) + + else: + preferences = user.prop.preferences + + if preferences: + form = UserPreferencesForm(initial=preferences) + else: + form = UserPreferencesForm() + + return {'view_user': user, 'form': form} + @login_required def account_settings(request): logging.debug('') -- 2.39.5