Permalink
Browse files

Merge branch 'master' into refactoring

Conflicts:
	apps/users/models.py
	locale/es/LC_MESSAGES/django.mo
	locale/es/LC_MESSAGES/django.po
	templates/mojo.html
	templates/projects/sidebar.html
  • Loading branch information...
zuzelvp committed Jul 3, 2011
2 parents e4d351a + d1e15db commit 71850fb1e9dbaab000a0d2540ab968eecfa88e91
@@ -10,7 +10,7 @@
register = template.Library()
-def sidebar(context):
+def sidebar(context, max_people_count=64):
user = context['user']
project = context['project']
is_participating = is_following = is_organizing = False
@@ -26,9 +26,27 @@ def sidebar(context):
deleted=False, author=profile)
if answers.exists():
pending_signup = answers[0]
- participants_count = project.non_organizer_participants().count()
- followers_count = project.non_participant_followers().count()
- organizers_count = project.organizers().count()
+
+ organizers = project.organizers()
+ organizers_count = organizers.count()
+ participants = project.non_organizer_participants()
+ participants_count = participants.count()
+ followers = project.non_participant_followers()
+ followers_count = followers.count()
+
+ # only display a subset of the participants and followers.
+ remaining = max_people_count
+ sidebar_organizers = organizers[:remaining]
+ sidebar_participants = []
+ sidebar_followers = []
+ remaining -= sidebar_organizers.count()
+ if remaining > 0:
+ sidebar_participants = participants[:remaining]
+ remaining -= sidebar_participants.count()
+ if remaining > 0:
+ sidebar_followers = followers[:remaining]
+ remaining -= sidebar_followers.count()
+
update_count = project.activities().count()
pending_applicants_count = len(project.pending_applicants())
content_pages = Page.objects.filter(project__pk=project.pk,
@@ -52,6 +70,9 @@ def sidebar(context):
'school': school,
'imported_from': imported_from,
'pending_signup': pending_signup,
+ 'sidebar_organizers': sidebar_organizers,
+ 'sidebar_participants': sidebar_participants,
+ 'sidebar_followers': sidebar_followers,
})
return context
View
@@ -26,6 +26,11 @@
name='projects_show'),
url(r'^(?P<slug>[\w-]+)/(?P<page>\d+)/$', 'projects.views.show',
name='projects_show'),
+ url(r'^(?P<slug>[\w-]+)/people/$', 'projects.views.user_list',
+ name='projects_user_list'),
+ url(r'^(?P<slug>[\w-]+)/people/' +
+ '(?P<participants_page>\d+)/(?P<followers_page>\d+)/$',
+ 'projects.views.user_list', name='projects_user_list'),
url(r'^(?P<slug>[\w-]+)/contact_organizers/$',
'projects.views.contact_organizers',
name='projects_contact_organizers'),
View
@@ -605,3 +605,44 @@ def task_list(request, slug):
}
return render_to_response('projects/project_task_list.html', context,
context_instance=RequestContext(request))
+
+
+def user_list(request, slug, participants_page=1, followers_page=1):
+ """Display full list of users for the project."""
+ project = get_object_or_404(Project, slug=slug)
+
+ participants = project.non_organizer_participants()
+ participants_paginator = Paginator(participants, 24)
+ try:
+ participants_current_page = participants_paginator.page(
+ participants_page)
+ except EmptyPage:
+ raise http.Http404
+ participants = participants_current_page.object_list
+
+ followers = project.non_participant_followers()
+ followers_paginator = Paginator(followers, 24)
+ try:
+ followers_current_page = followers_paginator.page(followers_page)
+ except EmptyPage:
+ raise http.Http404
+ followers = followers_current_page.object_list
+
+ return render_to_response('projects/project_user_list.html', {
+ 'project': project,
+ 'organizers': project.organizers(),
+ 'participants': participants,
+ 'followers': followers,
+ 'participants_paginator': participants_paginator,
+ 'participants_page_num': participants_page,
+ 'participants_next_page': int(participants_page) + 1,
+ 'participants_prev_page': int(participants_page) - 1,
+ 'participants_num_pages': participants_paginator.num_pages,
+ 'participants_page': participants_current_page,
+ 'followers_paginator': followers_paginator,
+ 'followers_page_num': followers_page,
+ 'followers_next_page': int(followers_page) + 1,
+ 'followers_prev_page': int(followers_page) - 1,
+ 'followers_num_pages': followers_paginator.num_pages,
+ 'followers_page': followers_current_page,
+ }, context_instance=RequestContext(request))
@@ -1,7 +1,7 @@
import logging
from django.db.utils import IntegrityError
-from django.http import HttpResponseRedirect, Http404, HttpResponseForbidden
+from django.http import HttpResponseRedirect, Http404
from django.views.decorators.http import require_http_methods
from django.shortcuts import get_object_or_404
from django.utils.translation import ugettext as _
@@ -26,9 +26,11 @@ def follow(request, object_type, slug):
if object_type == PROJECT:
project = get_object_or_404(Project, slug=slug)
relationship = Relationship(source=profile, target_project=project)
+ url = project.get_absolute_url()
elif object_type == USER:
user = get_object_or_404(UserProfile, username=slug)
relationship = Relationship(source=profile, target_user=user)
+ url = user.get_absolute_url()
else:
raise Http404
try:
@@ -41,7 +43,7 @@ def follow(request, object_type, slug):
messages.error(request, _('You are already following this user'))
log.warn("Attempt to create duplicate relationship: %s" % (
relationship,))
- return HttpResponseRedirect(request.META['HTTP_REFERER'])
+ return HttpResponseRedirect(url)
@login_required
@@ -52,13 +54,16 @@ def unfollow(request, object_type, slug):
project = get_object_or_404(Project, slug=slug)
# project.participants() includes project.organizers()
if project.participants().filter(user=profile).exists():
- return HttpResponseForbidden(_("You can't unfollow"))
- Relationship.objects.filter(
- source=profile, target_project=project).delete()
+ messages.error(request, _("You can't unfollow"))
+ else:
+ Relationship.objects.filter(
+ source=profile, target_project=project).delete()
+ url = project.get_absolute_url()
elif object_type == USER:
user = get_object_or_404(UserProfile, username=slug)
Relationship.objects.filter(
source=profile, target_user=user).delete()
+ url = user.get_absolute_url()
else:
raise Http404
- return HttpResponseRedirect(request.META['HTTP_REFERER'])
+ return HttpResponseRedirect(url)
View
@@ -1,5 +1,5 @@
from django.contrib import admin
-from users.models import UserProfile
+from users.models import UserProfile, TaggedProfile
class UserProfileAdmin(admin.ModelAdmin):
@@ -9,4 +9,9 @@ class UserProfileAdmin(admin.ModelAdmin):
list_filter = list_display[5:]
search_fields = list_display[:5]
+
+class TaggedProfileAdmin(admin.ModelAdmin):
+ list_display = ('id', 'tag')
+
admin.site.register(UserProfile, UserProfileAdmin)
+admin.site.register(TaggedProfile, TaggedProfileAdmin)
View
@@ -10,9 +10,11 @@
from drumbeat.utils import CKEditorWidget
from captcha import fields as captcha_fields
+from taggit.forms import TagField
+from taggit.utils import edit_string_for_tags
from users.blacklist import passwords as blacklisted_passwords
-from users.models import UserProfile
+from users.models import UserProfile, TaggedProfile
from users.fields import UsernameField
from users import drupal
from links.models import Link
@@ -45,7 +47,6 @@ def check_password_complexity(password):
class SetPasswordForm(auth_forms.SetPasswordForm):
-
def __init__(self, *args, **kwargs):
super(SetPasswordForm, self).__init__(*args, **kwargs)
@@ -171,13 +172,63 @@ def clean(self):
return data
+class CategoryTagWidget(forms.TextInput):
+ def __init__(self, *args, **kwargs):
+ self.category = kwargs.pop('category', None)
+ super(CategoryTagWidget, self).__init__(*args, **kwargs)
+
+ def render(self, name, value, attrs=None):
+ if value is not None and not isinstance(value, basestring):
+ objs = value.select_related("tag").filter(
+ tag__category=self.category)
+ value = edit_string_for_tags([o.tag for o in objs])
+ return super(CategoryTagWidget, self).render(name, value, attrs)
+
+
+class CategoryTagField(TagField):
+ def __init__(self, **kwargs):
+ category = kwargs.pop('category', None)
+ self.widget = CategoryTagWidget(category=category)
+ super(CategoryTagField, self).__init__(**kwargs)
+
+ def clean(self, value):
+ value = super(CategoryTagField, self).clean(value)
+ value = [i.lower() for i in value]
+ return value
+
+
class ProfileEditForm(forms.ModelForm):
+ interest = CategoryTagField(category='interest', required=False)
+ skill = CategoryTagField(category='skill', required=False)
+ desired_topic = CategoryTagField(category='desired_topic', required=False)
+
+ def __init__(self, *args, **kwargs):
+ super(ProfileEditForm, self).__init__(*args, **kwargs)
+
+ if kwargs.has_key('instance'):
+ instance = kwargs['instance']
+ self.initial['interest'] = TaggedProfile.objects.filter(
+ object_id=instance.id)
+ self.initial['skill'] = TaggedProfile.objects.filter(
+ object_id=instance.id)
+ self.initial['desired_topic'] = TaggedProfile.objects.filter(
+ object_id=instance.id)
+
+ def save(self, commit=True):
+ model = super(ProfileEditForm, self).save(commit=False)
+ model.tags.set('interest', *self.cleaned_data['interest'])
+ model.tags.set('skill', *self.cleaned_data['skill'])
+ model.tags.set('desired_topic', *self.cleaned_data['desired_topic'])
+ if commit:
+ model.save()
+ return model
class Meta:
model = UserProfile
- fields = ('full_name', 'location', 'bio', 'preflang',)
+ fields = ('full_name', 'location', 'bio', 'preflang', 'interest')
widgets = {
'bio': CKEditorWidget(config_name='reduced'),
+ 'interest': CategoryTagWidget(category='interest')
}
def clean(self):
@@ -189,7 +240,6 @@ def clean(self):
class ProfileImageForm(forms.ModelForm):
-
class Meta:
model = UserProfile
fields = ('image',)
@@ -206,14 +256,12 @@ def clean_image(self):
class ProfileLinksForm(forms.ModelForm):
-
class Meta:
model = Link
fields = ('name', 'url', 'subscribe',)
class PasswordResetForm(auth_forms.PasswordResetForm):
-
def clean_email(self):
email = self.cleaned_data["email"]
self.users_cache = User.objects.filter(
View
@@ -0,0 +1,59 @@
+from taggit.utils import require_instance_manager
+from taggit.managers import TaggableManager, _TaggableManager
+
+
+class CategoryTaggableManager(TaggableManager):
+ def formfield(self, *args, **kwargs):
+ return None
+
+ def __get__(self, instance, model):
+ """Override ___get___ to return a slightly tweaked manager class"""
+ if instance is not None and instance.pk is None:
+ raise ValueError("%s objects need to have a primary key value "
+ "before you can access their tags." % model.__name__)
+ manager = _CategoryTaggableManager(
+ through=self.through, model=model, instance=instance
+ )
+ return manager
+
+
+class _CategoryTaggableManager(_TaggableManager):
+ @require_instance_manager
+ def add(self, category, *tags):
+ """This is the same as the _TaggableManager add, except it accepts a
+ category parameter."""
+ str_tags = set([
+ t
+ for t in tags
+ if not isinstance(t, self.through.tag_model())
+ ])
+ tag_objs = set(tags) - str_tags
+ # If str_tags has 0 elements Django actually optimizes that to not do a
+ # query. Malcolm is very smart.
+ existing = self.through.tag_model().objects.filter(
+ name__in=str_tags, category=category
+ )
+ tag_objs.update(existing)
+
+ for new_tag in str_tags - set(t.name for t in existing):
+ tag_objs.add(self.through.tag_model().objects.
+ create(name=new_tag, category=category))
+
+ for tag in tag_objs:
+ self.through.objects.get_or_create(
+ tag=tag, **self._lookup_kwargs())
+
+ @require_instance_manager
+ def set(self, category, *tags):
+ self.clear(category)
+ self.add(category, *tags)
+
+ @require_instance_manager
+ def remove(self, category, *tags):
+ self.through.objects.filter(**self._lookup_kwargs()).filter(
+ tag__name__in=tags, tag__category=category).delete()
+
+ @require_instance_manager
+ def clear(self, category):
+ self.through.objects.filter(**self._lookup_kwargs()).filter(
+ tag__category=category).delete()
Oops, something went wrong.

0 comments on commit 71850fb

Please sign in to comment.