Skip to content

Commit

Permalink
Merge pull request #20 from nitely/future
Browse files Browse the repository at this point in the history
v0.1.2
  • Loading branch information
nitely committed Aug 1, 2014
2 parents 65a7311 + 2d8ab7d commit a47ed97
Show file tree
Hide file tree
Showing 202 changed files with 10,722 additions and 1,643 deletions.
3 changes: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,6 @@ htmlcov/
nosetests.xml
coverage.xml

# Translations
*.mo

# Mr Developer
.mr.developer.cfg
.project
Expand Down
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,13 @@ Visit (http://127.0.0.1:8000/)
## Updating

Soon.
Run:

pip install -r requirements.txt
python manage.py syncdb
python manage.py loaddata spirit_init
python manage.py collectstatic
python manage.py rebuild_index

## Contributing

Expand Down
9 changes: 5 additions & 4 deletions TODO
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
* Unsubscribe on notifications list
* Unread: mark all as read, unsubscribe
* NestedModelChoiceField for multiple choice (search), add *----* as initial
* NestedModelChoiceField for multiple choice (search)
* 'User has leave or has joined the conversation' comment on private topics, dont send notification.
* Ocultar quote anidado (ej: max tres niveles, y ocultar el tercero con js [...])
* Diff entre comentarios en historial (js)
* Agregar contadores (comments, topics) para categoria
* Agregar contadores (likes, topics, comments) para usuario
* Agregar opcion para ver topics privados abandonados (solo para creador)
* Panel de administracion: news letter,
* Email notificacion digest/resume (once a day or so),
add preference for sending on every notif, unsubscribe
add preference for sending on every notif, unsubscribe,
translate.activate the user lang before sending or send bulk in english (?)
* Test middlewares
* Test managers
* Tests views for login required
Expand All @@ -25,14 +25,15 @@
* User groups (permissions)
* >> add @username on reply
* >> allow mods to create topics on closed categories
* >> order profile topics by creation date


Template
* profile, add rank mod/admin
* admin: flag detail delete comment, detail add topic title
* admin: add nav to detail templates
* Notifications: show all/unread link
* Emojis popup selector
* local store comment publish/update


Readme
Expand Down
File renamed without changes.
41 changes: 41 additions & 0 deletions example/local_settings_sample_prod.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#-*- coding: utf-8 -*-

# MINIMAL CONFIGURATION FOR PRODUCTION ENV

DEBUG = False

TEMPLATE_DEBUG = False

# https://docs.djangoproject.com/en/dev/ref/settings/#admins
ADMINS = (('John', '[email protected]'), )

# Secret key generator: https://djskgen.herokuapp.com/
SECRET_KEY = ''

# https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts
ALLOWED_HOSTS = ['.example.com', ]

# https://docs.djangoproject.com/en/dev/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'mydatabase',
'USER': 'mydatabaseuser',
'PASSWORD': 'mypassword',
'HOST': '127.0.0.1',
'PORT': '5432',
}
}

# These are all the languages Spirit provides.
# https://www.transifex.com/projects/p/spirit/
gettext_noop = lambda s: s
LANGUAGES = (
('de', gettext_noop('German')),
('en', gettext_noop('English')),
('es', gettext_noop('Spanish')),
('sv', gettext_noop('Swedish')),
)

# Default language
LANGUAGE_CODE = 'en'
25 changes: 24 additions & 1 deletion example/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,33 @@

# Application definition

# Extend the Spirit installed apps (notice the plus sign)
# Check out the spirit.settings.py so you do not end up with duplicate apps.
INSTALLED_APPS += (
# 'myapp',
#'my_app1',
#'my_app2',
)

# same here, check out the spirit.settings.py
MIDDLEWARE_CLASSES += (
#'my_middleware1',
#'my_middleware2',
)

# same here
TEMPLATE_CONTEXT_PROCESSORS += (
#'my_template_proc1',
#'my_template_proc2',
)

# same here (we update the Spirit caches)
CACHES.update({
#'default': {
# 'BACKEND': 'my.backend.path',
#},
})


ROOT_URLCONF = 'example.urls'

WSGI_APPLICATION = 'example.wsgi.application'
Expand Down
2 changes: 1 addition & 1 deletion example/settings_test_runner.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
from settings import *
from local_settings_sample import *
from local_settings_sample_dev import *
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

setup(
name='django-spirit',
version='0.1.1',
version='0.1.2',
description='Spirit is a Python based forum powered by Django.',
author='Esteban Castro Borsani',
author_email='[email protected]',
Expand Down
2 changes: 1 addition & 1 deletion spirit/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '0.1.1'
__version__ = '0.1.2'
2 changes: 1 addition & 1 deletion spirit/forms/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from djconfig.forms import ConfigForm

from django import forms
from django.utils.translation import ugettext as _
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth import get_user_model

from spirit.models.category import Category
Expand Down
20 changes: 10 additions & 10 deletions spirit/forms/comment.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from django import forms
from django.conf import settings
from django.utils.translation import ugettext as _
from django.utils.translation import ugettext_lazy as _
from django.utils.image import Image

from spirit.models.comment import Comment
Expand Down Expand Up @@ -60,6 +60,11 @@ def save(self):
comments_list = list(comments)
topic = self.cleaned_data['topic']
comments.update(topic=topic)

# Update topic in comment instance
for c in comments_list:
c.topic = topic

return comments_list


Expand All @@ -73,24 +78,19 @@ def __init__(self, user=None, *args, **kwargs):

def clean_image(self):
image = self.cleaned_data["image"]
image.format = Image.open(image).format.lower()
image.seek(0)

if Image.open(image).format.lower() not in settings.ST_ALLOWED_UPLOAD_IMAGE_FORMAT:
if image.format not in settings.ST_ALLOWED_UPLOAD_IMAGE_FORMAT:
raise forms.ValidationError(_("Unsupported file format. Supported formats are %s."
% ", ".join(settings.ST_ALLOWED_UPLOAD_IMAGE_FORMAT)))

image.seek(0)
return image

def save(self):
image = self.cleaned_data["image"]
hash = hashlib.md5(image.read()).hexdigest()
name, ext = os.path.splitext(image.name)

# Remove the extension if not allowed
if ext and ext[1:].lower() not in settings.ST_ALLOWED_UPLOAD_IMAGE_EXT:
ext = ""

image.name = u"".join((hash, ext.lower()))
image.name = u"".join((hash, ".", image.format))
upload_to = os.path.join('spirit', 'images', str(self.user.pk))
image.url = os.path.join(settings.MEDIA_URL, upload_to, image.name).replace("\\", "/")
media_path = os.path.join(settings.MEDIA_ROOT, upload_to)
Expand Down
2 changes: 1 addition & 1 deletion spirit/forms/comment_flag.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#-*- coding: utf-8 -*-

from django import forms
from django.utils.translation import ugettext as _
from django.utils.translation import ugettext_lazy as _
from django.db import IntegrityError
from django.utils import timezone

Expand Down
2 changes: 1 addition & 1 deletion spirit/forms/comment_like.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#-*- coding: utf-8 -*-

from django import forms
from django.utils.translation import ugettext as _
from django.utils.translation import ugettext_lazy as _

from spirit.models.comment_like import CommentLike

Expand Down
2 changes: 1 addition & 1 deletion spirit/forms/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from django import forms
from django.conf import settings
from django.utils.translation import ugettext as _
from django.utils.translation import ugettext_lazy as _

from haystack.forms import SearchForm
from haystack.query import EmptySearchQuerySet
Expand Down
2 changes: 1 addition & 1 deletion spirit/forms/topic.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#-*- coding: utf-8 -*-

from django import forms
from django.utils.translation import ugettext as _
from django.utils.translation import ugettext_lazy as _

from ..utils.forms import NestedModelChoiceField
from spirit.models.category import Category
Expand Down
2 changes: 1 addition & 1 deletion spirit/forms/topic_favorite.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#-*- coding: utf-8 -*-

from django import forms
from django.utils.translation import ugettext as _
from django.utils.translation import ugettext_lazy as _

from spirit.models.topic_favorite import TopicFavorite

Expand Down
2 changes: 1 addition & 1 deletion spirit/forms/topic_notification.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#-*- coding: utf-8 -*-

from django import forms
from django.utils.translation import ugettext as _
from django.utils.translation import ugettext_lazy as _

from spirit.models.topic_notification import TopicNotification

Expand Down
114 changes: 114 additions & 0 deletions spirit/forms/topic_poll.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#-*- coding: utf-8 -*-

from django import forms
from django.forms.models import inlineformset_factory, BaseInlineFormSet
from django.utils.translation import ugettext_lazy as _

from spirit.models.topic_poll import TopicPollChoice, TopicPoll, TopicPollVote


class TopicPollForm(forms.ModelForm):

class Meta:
model = TopicPoll
fields = ['choice_limit', ]

def __init__(self, topic=None, *args, **kwargs):
super(TopicPollForm, self).__init__(*args, **kwargs)
self.topic = topic

def clean_choice_limit(self):
choice_limit = self.cleaned_data['choice_limit']

if choice_limit < 1:
raise forms.ValidationError(_("This must be greater than zero"))

return choice_limit

def save(self, commit=True):
if not self.instance.pk:
self.instance.topic = self.topic

return super(TopicPollForm, self).save(commit)


class TopicPollChoiceInlineFormSet(BaseInlineFormSet):

def is_filled(self):
for form in self.forms:
description = form.cleaned_data.get('description')
is_marked_as_delete = form.cleaned_data.get('DELETE', False)

if description and not is_marked_as_delete:
return True

return False


# TODO: use min_num and validate_min in Django 1.7
TopicPollChoiceFormSet = inlineformset_factory(TopicPoll, TopicPollChoice,
formset=TopicPollChoiceInlineFormSet, fields=('description', ),
extra=2, max_num=20, validate_max=True)


class TopicPollVoteManyForm(forms.Form):
"""
This special form allows single vote and multi vote as well.
Its beauty is that it doesn't care if the choice_limit is increased or decreased later.
"""
def __init__(self, user=None, poll=None, *args, **kwargs):
super(TopicPollVoteManyForm, self).__init__(*args, **kwargs)
self.user = user
self.poll = poll
choices = TopicPollChoice.objects.filter(poll=poll)

if poll.choice_limit > 1:
self.fields['choices'] = forms.ModelMultipleChoiceField(queryset=choices,
widget=forms.CheckboxSelectMultiple,
label=_("Poll choices"))
else:
self.fields['choices'] = forms.ModelChoiceField(queryset=choices,
empty_label=None,
widget=forms.RadioSelect,
label=_("Poll choices"))

def load_initial(self):
selected_choices = TopicPollChoice.objects.filter(poll=self.poll, votes__user=self.user)

if self.poll.choice_limit == 1:
try:
selected_choices = selected_choices[0]
except IndexError:
selected_choices = None

self.initial = {'choices': selected_choices, }

def clean_choices(self):
choices = self.cleaned_data['choices']

if self.poll.choice_limit > 1:
if len(choices) > self.poll.choice_limit:
raise forms.ValidationError(_("Too many selected choices. Limit is %s")
% self.poll.choice_limit)

return choices

def clean(self):
cleaned_data = super(TopicPollVoteManyForm, self).clean()

if self.poll.is_closed:
raise forms.ValidationError(_("This poll is closed"))

return cleaned_data

def save_m2m(self):
choices = self.cleaned_data['choices']

if self.poll.choice_limit == 1:
choices = [choices, ]

TopicPollVote.objects.filter(user=self.user, choice__poll=self.poll)\
.delete()

return TopicPollVote.objects.bulk_create([TopicPollVote(user=self.user, choice=choice)
for choice in choices])
2 changes: 1 addition & 1 deletion spirit/forms/topic_private.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#-*- coding: utf-8 -*-

from django import forms
from django.utils.translation import ugettext as _
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth import get_user_model
from django.conf import settings

Expand Down
Loading

0 comments on commit a47ed97

Please sign in to comment.