Add a Team slug for human readable URLs. Fixes #73

This commit is contained in:
Michael Hall 2018-06-08 22:46:07 -04:00
parent 488d1f5c1e
commit 7540b93d0a
15 changed files with 84 additions and 27 deletions

View file

@ -0,0 +1,34 @@
# Generated by Django 2.0 on 2018-06-09 01:44
from django.db import migrations, models
from events.utils import slugify
def add_team_slug(apps, schema_editor):
Team = apps.get_model('events', 'Team')
for team in Team.objects.all():
team.slug = slugify(team.name)
team.save()
class Migration(migrations.Migration):
dependencies = [
('events', '0031_add_sponsors'),
]
operations = [
migrations.AddField(
model_name='team',
name='slug',
field=models.CharField(max_length=256, null=True),
),
migrations.RunPython(add_team_slug, reverse_code=migrations.RunPython.noop),
migrations.AlterField(
model_name='team',
name='slug',
field=models.CharField(default='', max_length=256),
preserve_default=False,
),
]

View file

@ -222,6 +222,7 @@ class SponsorSerializer(serializers.ModelSerializer):
class Team(models.Model):
name = models.CharField(_("Team Name"), max_length=256, null=False, blank=False)
slug = models.CharField(max_length=256, null=False, blank=False, unique=True)
organization = models.ForeignKey(Organization, related_name='teams', null=True, blank=True, on_delete=models.CASCADE)
description = models.TextField(blank=True, null=True)
@ -282,6 +283,12 @@ class Team(models.Model):
if self.city is not None:
self.spr = self.city.spr
self.country = self.spr.country
new_slug = slugify(self.name)
slug_matches = list(Team.objects.filter(slug=new_slug))
if len(slug_matches) == 0 or (len(slug_matches) == 1 and slug_matches[0].id == self.id):
self.slug = new_slug
else:
self.slug = '%s-%s' % (new_slug, self.id)
super().save(*args, **kwargs) # Call the "real" save() method.

View file

@ -14,7 +14,7 @@
<div class="col-md-4">
<div class="card mb-4 box-shadow">
<div class="card-banner">
<a href="{% url 'show-team' team.id %}">
<a href="{% url 'show-team-by-slug' team.slug %}">
{% if team.category %}
<img class="card-img-top" src="{{team.category.img_url}}" alt="{{team.name}}">
{% else %}

View file

@ -101,7 +101,7 @@
<div class="col-md-9">
<h2>{{ event.name }}
</h2>
<p class="text-muted">Hosted by <a href="{% url "show-team" team.id %}">{{ team.name }}</a></p>
<p class="text-muted">Hosted by <a href="{% url "show-team-by-slug" team.slug %}">{{ team.name }}</a></p>
{% if settings.SOCIAL_AUTH_TWITTER_KEY %}
<a href="https://twitter.com/intent/tweet?text=I'm+having+a+get+together!%0D{{event.name|urlencode}}&original_referer={{event.get_full_url|urlencode}}&url={{event.get_full_url|urlencode}}&hashtags=gettogether" data-size="large" class="btn btn-twitter btn-sm"><i class="fa fa-twitter"></i> Tweet</a>
{% endif %}

View file

@ -39,7 +39,7 @@
<a href="{% url 'edit-series' series.id %}" class="btn btn-secondary btn-sm">Edit Series</a>
{% endif %}
</h2>
<p class="text-muted">Hosted by <a href="{% url "show-team" team.id %}">{{ team.name }}</a></p>
<p class="text-muted">Hosted by <a href="{% url "show-team-by-slug" team.slug %}">{{ team.name }}</a></p>
<hr/>
<p>{{ series.summary|markdown }}</p>

View file

@ -68,7 +68,7 @@
<div class="col-md-4">
<div class="card mb-4 box-shadow">
<div class="card-banner">
<a href="{% url 'show-team' team.id %}">
<a href="{% url 'show-team-by-slug' team.slug %}">
{% if team.category %}
<img class="card-img-top" src="{{team.category.img_url}}" alt="{{team.name}}">
{% else %}
@ -78,11 +78,11 @@
<p class="card-title">{{team.name}}</p>
</div>
<div class="card-body">
<p class="card-text"><strong><a class="card-link" href="{% url 'show-team' team.id %}">{{team.city}}</a></strong></p>
<p class="card-text"><strong><a class="card-link" href="{% url 'show-team-by-slug' team.slug %}">{{team.city}}</a></strong></p>
<div class="d-flex justify-content-between align-items-center">
<small class="text-muted">{{ team.members.count }} members</small>
<div class="btn-group">
<a class="btn btn-primary" href="{% url 'show-team' team.id %}">View</a></span>
<a class="btn btn-primary" href="{% url 'show-team-by-slug' team.slug %}">View</a></span>
</div>
</div>
</div>

View file

@ -14,7 +14,7 @@
<div class="col-md-4">
<div class="card mb-4 box-shadow">
<div class="card-banner">
<a href="{% url 'show-team' team.id %}">
<a href="{% url 'show-team-by-slug' team.slug %}">
{% if team.category %}
<img class="card-img-top" src="{{team.category.img_url}}" alt="{{team.name}}">
{% else %}

View file

@ -65,7 +65,7 @@
<div class="row mb-3">
<div class="col media gt-profile">
<div class="media-body">
<h6 class="mt-0 mb-0"><a href="{% url 'show-team' member.id %}" title="{{member.name}}">{{member.name}}</a></h6>
<h6 class="mt-0 mb-0"><a href="{% url 'show-team-by-slug' member.slug %}" title="{{member.name}}">{{member.name}}</a></h6>
</div>
</div>
</div>

View file

@ -7,7 +7,7 @@
<div class="fluid-container">
<div class="row">
<div class="col-sm-9">
<h2>Invite people to <a href="{% url 'show-team' team.id %}">{{ team.name }}</a>
<h2>Invite people to <a href="{% url 'show-team-by-slug' team.slug %}">{{ team.name }}</a>
</h2>
<p>Add a list of emails, separated by commas</p>
<form action="{% url 'invite-members' team.id %}" method="POST">

View file

@ -20,19 +20,21 @@
<div class="col-md-4">
<div class="card mb-4 box-shadow">
<div class="card-banner">
<a href="{% url 'show-team-by-slug' team.slug %}">
{% if team.category %}
<img class="card-img-top" src="{{team.category.img_url}}" alt="{{team.name}}">
{% else %}
<img class="card-img-top" src="{% static 'img/team_placeholder.png' %}" alt="{{team.name}}">
{% endif %}
</a>
<p class="card-title">{{team.name}}</p>
</div>
<div class="card-body">
<p class="card-text"><strong><a class="card-link" href="{% url 'show-team' team.id %}">{{team.city}}</a></strong></p>
<p class="card-text"><strong>{{team.city}}</strong></p>
<div class="d-flex justify-content-between align-items-center">
<small class="text-muted">{{ team.members.count }} members</small>
<div class="btn-group">
<a class="btn btn-primary" href="{% url 'show-team' team.id %}">View</a></span>
<a class="btn btn-primary" href="{% url 'show-team-by-slug' team.slug %}">View</a></span>
</div>
</div>
</div>

View file

@ -21,7 +21,7 @@
<div class="fluid-container">
<div class="row">
<div class="col-sm-9">
<h2>Members of <a href="{% url 'show-team' team.id %}">{{ team.name }}</a>
<h2>Members of <a href="{% url 'show-team-by-slug' team.slug %}">{{ team.name }}</a>
</h2>
<p><a href="{% url 'invite-members' team.id %}" class="btn btn-secondary btn-sm"><i class="fa fa-user-plus"></i> Invite Members</a></p>

View file

@ -61,7 +61,7 @@
<ul>
{% for t in teams %}
<li>
<a href="{% url 'show-team' t.id %}" title="Team page for {{t.name}}">{{t.name}}</a>
<a href="{% url 'show-team-by-slug' t.slug %}" title="Team page for {{t.name}}">{{t.name}}</a>
</li>
{% endfor %}
</ul>

View file

@ -64,7 +64,7 @@ urlpatterns = [
path('events/all/', views.events_list_all, name='all-events'),
path('teams/', views.teams_list, name='teams'),
path('teams/all/', views.teams_list_all, name='all-teams'),
path('team/<int:team_id>/', views.show_team, name='show-team'),
path('team/<int:team_id>/', views.show_team_by_id, name='show-team'),
path('team/<int:team_id>/+edit/', views.edit_team, name='edit-team'),
path('team/<int:team_id>/+join/', event_views.join_team, name='join-team'),
path('team/<int:team_id>/+leave/', event_views.leave_team, name='leave-team'),
@ -109,6 +109,8 @@ urlpatterns = [
path('about/', include('django.contrib.flatpages.urls')),
path('oauth/', include('social_django.urls', namespace='social')),
path('<str:team_slug>/', views.show_team_by_slug, name='show-team-by-slug'),
]
if settings.DEBUG:
urlpatterns = urlpatterns + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

View file

@ -114,7 +114,7 @@ def create_event(request, team_id):
team = get_object_or_404(Team, id=team_id)
if not request.user.profile.can_create_event(team):
messages.add_message(request, messages.WARNING, message=_('You can not create events for this team.'))
return redirect('show-team', team_id=team.pk)
return redirect('show-team-by-slug', team_slug=team.slug)
new_event = Event(team=team, created_by=request.user.profile)
@ -669,10 +669,10 @@ def delete_event(request, event_id):
elif request.method == 'POST':
form = DeleteEventForm(request.POST)
if form.is_valid() and form.cleaned_data['confirm']:
team_id = event.team_id
delete_event_searchable(event);
team_slug = event.team.slug
delete_event_searchable(event)
event.delete()
return redirect('show-team', team_id)
return redirect('show-team-by-slug', team_slug)
else:
context = {
'team': event.team,
@ -734,9 +734,9 @@ def delete_series(request, series_id):
elif request.method == 'POST':
form = DeleteEventSeriesForm(request.POST)
if form.is_valid() and form.cleaned_data['confirm']:
team_id = series.team_id
team_slug = series.team.slug
series.delete()
return redirect('show-team', team_id)
return redirect('show-team-by-slug', team_slug)
else:
context = {
'team': series.team,

View file

@ -15,6 +15,7 @@ from events.models.profiles import Organization, Team, UserProfile, Member
from events.models.events import Event, CommonEvent, Place, Attendee
from events.forms import TeamForm, NewTeamForm, DeleteTeamForm, TeamContactForm, TeamInviteForm
from events import location
from events.utils import slugify
from accounts.models import EmailRecord
@ -43,8 +44,18 @@ def teams_list_all(request, *args, **kwargs):
}
return render(request, 'get_together/teams/list_teams.html', context)
def show_team(request, team_id, *args, **kwargs):
def show_team_by_slug(request, team_slug):
team = get_object_or_404(Team, slug=team_slug)
return show_team(request, team)
def show_team_by_id(request, team_id):
team = get_object_or_404(Team, id=team_id)
return redirect('show-team-by-slug', team_slug=team.slug)
def show_team(request, team):
upcoming_events = Event.objects.filter(team=team, end_time__gt=datetime.datetime.now()).order_by('start_time')
recent_events = Event.objects.filter(team=team, end_time__lte=datetime.datetime.now()).order_by('-start_time')[:5]
context = {
@ -58,6 +69,7 @@ def show_team(request, team_id, *args, **kwargs):
}
return render(request, 'get_together/teams/show_team.html', context)
@login_required
def create_team(request, *args, **kwargs):
if request.method == 'GET':
@ -74,7 +86,7 @@ def create_team(request, *args, **kwargs):
new_team.owner_profile = request.user.profile
new_team.save()
Member.objects.create(team=new_team, user=request.user.profile, role=Member.ADMIN)
return redirect('show-team', team_id=new_team.pk)
return redirect('show-team-by-slug', team_slug=new_team.slug)
else:
context = {
'team_form': form,
@ -88,7 +100,7 @@ def edit_team(request, team_id):
team = get_object_or_404(Team, id=team_id)
if not request.user.profile.can_edit_team(team):
messages.add_message(request, messages.WARNING, message=_('You can not make changes to this team.'))
return redirect('show-team', team_id=team.pk)
return redirect('show-team-by-slug', team_slug=team.slug)
if request.method == 'GET':
form = TeamForm(instance=team)
@ -104,7 +116,7 @@ def edit_team(request, team_id):
new_team = form.save()
new_team.owner_profile = request.user.profile
new_team.save()
return redirect('show-team', team_id=new_team.pk)
return redirect('show-team-by-slug', team_slug=new_team.slug)
else:
context = {
'team': team,
@ -119,7 +131,7 @@ def delete_team(request, team_id):
team = get_object_or_404(Team, id=team_id)
if not request.user.profile.can_edit_team(team):
messages.add_message(request, messages.WARNING, message=_('You can not make changes to this team.'))
return redirect('show-team', team_id)
return redirect('show-team-by-slug', team.slug)
if request.method == 'GET':
form = DeleteTeamForm()
@ -149,7 +161,7 @@ def manage_members(request, team_id):
team = get_object_or_404(Team, id=team_id)
if not request.user.profile.can_edit_team(team):
messages.add_message(request, messages.WARNING, message=_('You can not manage this team\'s members.'))
return redirect('show-team', team_id)
return redirect('show-team-by-slug', team.slug)
members = Member.objects.filter(team=team).order_by('user__realname')
member_choices = [(member.id, member.user) for member in members if member.user.user.account.is_email_confirmed]
@ -162,7 +174,7 @@ def manage_members(request, team_id):
body = contact_form.cleaned_data['body']
if to is not 'admins' and not request.user.profile.can_edit_team(team):
messages.add_message(request, messages.WARNING, message=_('You can not contact this team\'s members.'))
return redirect('show-team', team_id)
return redirect('show-team-by-slug', team.slug)
if to == 'all':
count = 0
for member in Member.objects.filter(team=team):