From e609552c59d05a41b98e786047d1ff02c1e3ab10 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Sat, 1 Nov 2014 12:31:52 -0500 Subject: Add bandwidth field to mirror URLs Not using this anywhere just yet, but suggested by Florian so we can do some more fancy things down the road, like determine bandwidth by country. Signed-off-by: Dan McGee --- mirrors/admin.py | 2 +- mirrors/migrations/0002_mirrorurl_bandwidth.py | 20 ++++++++++++++++++++ mirrors/models.py | 3 ++- 3 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 mirrors/migrations/0002_mirrorurl_bandwidth.py diff --git a/mirrors/admin.py b/mirrors/admin.py index d5c89c2a..16a97ea2 100644 --- a/mirrors/admin.py +++ b/mirrors/admin.py @@ -11,7 +11,7 @@ from .models import (Mirror, MirrorProtocol, MirrorUrl, MirrorRsync, class MirrorUrlForm(forms.ModelForm): class Meta: model = MirrorUrl - fields = ('url', 'country', 'active') + fields = ('url', 'country', 'bandwidth', 'active') def clean_url(self): # is this a valid-looking URL? diff --git a/mirrors/migrations/0002_mirrorurl_bandwidth.py b/mirrors/migrations/0002_mirrorurl_bandwidth.py new file mode 100644 index 00000000..f0118199 --- /dev/null +++ b/mirrors/migrations/0002_mirrorurl_bandwidth.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('mirrors', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='mirrorurl', + name='bandwidth', + field=models.FloatField(null=True, verbose_name=b'bandwidth (mbits)', blank=True), + preserve_default=True, + ), + ] diff --git a/mirrors/models.py b/mirrors/models.py index 641a6b97..820f3328 100644 --- a/mirrors/models.py +++ b/mirrors/models.py @@ -72,8 +72,9 @@ class MirrorUrl(models.Model): editable=False) has_ipv6 = models.BooleanField("IPv6 capable", default=False, editable=False) - created = models.DateTimeField(editable=False) active = models.BooleanField(default=True) + bandwidth = models.FloatField("bandwidth (mbits)", null=True, blank=True) + created = models.DateTimeField(editable=False) class Meta: verbose_name = 'mirror URL' -- cgit v1.2.3 From 0c72812fde64f3ed039d807b9e8b3914960b7d6b Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Sun, 2 Nov 2014 09:42:52 -0600 Subject: Mirror view tweaks and enhancements * Add country column to main mirror list overview page. Most mirrors are strictly in one country, so do a little magic to show the right country if it makes sense. * Use new way of getting country names so we respect the overrides now present in the django_countries package. * Make the country selection box on the mirrorlist generation page a lot taller by default so it is easier to use. Signed-off-by: Dan McGee --- main/templatetags/flags.py | 2 +- mirrors/views.py | 37 ++++++++++++++++++++++++++----------- settings.py | 5 +++++ templates/mirrors/mirrors.html | 8 +++++++- 4 files changed, 39 insertions(+), 13 deletions(-) diff --git a/main/templatetags/flags.py b/main/templatetags/flags.py index 22f524ca..5b356561 100644 --- a/main/templatetags/flags.py +++ b/main/templatetags/flags.py @@ -8,6 +8,6 @@ def country_flag(country): if not country: return '' return ' ' % ( - country.code.lower(), country.name) + unicode(country.code).lower(), unicode(country.name)) # vim: set ts=4 sw=4 et: diff --git a/mirrors/views.py b/mirrors/views.py index cffafbf5..65fa0123 100644 --- a/mirrors/views.py +++ b/mirrors/views.py @@ -4,7 +4,7 @@ import json from operator import attrgetter, itemgetter from django import forms -from django.forms.widgets import CheckboxSelectMultiple +from django.forms.widgets import SelectMultiple, CheckboxSelectMultiple from django.core.serializers.json import DjangoJSONEncoder from django.db import connection from django.db.models import Q @@ -14,7 +14,8 @@ from django.utils.timezone import now from django.views.decorators.cache import cache_page from django.views.decorators.csrf import csrf_exempt from django.views.decorators.http import condition -from django_countries.data import COUNTRIES +from django_countries import countries +from django_countries.fields import Country from .models import (Mirror, MirrorUrl, MirrorProtocol, MirrorLog, CheckLocation) @@ -22,7 +23,8 @@ from .utils import get_mirror_statuses, get_mirror_errors, DEFAULT_CUTOFF class MirrorlistForm(forms.Form): - country = forms.MultipleChoiceField(required=False) + country = forms.MultipleChoiceField(required=False, + widget=SelectMultiple(attrs={'size': '12'})) protocol = forms.MultipleChoiceField(required=False, widget=CheckboxSelectMultiple) ip_version = forms.MultipleChoiceField(required=False, @@ -30,8 +32,6 @@ class MirrorlistForm(forms.Form): widget=CheckboxSelectMultiple) use_mirror_status = forms.BooleanField(required=False) - countries = dict(COUNTRIES) - def __init__(self, *args, **kwargs): super(MirrorlistForm, self).__init__(*args, **kwargs) fields = self.fields @@ -49,8 +49,8 @@ class MirrorlistForm(forms.Form): country_codes.update(MirrorUrl.objects.filter(active=True, mirror__active=True).exclude(country='').values_list( 'country', flat=True).order_by().distinct()) - countries = [(code, self.countries[code]) for code in country_codes] - return sorted(countries, key=itemgetter(1)) + code_list = [(code, countries.name(code)) for code in country_codes] + return sorted(code_list, key=itemgetter(1)) def as_div(self): "Returns this form rendered as HTML s." @@ -142,14 +142,29 @@ def mirrors(request): mirror_list = Mirror.objects.select_related().order_by('tier', 'name') protos = MirrorUrl.objects.values_list( 'mirror_id', 'protocol__protocol').order_by( - 'mirror__id', 'protocol__protocol').distinct() + 'mirror_id', 'protocol__protocol').distinct() + countries = MirrorUrl.objects.values_list( + 'mirror_id', 'country').order_by( + 'mirror_id', 'country').distinct() + if not request.user.is_authenticated(): mirror_list = mirror_list.filter(public=True, active=True) - protos = protos.filter(mirror__public=True, mirror__active=True) + protos = protos.filter( + mirror__public=True, mirror__active=True, active=True) + countries = countries.filter( + mirror__public=True, mirror__active=True, active=True) + protos = {k: list(v) for k, v in groupby(protos, key=itemgetter(0))} + countries = {k: list(v) for k, v in groupby(countries, key=itemgetter(0))} + for mirror in mirror_list: - items = protos.get(mirror.id, []) - mirror.protocols = [item[1] for item in items] + item_protos = protos.get(mirror.id, []) + mirror.protocols = [item[1] for item in item_protos] + mirror.country = None + item_countries = countries.get(mirror.id, []) + if len(item_countries) == 1: + mirror.country = Country(item_countries[0][1]) + return render(request, 'mirrors/mirrors.html', {'mirror_list': mirror_list}) diff --git a/settings.py b/settings.py index ba6c68ee..60fe71bc 100644 --- a/settings.py +++ b/settings.py @@ -175,6 +175,11 @@ TORRENT_TRACKERS = ( 'http://tracker.archlinux.org:6969/announce', ) +# Country name overrides for display purposes +COUNTRIES_OVERRIDE = { + 'MK': 'Macedonia', +} + ## Import local settings from local_settings import * diff --git a/templates/mirrors/mirrors.html b/templates/mirrors/mirrors.html index 4276b30a..f55bd875 100644 --- a/templates/mirrors/mirrors.html +++ b/templates/mirrors/mirrors.html @@ -1,8 +1,12 @@ {% extends "base.html" %} {% load cycle from future %} {% load static from staticfiles %} +{% load flags %} + {% block title %}Arch Linux - Mirror Overview{% endblock %} +{% block head %}{% endblock %} + {% block content %}

Mirror Overview

@@ -10,6 +14,7 @@ Server + Country Tier ISOs Protocols @@ -26,6 +31,7 @@ {{ mirror.name }} + {% if mirror.country %}{% country_flag mirror.country %}{{ mirror.country.name }}{% else %}Various{% endif %} {{ mirror.get_tier_display }} {{ mirror.isos|yesno|capfirst }} {{ mirror.protocols|join:", " }} @@ -44,7 +50,7 @@ {% endblock %} -- cgit v1.2.3 From 5bfe138a86a98b52f0b6746b900af6431cd4d17a Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Sun, 2 Nov 2014 10:43:09 -0600 Subject: Add new StaffGroup object This will allow us to be a bit more dynamic in showing the people listings on the website. We'll be adding a Support Staff category to recognize those that do things around here but aren't technically developers. Signed-off-by: Dan McGee --- devel/admin.py | 8 ++++++- devel/migrations/0002_staffgroup.py | 31 ++++++++++++++++++++++++++ devel/models.py | 37 +++++++++++++++++++++---------- public/views.py | 43 +++++++----------------------------- sitemaps.py | 3 --- templates/public/developer_list.html | 4 ++-- templates/public/index.html | 6 ++--- templates/public/userlist.html | 8 +++---- urls.py | 11 ++++----- 9 files changed, 86 insertions(+), 65 deletions(-) create mode 100644 devel/migrations/0002_staffgroup.py diff --git a/devel/admin.py b/devel/admin.py index c8f80f95..d1729fe3 100644 --- a/devel/admin.py +++ b/devel/admin.py @@ -2,7 +2,7 @@ from django.contrib import admin from django.contrib.auth.admin import UserAdmin from django.contrib.auth.models import User -from .models import UserProfile, MasterKey, DeveloperKey, PGPSignature +from .models import UserProfile, StaffGroup, MasterKey, DeveloperKey, PGPSignature class UserProfileInline(admin.StackedInline): @@ -15,6 +15,11 @@ class UserProfileAdmin(UserAdmin): list_filter = ('is_staff', 'is_superuser', 'is_active') +class StaffGroupAdmin(admin.ModelAdmin): + list_display = ('name', 'group', 'sort_order', 'member_title', 'slug') + prepopulated_fields = {'slug': ('name',)} + + class MasterKeyAdmin(admin.ModelAdmin): list_display = ('pgp_key', 'owner', 'created', 'revoker', 'revoked') search_fields = ('pgp_key', 'owner__username', 'revoker__username') @@ -36,6 +41,7 @@ class PGPSignatureAdmin(admin.ModelAdmin): admin.site.unregister(User) admin.site.register(User, UserProfileAdmin) +admin.site.register(StaffGroup, StaffGroupAdmin) admin.site.register(MasterKey, MasterKeyAdmin) admin.site.register(DeveloperKey, DeveloperKeyAdmin) diff --git a/devel/migrations/0002_staffgroup.py b/devel/migrations/0002_staffgroup.py new file mode 100644 index 00000000..5679e6a3 --- /dev/null +++ b/devel/migrations/0002_staffgroup.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('auth', '0001_initial'), + ('devel', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='StaffGroup', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('name', models.CharField(max_length=100)), + ('slug', models.SlugField(unique=True, max_length=100)), + ('sort_order', models.PositiveIntegerField()), + ('member_title', models.CharField(max_length=100)), + ('description', models.TextField(blank=True)), + ('group', models.OneToOneField(to='auth.Group')), + ], + options={ + 'ordering': ('sort_order',), + }, + bases=(models.Model,), + ), + ] diff --git a/devel/models.py b/devel/models.py index 5c4d4fe7..b05800a5 100644 --- a/devel/models.py +++ b/devel/models.py @@ -1,9 +1,10 @@ # -*- coding: utf-8 -*- import pytz +from django.core.urlresolvers import reverse from django.db import models from django.db.models.signals import pre_save -from django.contrib.auth.models import User +from django.contrib.auth.models import User, Group from django_countries.fields import CountryField from .fields import PGPKeyField @@ -54,17 +55,29 @@ class UserProfile(models.Model): verbose_name_plural = 'additional profile data' def get_absolute_url(self): - # TODO: this is disgusting. find a way to consolidate this logic with - # public.views.userlist among other places, and make some constants or - # something so we aren't using copies of string names everywhere. - group_names = self.user.groups.values_list('name', flat=True) - if "Developers" in group_names: - prefix = "developers" - elif "Trusted Users" in group_names: - prefix = "trustedusers" - else: - prefix = "fellows" - return '/%s/#%s' % (prefix, self.user.username) + user = self.user + group = StaffGroup.objects.filter(group=user.groups.all()).first() + if group: + return '%s#%s' % (group.get_absolute_url(), user.username) + return None + + +class StaffGroup(models.Model): + name = models.CharField(max_length=100) + slug = models.SlugField(max_length=100, unique=True) + group = models.OneToOneField(Group) + sort_order = models.PositiveIntegerField() + member_title = models.CharField(max_length=100) + description = models.TextField(blank=True) + + class Meta: + ordering = ('sort_order',) + + def __unicode__(self): + return self.name + + def get_absolute_url(self): + return reverse('people', args=[self.slug]) class MasterKey(models.Model): diff --git a/public/views.py b/public/views.py index 62d1137a..118f067a 100644 --- a/public/views.py +++ b/public/views.py @@ -5,11 +5,11 @@ from operator import attrgetter from django.conf import settings from django.contrib.auth.models import User from django.db.models import Count, Q -from django.http import Http404, HttpResponse -from django.shortcuts import render +from django.http import HttpResponse +from django.shortcuts import get_object_or_404, render from django.views.decorators.cache import cache_control, cache_page -from devel.models import MasterKey, PGPSignature +from devel.models import MasterKey, PGPSignature, StaffGroup from main.models import Arch, Repo, Donor from mirrors.models import MirrorUrl from news.models import News @@ -28,45 +28,18 @@ def index(request): context = { 'news_updates': News.objects.order_by('-postdate', '-id')[:15], 'pkg_updates': updates, + 'staff_groups': StaffGroup.objects.all(), } return render(request, 'public/index.html', context) -USER_LISTS = { - 'devs': { - 'user_type': 'Developers', - 'user_title': 'Developer', - 'description': "This is a list of the current Arch Linux Developers. They maintain the [core] and [extra] package repositories in addition to doing any other developer duties.", - }, - 'tus': { - 'user_type': 'Trusted Users', - 'user_title': 'Trusted User', - 'description': "Here are all your friendly Arch Linux Trusted Users who are in charge of the [community] repository.", - }, - 'fellows': { - 'user_type': 'Fellows', - 'user_title': 'Fellow', - 'description': "Below you can find a list of ex-developers (aka project fellows). These folks helped make Arch what it is today. Thanks!", - }, -} - @cache_control(max_age=307) -def userlist(request, user_type='devs'): - users = User.objects.order_by( +def people(request, slug): + group = get_object_or_404(StaffGroup, slug=slug) + users = User.objects.filter(groups=group.group).order_by( 'first_name', 'last_name').select_related('userprofile') - if user_type == 'devs': - users = users.filter(is_active=True, groups__name="Developers") - elif user_type == 'tus': - users = users.filter(is_active=True, groups__name="Trusted Users") - elif user_type == 'fellows': - users = users.filter(is_active=False, - groups__name__in=["Developers", "Trusted Users"]) - else: - raise Http404 - users = users.distinct() - context = USER_LISTS[user_type].copy() - context['users'] = users + context = {'group': group, 'users': users} return render(request, 'public/userlist.html', context) diff --git a/sitemaps.py b/sitemaps.py index d79b00b5..eb4e05d9 100644 --- a/sitemaps.py +++ b/sitemaps.py @@ -127,9 +127,6 @@ class BaseSitemap(Sitemap): 'page-about', 'page-art', 'page-svn', - 'page-devs', - 'page-tus', - 'page-fellows', 'page-donate', 'feeds-list', 'mirror-list', diff --git a/templates/public/developer_list.html b/templates/public/developer_list.html index 4401d97b..954216ce 100644 --- a/templates/public/developer_list.html +++ b/templates/public/developer_list.html @@ -21,7 +21,7 @@ - +
@@ -53,7 +53,7 @@ Occupation: {{ prof.occupation }} - YOB: + Birth Year: {% if prof.yob %}{{ prof.yob }}{% endif %} Location: diff --git a/templates/public/index.html b/templates/public/index.html index 3b17803c..c78303ce 100644 --- a/templates/public/index.html +++ b/templates/public/index.html @@ -172,9 +172,9 @@

People

diff --git a/templates/public/userlist.html b/templates/public/userlist.html index 35104317..b49c5de2 100644 --- a/templates/public/userlist.html +++ b/templates/public/userlist.html @@ -2,16 +2,16 @@ {% load static from staticfiles %} {% load cache %} -{% block title %}Arch Linux - {{ user_type }}{% endblock %} +{% block title %}Arch Linux - {{ group.name }}{% endblock %} {% block head %}{% endblock %} {% block content %} -{% cache 600 dev-tu-profiles user_type %} +{% cache 600 dev-tu-profiles group.name %}
-

Arch Linux {{user_type}}

+

Arch Linux {{ group.name }}

-

{{description}}

+

{{ group.description }}

{% with users as dev_list %} {% include 'public/developer_list.html' %} diff --git a/urls.py b/urls.py index 8f0bbe21..518e88e7 100644 --- a/urls.py +++ b/urls.py @@ -29,13 +29,11 @@ urlpatterns += patterns('public.views', {}, 'page-art'), (r'^svn/$', TemplateView.as_view(template_name='public/svn.html'), {}, 'page-svn'), - (r'^developers/$', 'userlist', { 'user_type':'devs' }, 'page-devs'), - (r'^trustedusers/$', 'userlist', { 'user_type':'tus' }, 'page-tus'), - (r'^fellows/$', 'userlist', { 'user_type':'fellows' }, 'page-fellows'), (r'^donate/$', 'donate', {}, 'page-donate'), (r'^download/$', 'download', {}, 'page-download'), (r'^master-keys/$', 'keys', {}, 'page-keys'), (r'^master-keys/json/$', 'keys_json', {}, 'pgp-keys-json'), + (r'^people/(?P[-\w]+)/$', 'people', {}, 'people'), ) # Feeds patterns, used below @@ -98,15 +96,18 @@ urlpatterns += patterns('django.contrib.auth.views', legacy_urls = ( ('^about.php', '/about/'), ('^changelog.php', '/packages/?sort=-last_update'), - ('^devs.php', '/developers/'), + ('^devs.php', '/people/developers/'), ('^donations.php', '/donate/'), ('^download.php', '/download/'), ('^index.php', '/'), ('^logos.php', '/art/'), ('^news.php', '/news/'), ('^packages.php', '/packages/'), - ('^people.php', '/developers/'), + ('^people.php', '/people/developers/'), ('^todolists/$', '/todo/'), + ('^developers/$', '/people/developers/'), + ('^fellows/$', '/people/developer-fellows/'), + ('^trustedusers/$', '/people/trusted-users/'), ('^docs/en/guide/install/arch-install-guide.html', 'https://wiki.archlinux.org/index.php/Installation_guide'), -- cgit v1.2.3