From c5a44b521650dd35c9092308ab30f29c5e3a8f43 Mon Sep 17 00:00:00 2001 From: Evgeny Fadeev Date: Sat, 10 Apr 2010 10:50:02 -0400 Subject: intermediate broken commit --- forum/const.py | 2 +- forum/forms.py | 3 + forum/middleware/view_log.py | 26 ++-- forum/models/__init__.py | 3 + forum/models/question.py | 11 +- forum/search/indexer.py | 9 ++ forum/search/state_manager.py | 28 +++-- forum/skins/default/media/style/style.css | 76 ++++++++++-- forum/skins/default/templates/base.html | 15 ++- forum/skins/default/templates/book.html | 2 +- forum/skins/default/templates/header.html | 107 ++++++++++------- forum/skins/default/templates/index.html | 5 +- forum/skins/default/templates/index_.html | 5 +- forum/skins/default/templates/question.html | 13 +- forum/skins/default/templates/question_list.html | 2 +- .../templates/question_summary_list_roll.html | 2 +- forum/skins/default/templates/questions.html | 131 +++++++++++++-------- forum/skins/default/templates/tag_selector.html | 9 +- forum/skins/default/templates/tags.html | 3 +- forum/skins/default/templates/user_stats.html | 2 +- forum/skins/default/templates/users_questions.html | 2 +- forum/templatetags/extra_tags.py | 81 ++++++++++++- forum/utils/decorators.py | 1 - forum/views/readers.py | 32 ++--- forum/views/users.py | 11 +- forum/views/writers.py | 10 +- settings.py | 1 + 27 files changed, 416 insertions(+), 176 deletions(-) create mode 100644 forum/search/indexer.py diff --git a/forum/const.py b/forum/const.py index 6f6086f0..dd85bb2e 100755 --- a/forum/const.py +++ b/forum/const.py @@ -58,7 +58,7 @@ DEFAULT_QUESTIONS_PAGE_SIZE = 30 PAGE_SIZES = (10,30,50) UNANSWERED_MEANING_LIST = ('NO_ANSWERS','NO_UPVOTED_ANSWERS','NO_ACCEPTED_ANSWERS') -UNANSWERED_MEANING = 'NO_ANSWERS' +UNANSWERED_MEANING = 'NO_ACCEPTED_ANSWERS' assert(UNANSWERED_MEANING in UNANSWERED_MEANING_LIST) #todo: diff --git a/forum/forms.py b/forum/forms.py index c32ce6c0..2c2df738 100755 --- a/forum/forms.py +++ b/forum/forms.py @@ -136,6 +136,7 @@ class AdvancedSearchForm(forms.Form): reset_tags = forms.BooleanField(required=False) reset_author = forms.BooleanField(required=False) reset_query = forms.BooleanField(required=False) + start_over = forms.BooleanField(required=False) tags = forms.CharField(max_length=256,required=False) author = forms.IntegerField(required=False) page_size = forms.ChoiceField(choices=const.PAGE_SIZES, required=False) @@ -188,6 +189,8 @@ class AdvancedSearchForm(forms.Form): del self.cleaned_data['reset_author'] if self.cleaned_data['reset_query'] == False: del self.cleaned_data['reset_query'] + if self.cleaned_data['start_over'] == False: + del self.cleaned_data['start_over'] if self.cleaned_data['author'] is None: del self.cleaned_data['author'] if self.cleaned_data['page'] is None: diff --git a/forum/middleware/view_log.py b/forum/middleware/view_log.py index 6f59568a..213292fe 100644 --- a/forum/middleware/view_log.py +++ b/forum/middleware/view_log.py @@ -1,8 +1,16 @@ import logging from django.conf import settings from forum.views.readers import questions as questions_view -from forum.views.commands import vote as vote_view -from django.views.static import serve as django_serve_view +from forum.views.commands import vote +from django.views.static import serve +from forum.views.writers import delete_comment, question_comments, answer_comments +from forum.views.readers import question, question_revisions, answer_revisions + +#todo: the list is getting bigger and bigger - maybe there is a better way to +#trigger reset of sarch state? +IGNORED_VIEWS = (serve, vote, delete_comment, + question_comments, answer_comments, + question, question_revisions, answer_revisions) class ViewLog(object): """must be modified only in this middlware @@ -36,17 +44,21 @@ class ViewLogMiddleware(object): def process_view(self, request, view_func, view_args, view_kwargs): if view_func == questions_view: view_str = 'questions' - elif view_func in (django_serve_view, vote_view): + elif view_func in IGNORED_VIEWS: return - elif settings.DEBUG == True: + else: + view_str = view_func.__name__ + if view_str == 'wrap': + print str(view_func.__module__)# == 'forum.utils.decorators': + return + + if settings.DEBUG == True: #todo: dependency! - from debug_toolbar.views import debug_media_view + from debug_toolbar.views import debug_media as debug_media_view if view_func == debug_media_view: return else: view_str = view_func.__name__ - else: - view_str = view_func.__name__ if request.user.is_authenticated(): user_name = request.user.username diff --git a/forum/models/__init__.py b/forum/models/__init__.py index 2349c9e3..191f66d3 100755 --- a/forum/models/__init__.py +++ b/forum/models/__init__.py @@ -5,6 +5,8 @@ from meta import Vote, Comment, FlaggedItem from user import Activity, ValidationHash, EmailFeedSetting, AuthKeyUserAssociation from repute import Badge, Award, Repute from django.core.urlresolvers import reverse +from forum.search.indexer import create_fulltext_indexes +from django.db.models.signals import post_syncdb import re from base import * @@ -440,6 +442,7 @@ tags_updated.connect(record_update_tags, sender=Question) post_save.connect(record_favorite_question, sender=FavoriteQuestion) user_updated.connect(record_user_full_updated, sender=User) user_logged_in.connect(post_stored_anonymous_content) +post_syncdb.connect(create_fulltext_indexes) Question = Question QuestionRevision = QuestionRevision diff --git a/forum/models/question.py b/forum/models/question.py index 98b50490..aae99da2 100755 --- a/forum/models/question.py +++ b/forum/models/question.py @@ -10,6 +10,7 @@ import datetime from django.conf import settings from django.utils.datastructures import SortedDict from forum.models.tag import MarkedTag +from django.db.models import Q markdowner = Markdown(html4tags=True) @@ -77,7 +78,8 @@ class QuestionManager(models.Manager): #return metadata meta_data = {} if tag_selector: - qs = qs.filter(tags__name__in = tag_selector) + for tag in tag_selector: + qs = qs.filter(tags__name = tag) if search_query: qs = qs.filter(deleted=False).extra( @@ -101,9 +103,9 @@ class QuestionManager(models.Manager): #user contributed questions & answers if author_selector: try: - u = User.objects.get(username=author_selector) - qs = qs.filter(Q(author=u) | Q(answers__author=u)) - meta_data['author_name'] = author_selector + u = User.objects.get(id=int(author_selector)) + qs = qs.filter(Q(author=u, deleted=False) | Q(answers__author=u, answers__deleted=False)) + meta_data['author_name'] = u.username except User.DoesNotExist: meta_data['author_name'] = None @@ -155,6 +157,7 @@ class QuestionManager(models.Manager): if orderby: #relevance will be ignored here qs = qs.order_by(orderby) + qs = qs.distinct() return qs, meta_data def update_tags(self, question, tagnames, user): diff --git a/forum/search/indexer.py b/forum/search/indexer.py new file mode 100644 index 00000000..c7c45c59 --- /dev/null +++ b/forum/search/indexer.py @@ -0,0 +1,9 @@ +from django.conf import settings +from django.db import connection + +def create_fulltext_indexes(): + if settings.DATABASE_ENGINE == 'mysql': + cursor = connection.cursor() + cursor.execute('ALTER TABLE question ADD FULLTEXT (title, text, tagnames)') + cursor.execute('ALTER TABLE answer ADD FULLTEXT (title, text, tagnames)') + diff --git a/forum/search/state_manager.py b/forum/search/state_manager.py index b36c5e53..4b3772b6 100644 --- a/forum/search/state_manager.py +++ b/forum/search/state_manager.py @@ -51,12 +51,13 @@ class SearchState(object): setattr(self, key, new_value) self.reset_page() - def update_from_user_input(self,input): + def update_from_user_input(self,input, raw_input = {}): #todo: this function will probably not #fit the case of multiple parameters entered at the same tiem - print ','.join(input.keys()) + if 'start_over' in input: + self.reset() + if 'page' in input: - print input['page'] self.page = input['page'] #special case - on page flip no other input is accepted return @@ -76,7 +77,10 @@ class SearchState(object): if 'tags' in input: if self.tags: old_tags = self.tags.copy() - self.tags.union(input['tags']) + print 'old tags %s' % str(old_tags) + print 'new tags %s' % str(input['tags']) + self.tags = self.tags.union(input['tags']) + print 'combined %s' % str(self.tags) if self.tags != old_tags: self.reset_page() else: @@ -97,11 +101,7 @@ class SearchState(object): return if 'reset_query' in input: - if self.query: - self.query = None - self.reset_page() - if self.sort == 'relevant': - self.reset_sort() + self.reset_query() return self.update_value('author',input) @@ -109,6 +109,9 @@ class SearchState(object): if 'query' in input: self.update_value('query',input) self.sort = 'relevant' + elif 'search' in raw_input:#a case of use nulling search query by hand + self.reset_query() + return if 'sort' in input: @@ -120,6 +123,13 @@ class SearchState(object): def reset_page(self): self.page = 1 + def reset_query(self): + if self.query: + self.query = None + self.reset_page() + if self.sort == 'relevant': + self.reset_sort() + def reset_sort(self): self.sort = const.DEFAULT_POST_SORT_METHOD diff --git a/forum/skins/default/media/style/style.css b/forum/skins/default/media/style/style.css index 8315839d..81c6965e 100755 --- a/forum/skins/default/media/style/style.css +++ b/forum/skins/default/media/style/style.css @@ -204,7 +204,6 @@ blockquote { background-color: #F5F5F5; } -/*页面布局*/ #wrapper { width: 960px; margin: auto; @@ -340,28 +339,56 @@ blockquote { padding-right: 0px; } -/*搜索栏*/ #searchBar { width: 958px; background-color: #888a85; /*#e9b96e;*/ border: 1px solid #aaaaaa; - padding: 4px 0 0 0; + padding: 4px 0 5px 5px; } - -/* #B02B2C */ -#searchBar .content { +#fakeSearchBar { + width: 958px; + height: 4px; + background-color: #888a85; /*#e9b96e;*/ + border: 1px solid #aaaaaa; } #searchBar .searchInput { - font-size: 13px; - height: 18px; - width: 400px; + font-size: 24px; + line-height: 24px; + height: 36px; + width: 620px; + margin: 0px; + padding: 5px 0 0 5px; +} + +#searchBar .searchInputCancelable { + font-size: 24px; + line-height: 24px; + height: 36px; + width: 570px; + padding: 5px 0 0 5px; + margin: 0px; } #searchBar .searchBtn { - font-size: 14px; - height: 26px; - width: 80px; + font-size: 20px; + color: #666666; + height: 40px; + line-height: 22px; + text-align: center; + margin-top:1px; + padding-bottom: 4px; +} + +#searchBar .cancelSearchBtn { + font-size: 20px; + color: #666666; + height: 40px; + width: 40px; + line-height: 22px; + padding-bottom: 4px; + margin-top:1px; + text-align: center; } #searchBar .options { @@ -552,6 +579,10 @@ blockquote { font-weight: 800; } +.evenMore a { + text-decoration: underline; +} + .questions-count { font-size: 32px; font-family: sans-serif; @@ -1503,6 +1534,10 @@ span.form-error { width: 100%; } +#id_title { + width: 100%; +} + .wmd-preview { margin-top: 10px; padding: 6px; @@ -2539,3 +2574,20 @@ p.signup_p { color:red; padding:5px; } + +.search-result-summary { + font-weight: bold; + font-size:18px; + line-height:30px; + margin:0px 0px 0px 5px; + padding:0px; +} +.search-tips { + font-size:12px; + line-height:12px; + margin:0 0 5px 5px; + padding:0px; +} +.search-tips a { + text-decoration: underline; +} diff --git a/forum/skins/default/templates/base.html b/forum/skins/default/templates/base.html index 1018da50..fe5a95a3 100644 --- a/forum/skins/default/templates/base.html +++ b/forum/skins/default/templates/base.html @@ -2,6 +2,7 @@ {% load extra_filters %} {% load extra_tags %} +{% load smart_if %} {% load i18n %} @@ -36,7 +37,19 @@ }); {% endif %} - + {% if active_tab != "tags" and active_tab != "users" %} + + {% endif %} {% block forejs %} {% endblock %} diff --git a/forum/skins/default/templates/book.html b/forum/skins/default/templates/book.html index 8574fa73..528b800d 100644 --- a/forum/skins/default/templates/book.html +++ b/forum/skins/default/templates/book.html @@ -122,7 +122,7 @@
{% for tag in question.tagname_list %} - + {% endfor %}
diff --git a/forum/skins/default/templates/header.html b/forum/skins/default/templates/header.html index aaf19874..efc0d8f2 100644 --- a/forum/skins/default/templates/header.html +++ b/forum/skins/default/templates/header.html @@ -1,5 +1,6 @@ {% load extra_tags %} +{% load smart_if %} {% load i18n %}
- - + + {% endcomment %} + +
- - - + + +
+ {% if active_tab != "ask" %} + {% else %} +
+ {% endif %}
diff --git a/forum/skins/default/templates/index.html b/forum/skins/default/templates/index.html index 8a885dd4..b90d788a 100644 --- a/forum/skins/default/templates/index.html +++ b/forum/skins/default/templates/index.html @@ -57,11 +57,12 @@ {% cache 60 recent_tags %} {% for tag in tags %} + title="{% blocktrans with tag.name as tagname %}see questions tagged '{{tagname}}'{% endblocktrans %}" + href="{% url questions %}?tags={{tag.name|urlencode}}">{{ tag.name }} {% endfor %} {% endcache %} -
{% trans "popular tags" %}
+
{% trans "see all tags" %}
{% if awards %} diff --git a/forum/skins/default/templates/index_.html b/forum/skins/default/templates/index_.html index 5e4cf533..8ba169a7 100644 --- a/forum/skins/default/templates/index_.html +++ b/forum/skins/default/templates/index_.html @@ -60,7 +60,7 @@
{% for tag in question.tagname_list %} - + {% endfor %}
@@ -87,7 +87,8 @@
{% for tag in tags %} + title="{% blocktrans with tag.name as tagname %}see questions tagged '{{tagname}}'{% endblocktrans %}" + href="{% url questions %}?tags={{tag.name|urlencode}}">{{ tag.name }} {% endfor %}
{% trans "popular tags" %} »
diff --git a/forum/skins/default/templates/question.html b/forum/skins/default/templates/question.html index 1c542c8b..c3564a34 100644 --- a/forum/skins/default/templates/question.html +++ b/forum/skins/default/templates/question.html @@ -128,10 +128,12 @@ {{ question.html|safe }}
+ {% comment %}todo: here we have important case to reset search state{% endcomment %}
{% for tag in question.tagname_list %} - + {% endfor %}
{% joinitems using '|' %} @@ -474,9 +476,10 @@

{% for tag in tags %} - ×{{ tag.used_count|intcomma }}
+ + ×{{ tag.used_count|intcomma }}
{% endfor %}

diff --git a/forum/skins/default/templates/question_list.html b/forum/skins/default/templates/question_list.html index 53633691..38ac254a 100644 --- a/forum/skins/default/templates/question_list.html +++ b/forum/skins/default/templates/question_list.html @@ -16,7 +16,7 @@

{% for tag in question.tagname_list %} - + {% endfor %}
diff --git a/forum/skins/default/templates/question_summary_list_roll.html b/forum/skins/default/templates/question_summary_list_roll.html index 57685d6d..f2432a24 100644 --- a/forum/skins/default/templates/question_summary_list_roll.html +++ b/forum/skins/default/templates/question_summary_list_roll.html @@ -49,7 +49,7 @@
{% for tag in question.tagname_list %} - + {% endfor %}
diff --git a/forum/skins/default/templates/questions.html b/forum/skins/default/templates/questions.html index 0a7c0c96..03ccc324 100644 --- a/forum/skins/default/templates/questions.html +++ b/forum/skins/default/templates/questions.html @@ -48,7 +48,7 @@
{% endcomment %}
- {% trans "Pick:" %} + {% trans "In:" %} {% trans "all" %} {% trans "unanswered" %} {% if request.user.is_authenticated %} @@ -134,20 +134,90 @@ {% endif %}
+{% if questions_count > 0 %} +
+

+ {% if author_name or search_tags or query %} + {% blocktrans count questions_count as cnt with questions_count|intcomma as q_num %} One question found{% plural %}{{q_num}} questions found{% endblocktrans %} + {% else %} + {% blocktrans count questions_count as cnt with questions_count|intcomma as q_num %} {{q_num}} question{% plural %}{{q_num}} questions{% endblocktrans %} + {% endif %} + {% joinitems using ', ' %} + {% if author_name %} + {% blocktrans %}with {{author_name}}'s contributions{% endblocktrans %} + {% endif %} + {% separator %} + {% if search_tags %} + {% trans "tagged" %} + "{{ search_tags|join:"\", \"" }}" + {% endif %} + {% endjoinitems %} +

+ {% if author_name or search_tags or query %} +

{% trans "Search tips:" %} + {% ifmany query search_tags author_name %} + {% joinitems using ', ' ' or ' %} + {% if author_name %} + {% trans "reset author" %} + {% endif %} + {% separator %} + {% if search_tags %} + {% trans "reset tags" %} + {% endif %} + {% separator %} + {% ifmany query search_tags author_name %} + {% trans "start over" %} + {% endifmany %} + {% endjoinitems %} + {% else %} + {% trans "start over" %} + {% endifmany %} + {% trans " - to expand, or dig in by adding more tags and revising the query." %} +

+ {% else %} +

{% trans "Search tip:" %} {% trans "add tags and a query to focus your search" %}

+ {% endif %} + +
+{% endif %}
{% include "question_list.html" %} + {% comment %}todo: fix css here{% endcomment %} {% if questions_count == 0 %} + {% comment %}todo: add tips to widen selection{% endcomment%}

{% if scope == "unanswered" %} - {% trans "There are no unanswered questions in this selection" %} + {% trans "There are no unanswered questions here" %} {% endif %} {% if scope == "favorite" %} {% trans "No favorite questions here. " %} - {% trans "Please bookmark some questions with a star and find them here later." %} + {% trans "Please start (bookmark) some questions when you visit them" %} {% endif %} - {% if scope == "all" %} - {% trans "Did not find anything? Please feel free to ask your question!" %} +

+ {% if query or search_tags or author_name %} +

+ {% trans "You can expand your search by " %} + {% ifmany query search_tags author_name %} + {% joinitems using ', ' ' or ' %} + {% if author_name %} + {% trans "resetting author" %} + {% endif %} + {% separator %} + {% if search_tags %} + {% trans "resetting tags" %} + {% endif %} + {% separator %} + {% ifmany query search_tags author_name %} + {% trans "starting over" %} + {% endifmany %} + {% endjoinitems %} + {% else %} + {% trans "starting over" %} + {% endifmany %} +

{% endif %} +

+ {% trans "Please always feel free to ask your question!" %}

{% else %}

@@ -158,51 +228,14 @@

{% endblock %} -{% block tail %} -
{% cnprog_paginator context %}
-
{% cnprog_pagesize context %}
-{% endblock %} + {% block tail %} + {% if questions_count > 10 %}{%comment%}todo: remove magic number{%endcomment%} +
{% cnprog_paginator context %}
+
{% cnprog_pagesize context %}
+ {% endif %} + {% endblock %} {% block sidebar %} -
- {% if searchtag %} - {% blocktrans count questions_count as cnt with questions_count|intcomma as q_num and searchtag as tagname %}have total {{q_num}} questions tagged {{tagname}}{% plural %}have total {{q_num}} questions tagged {{tagname}}{% endblocktrans %} - {% else %} - {% if searchtitle %} - {% if settings.USE_SPHINX_SEARCH %} - {% blocktrans count questions_count as cnt with questions_count|intcomma as q_num %} have total {{q_num}} questions containing {{searchtitle}} in full text {% plural %} have total {{q_num}} questions containing {{searchtitle}} in full text {% endblocktrans %} - {% else %} - {% blocktrans count questions_count as cnt with questions_count|intcomma as q_num %} have total {{q_num}} questions containing {{searchtitle}} {% plural %} have total {{q_num}} questions containing {{searchtitle}} {% endblocktrans %} - {% endif %} - {% else %} - {% if is_unanswered %} - {% blocktrans count questions_count as cnt with questions_count|intcomma as q_num %} have total {{q_num}} unanswered questions {% plural %} have total {{q_num}} unanswered questions {% endblocktrans %} - {% else %} - {% blocktrans count questions_count as cnt with questions_count|intcomma as q_num %} have total {{q_num}} questions {% plural %} have total {{q_num}} questions {% endblocktrans %} - {% endif %} - {% endif %} - {% endif %} -

- {% ifequal tab_id "latest" %} - {% trans "latest questions info" %} - {% endifequal %} - - {% ifequal tab_id "active" %} - {% trans "Questions are sorted by the time of last update." %} - {% trans "Most recently answered ones are shown first." %} - {% endifequal %} - - {% ifequal tab_id "hottest" %} - {% trans "Questions sorted by number of responses." %} - {% trans "Most answered questions are shown first." %} - {% endifequal %} - - {% ifequal tab_id "mostvoted" %} - {% trans "Questions are sorted by the number of votes." %} - {% trans "Most voted questions are shown first." %} - {% endifequal %} -

-
{% if request.user.is_authenticated %} {% include "tag_selector.html" %} {% endif %} @@ -210,7 +243,7 @@

{% trans "Related tags" %}

{% for tag in tags %} - + × {{ tag.used_count|intcomma }}
{% endfor %} diff --git a/forum/skins/default/templates/tag_selector.html b/forum/skins/default/templates/tag_selector.html index 5e3e2ad8..85b858d2 100644 --- a/forum/skins/default/templates/tag_selector.html +++ b/forum/skins/default/templates/tag_selector.html @@ -1,5 +1,6 @@ {% load i18n %} {% load extra_tags %} +{% comment %}todo - maybe disable navigation from ignored tags here when "hide" is on - with js?{%endcomment%}

{% trans "Interesting tags" %}

@@ -7,8 +8,8 @@ {% spaceless %} + title="{% blocktrans %}see questions tagged '{{ tag_name }}'{% endblocktrans %}" + href="{% url questions %}?tags={{tag_name|urlencode}}">{{tag_name}} @@ -24,8 +25,8 @@ {% spaceless %} + title="{% blocktrans %}see questions tagged '{{ tag_name }}'{% endblocktrans %}" + href="{% url questions %}?tags={{tag_name|urlencode}}">{{tag_name}} diff --git a/forum/skins/default/templates/tags.html b/forum/skins/default/templates/tags.html index 50f90fb1..2bc01070 100644 --- a/forum/skins/default/templates/tags.html +++ b/forum/skins/default/templates/tags.html @@ -46,7 +46,8 @@
    {% for tag in tags.object_list %}
  • -   × {{ tag.used_count|intcomma }} diff --git a/forum/skins/default/templates/user_stats.html b/forum/skins/default/templates/user_stats.html index 1f462581..482b1228 100644 --- a/forum/skins/default/templates/user_stats.html +++ b/forum/skins/default/templates/user_stats.html @@ -98,7 +98,7 @@ {% for tag in user_tags%} + href="{% url questions %}?tags={{tag|urlencode}}&author={{view_user.id}}&start_over=true">{{tag.name}} × {{ tag.user_tag_usage_count|intcomma }}
    {% if forloop.counter|divisibleby:"10" %} diff --git a/forum/skins/default/templates/users_questions.html b/forum/skins/default/templates/users_questions.html index be6aaf7d..99a7f90c 100644 --- a/forum/skins/default/templates/users_questions.html +++ b/forum/skins/default/templates/users_questions.html @@ -31,7 +31,7 @@ {% convert2tagname_list question %} {% for tag in question.tagnames %} - + {% endfor %}
diff --git a/forum/templatetags/extra_tags.py b/forum/templatetags/extra_tags.py index 382d19f0..a10c473b 100755 --- a/forum/templatetags/extra_tags.py +++ b/forum/templatetags/extra_tags.py @@ -304,8 +304,12 @@ class ItemSeparatorNode(template.Node): return self.content class JoinItemListNode(template.Node): - def __init__(self,separator=ItemSeparatorNode("''"), items=()): + def __init__(self,separator=ItemSeparatorNode("''"), last_separator=None, items=()): self.separator = separator + if last_separator: + self.last_separator = last_separator + else: + self.last_separator = separator self.items = items def render(self,context): out = [] @@ -314,16 +318,34 @@ class JoinItemListNode(template.Node): bit = item.render(context) if not empty_re.search(bit): out.append(bit) - return self.separator.render(context).join(out) + if len(out) == 1: + return out[0] + if len(out) > 1: + last = out.pop() + all_but_last = self.separator.render(context).join(out) + return self.last_separator.render(context).join((all_but_last,last)) + else: + assert(len(out)==0) + return '' @register.tag(name="joinitems") def joinitems(parser,token): try: - tagname,junk,sep_token = token.split_contents() - except ValueError: - raise template.TemplateSyntaxError("joinitems tag requires 'using \"separator html\"' parameters") + tagname, junk, sep_token = token.split_contents() + last_sep_token = None + except: + try: + tagname, junk, sep_token, last_sep_token = token.split_contents() + except: + raise template.TemplateSyntaxError('incorrect usage of joinitems tag first param ' + 'must be \'using\' second - separator and ' + 'optional third - last item separator') if junk == 'using': sep_node = ItemSeparatorNode(sep_token) + if last_sep_token: + last_sep_node = ItemSeparatorNode(last_sep_token) + else: + last_sep_node = None else: raise template.TemplateSyntaxError("joinitems tag requires 'using \"separator html\"' parameters") nodelist = [] @@ -333,7 +355,7 @@ def joinitems(parser,token): if next.contents == 'endjoinitems': break - return JoinItemListNode(separator=sep_node,items=nodelist) + return JoinItemListNode(separator=sep_node,last_separator=last_sep_node,items=nodelist) class BlockMediaUrlNode(template.Node): def __init__(self,nodelist): @@ -436,3 +458,50 @@ def question_counter_widget(question): #returns a dictionary with keys like 'votes_bg', etc return locals() +class IsManyNode(template.Node): + def __init__(self, test_items, true_nodelist, false_nodelist): + self.true_nodelist = true_nodelist + self.false_nodelist = false_nodelist + self.test_items = test_items + def render(self, context): + maybe = False + for item in self.test_items: + is_good = item.resolve(context) + print item, is_good + if maybe == True and is_good: + print 'have many!' + return self.true_nodelist.render(context) + if is_good: + maybe = True + print 'have one item' + return self.false_nodelist.render(context) + +@register.tag(name='ifmany') +def ifmany(parser,token): + """usage {% ifmany item1 item2 item3 ... itemN %} stuff {% endifmany %} + returns content included into the tag if more than one + item evaluates to Tru'ish value - that's the idea + {% else %} is not supported yet + """ + + bits = list(token.split_contents()) + start_tag = bits.pop(0) + + test_items = [] + for bit in bits: + item = parser.compile_filter(bit) + test_items.append(item) + + end_tag = 'end' + start_tag + else_tag = 'else' + true_nodelist = parser.parse((end_tag,else_tag,)) + token = parser.next_token() + if token.contents == else_tag: + print 'have else clause' + false_nodelist = parser.parse((end_tag,)) + token = parser.next_token() + else: + false_nodelist = template.NodeList() + + + return IsManyNode(test_items, true_nodelist, false_nodelist) diff --git a/forum/utils/decorators.py b/forum/utils/decorators.py index e4e7acb3..440e8312 100755 --- a/forum/utils/decorators.py +++ b/forum/utils/decorators.py @@ -22,4 +22,3 @@ def ajax_method(view_func): json = simplejson.dumps(retval) return HttpResponse(json,mimetype='application/json') return wrap - diff --git a/forum/views/readers.py b/forum/views/readers.py index 9e9662dd..01dfc035 100644 --- a/forum/views/readers.py +++ b/forum/views/readers.py @@ -90,18 +90,15 @@ def questions(request):#a view generating listing of questions, used by 'unanswe if request.user.is_authenticated(): search_state.set_logged_in() - print 'before: ', search_state - form = AdvancedSearchForm(request.GET) if form.is_valid(): - print 'form is valid' - search_state.update_from_user_input(form.cleaned_data) + search_state.update_from_user_input(form.cleaned_data, request.GET) request.session['search_state'] = search_state request.session.modified = True - print 'after: ', search_state - - print 'going into the search' + #force reset for debugging + #search_state.reset() + #request.session.modified = True #have this call implemented for sphinx, mysql and pgsql (qs, meta_data) = Question.objects.run_advanced_search( @@ -113,10 +110,6 @@ def questions(request):#a view generating listing of questions, used by 'unanswe sort_method = search_state.sort ) - print 'got out of the search' - - logging.debug('search state is %s' % search_state) - objects_list = Paginator(qs, search_state.page_size) questions = objects_list.page(search_state.page) @@ -128,17 +121,16 @@ def questions(request):#a view generating listing of questions, used by 'unanswe #todo!!!! #contributors = #User.objects.get_related_to_questions - print 'rendering template!!!' - print 'have %d' % objects_list.count - + #todo: organize variables by type return render_to_response('questions.html', { 'questions' : questions, 'author_name' : meta_data.get('author_name',None), 'tab_id' : search_state.sort, 'questions_count' : objects_list.count, 'tags' : related_tags, + 'query': search_state.query, + 'search_tags' : search_state.tags, 'tags_autocomplete' : tags_autocomplete, - 'searchtag' : search_state.tags, 'is_unanswered' : False,#remove this from template 'interesting_tag_names': meta_data.get('interesting_tag_names',None), 'ignored_tag_names': meta_data.get('ignored_tag_names',None), @@ -163,15 +155,16 @@ def search(request): #generates listing of questions matching a search query - i are useless under the search bar """ if request.method == "GET": - search_type == request.GET.get('t') + search_type = request.GET.get('t') + query = request.GET.get('query') try: page = int(request.GET.get('page', '1')) except ValueError: page = 1 if search_type == 'tag': - return HttpResponseRedirect(reverse('tags') + '?q=%s&page=%s' % (keywords.strip(), page)) - elif search_type == "user": - return HttpResponseRedirect(reverse('users') + '?q=%s&page=%s' % (keywords.strip(), page)) + return HttpResponseRedirect(reverse('tags') + '?q=%s&page=%s' % (query.strip(), page)) + elif search_type == 'user': + return HttpResponseRedirect(reverse('users') + '?q=%s&page=%s' % (query.strip(), page)) else: raise Http404 else: @@ -205,6 +198,7 @@ def tags(request):#view showing a listing of available tags - plain list tags = objects_list.page(objects_list.num_pages) return render_to_response('tags.html', { + "active_tab": "tags", "tags" : tags, "stag" : stag, "tab_id" : sortby, diff --git a/forum/views/users.py b/forum/views/users.py index 245a1f85..2356bf38 100755 --- a/forum/views/users.py +++ b/forum/views/users.py @@ -63,11 +63,12 @@ def users(request): users = objects_list.page(objects_list.num_pages) return render_to_response('users.html', { - "users" : users, - "suser" : suser, - "keywords" : suser, - "tab_id" : sortby, - "context" : { + 'active_tab': 'users', + 'users' : users, + 'suser' : suser, + 'keywords' : suser, + 'tab_id' : sortby, + 'context' : { 'is_paginated' : is_paginated, 'pages': objects_list.num_pages, 'page': page, diff --git a/forum/views/writers.py b/forum/views/writers.py index b9b1aad5..57c8e043 100755 --- a/forum/views/writers.py +++ b/forum/views/writers.py @@ -132,9 +132,18 @@ def ask(request):#view used to ask a new question return HttpResponseRedirect(reverse('user_signin_new_question')) else: form = AskForm() + if 'title' in request.GET: + raw_title = request.GET['title'] + form.initial['title'] = strip_tags(strip_entities(raw_title)) + else: + search_state = request.session.get('search_state',None) + if search_state: + query = search_state.query + form.initial['title'] = query tags = _get_tags_cache_json() return render_to_response('ask.html', { + 'active_tab': 'ask', 'form' : form, 'tags' : tags, 'email_validation_faq_url':reverse('faq') + '#validate', @@ -318,7 +327,6 @@ def __generate_comments_json(obj, type, user):#non-view generates json data for data = simplejson.dumps(json_comments) return HttpResponse(data, mimetype="application/json") - def question_comments(request, id):#ajax handler for loading comments to question question = get_object_or_404(Question, id=id) user = request.user diff --git a/settings.py b/settings.py index 4d799a13..b80eb4f2 100644 --- a/settings.py +++ b/settings.py @@ -75,6 +75,7 @@ INSTALLED_APPS = ( 'django_authopenid', 'debug_toolbar' , #'stackexchange', #se loader + 'south', ) AUTHENTICATION_BACKENDS = ('django.contrib.auth.backends.ModelBackend',) -- cgit v1.2.3-1-g7c22