From 9b089de1654397fd749933d655af36325c0d2730 Mon Sep 17 00:00:00 2001 From: Thomas Steen Rasmussen Date: Thu, 29 Dec 2016 00:15:13 +0100 Subject: [PATCH] proof that I did something during 33c3 --- bornhack/settings.py | 2 +- bornhack/urls.py | 132 +++++++++++------- camps/context_processors.py | 13 +- camps/migrations/0011_auto_20161228_1750.py | 27 ++++ camps/migrations/0012_auto_20161228_2312.py | 23 +++ camps/mixins.py | 9 +- info/admin.py | 5 +- info/migrations/0002_auto_20161228_2312.py | 29 ++++ info/models.py | 14 +- info/templates/info.html | 81 +++++------ info/views.py | 13 +- program/views.py | 2 +- sponsors/__init__.py | 0 sponsors/admin.py | 3 + sponsors/apps.py | 7 + sponsors/migrations/__init__.py | 0 sponsors/models.py | 5 + .../templates/bornhack-2016-sponsors.html | 0 sponsors/tests.py | 3 + sponsors/views.py | 9 ++ static_src/css/bornhack.css | 20 +-- .../bornhack-2016-logo-large.png} | Bin .../bornhack-2016-logo-small.png} | Bin .../{ => bornhack-2016}/logo-new-paths.svg | 0 static_src/img/bornhack-2016/logo-new.png | Bin 0 -> 4222 bytes .../img/{ => bornhack-2016}/logo-new.svg | 0 static_src/img/bornhack-2016/logo.png | Bin 0 -> 31258 bytes static_src/img/{ => bornhack-2016}/logo.svg | 0 static_src/img/logo-small.png | Bin 0 -> 4123 bytes templates/{info.html => 2016info.html} | 0 templates/base.html | 51 ++++--- utils/models.py | 4 +- villages/migrations/0007_village_camp.py | 22 +++ .../migrations/0008_auto_20161228_2209.py | 21 +++ villages/models.py | 4 +- .../templates/village_confirm_delete.html | 2 +- villages/templates/village_detail.html | 4 +- villages/templates/village_form.html | 2 +- villages/templates/village_list.html | 18 +-- villages/views.py | 13 +- 40 files changed, 353 insertions(+), 185 deletions(-) create mode 100644 camps/migrations/0011_auto_20161228_1750.py create mode 100644 camps/migrations/0012_auto_20161228_2312.py create mode 100644 info/migrations/0002_auto_20161228_2312.py create mode 100644 sponsors/__init__.py create mode 100644 sponsors/admin.py create mode 100644 sponsors/apps.py create mode 100644 sponsors/migrations/__init__.py create mode 100644 sponsors/models.py rename templates/sponsors.html => sponsors/templates/bornhack-2016-sponsors.html (100%) create mode 100644 sponsors/tests.py create mode 100644 sponsors/views.py rename static_src/img/{logo.png => bornhack-2016/bornhack-2016-logo-large.png} (100%) rename static_src/img/{logo-new.png => bornhack-2016/bornhack-2016-logo-small.png} (100%) rename static_src/img/{ => bornhack-2016}/logo-new-paths.svg (100%) create mode 100644 static_src/img/bornhack-2016/logo-new.png rename static_src/img/{ => bornhack-2016}/logo-new.svg (100%) create mode 100644 static_src/img/bornhack-2016/logo.png rename static_src/img/{ => bornhack-2016}/logo.svg (100%) create mode 100644 static_src/img/logo-small.png rename templates/{info.html => 2016info.html} (100%) create mode 100644 villages/migrations/0007_village_camp.py create mode 100644 villages/migrations/0008_auto_20161228_2209.py diff --git a/bornhack/settings.py b/bornhack/settings.py index c9108e34..7c5d3050 100644 --- a/bornhack/settings.py +++ b/bornhack/settings.py @@ -72,7 +72,7 @@ TEMPLATES = [ 'django.contrib.messages.context_processors.messages', 'shop.context_processors.current_order', 'shop.context_processors.user_has_tickets', - 'camps.context_processors.camps', + 'camps.context_processors.camp', ], }, }, diff --git a/bornhack/urls.py b/bornhack/urls.py index 03759c06..3133c851 100644 --- a/bornhack/urls.py +++ b/bornhack/urls.py @@ -11,8 +11,10 @@ from django.contrib import admin from django.views.generic import TemplateView, RedirectView from django.core.urlresolvers import reverse_lazy from camps.views import * -from info.views import CampInfoView - +from info.views import * +from villages.views import * +from program.views import * +from sponsors.views import * urlpatterns = [ url( @@ -27,24 +29,11 @@ urlpatterns = [ r'^news/', include('news.urls', namespace='news') ), - url( - r'^villages/', - include('villages.urls', namespace='villages') - ), - url( - r'^schedule/', - include('program.urls', namespace='schedule') - ), url( r'^$', TemplateView.as_view(template_name='frontpage.html'), name='frontpage' ), - url( - r'^info/', - TemplateView.as_view(template_name='info.html'), - name='info' - ), url( r'^contact/', TemplateView.as_view(template_name='contact.html'), @@ -90,54 +79,91 @@ urlpatterns = [ # camp specific urls below here - url(r'(?P[-_\w+]+)/', include([ - url( - r'^$', - CampDetailView.as_view(), - name='camp_detail' - ), - url( - r'^info/$', - CampInfoView.as_view(), - name='info' - ), - url( - r'^schedule/$', - CampScheduleView.as_view(), - name='schedule' - ), - url( - r'^sponsors/$', - CampSponsorView.as_view(), - name='camp_sponsors' - ), - url(r'^villages/$', include([ + url( + r'(?P[-_\w+]+)/', include([ url( r'^$', - VillageListView.as_view(), - name='village_list' + CampDetailView.as_view(), + name='camp_detail' ), + url( - r'create/$', - VillageCreateView.as_view(), - name='village_create' + r'^info/$', + CampInfoView.as_view(), + name='info' ), + url( - r'(?P[-_\w+]+)/delete/$', - VillageDeleteView.as_view(), - name='village_delete' + r'^schedule/', include([ + url( + r'^(?P\d{4})-(?P\d{2})-(?P\d{2})/$', + ProgramDayView.as_view(), + name='schedule_day' + ), + url( + r'^$', + ProgramOverviewView.as_view(), + name='schedule_index' + ), + url( + r'^speakers/$', + SpeakerListView.as_view(), + name='speaker_index' + ), + url( + r'^speakers/(?P[-_\w+]+)/$', + SpeakerDetailView.as_view(), + name='speaker_detail' + ), + url( + r'^events/$', + EventListView.as_view(), + name='event_index' + ), + url( + r'^(?P[-_\w+]+)/$', + EventDetailView.as_view(), + name='event' + ), + ]) ), + url( - r'(?P[-_\w+]+)/edit/$', - VillageUpdateView.as_view(), - name='village_update' + r'^sponsors/$', + SponsorIndexView.as_view(), + name='sponsors' ), + url( - r'(?P[-_\w+]+)/$', - VillageDetailView.as_view(), - name='village_detail' + r'^villages/', include([ + url( + r'^$', + VillageListView.as_view(), + name='village_list' + ), + url( + r'create/$', + VillageCreateView.as_view(), + name='village_create' + ), + url( + r'(?P[-_\w+]+)/delete/$', + VillageDeleteView.as_view(), + name='village_delete' + ), + url( + r'(?P[-_\w+]+)/edit/$', + VillageUpdateView.as_view(), + name='village_update' + ), + url( + r'(?P[-_\w+]+)/$', + VillageDetailView.as_view(), + name='village_detail' + ), + ]) ), - ])), - ])), + ]) + ) ] diff --git a/camps/context_processors.py b/camps/context_processors.py index faf0aed7..6874755f 100644 --- a/camps/context_processors.py +++ b/camps/context_processors.py @@ -3,9 +3,16 @@ from .models import Camp from django.utils import timezone -def camps(request): +def camp(request): + if 'camp_slug' in request.resolver_match.kwargs: + camp = Camp.objects.get(slug=request.resolver_match.kwargs['camp_slug']) + request.session['campslug'] = camp.slug + else: + request.session['campslug'] = None + camp = None + return { - 'upcoming_camps': Camp.objects.filter(camp_start__gt=timezone.now()), - 'previous_camps': Camp.objects.filter(camp_start__lt=timezone.now()), + 'camps': Camp.objects.all().order_by('-camp_start'), + 'camp': camp } diff --git a/camps/migrations/0011_auto_20161228_1750.py b/camps/migrations/0011_auto_20161228_1750.py new file mode 100644 index 00000000..0f304a50 --- /dev/null +++ b/camps/migrations/0011_auto_20161228_1750.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.4 on 2016-12-28 17:50 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('camps', '0010_auto_20161220_1714'), + ] + + operations = [ + migrations.AddField( + model_name='camp', + name='logo_large', + field=models.CharField(default='', help_text=b'The filename of the large logo to use on the frontpage of this camp', max_length=100, verbose_name=b'Large logo for this camp'), + preserve_default=False, + ), + migrations.AddField( + model_name='camp', + name='logo_small', + field=models.CharField(default='', help_text=b'The filename of the small logo to use in the top of the page for this camp', max_length=100, verbose_name=b'Small logo for this camp'), + preserve_default=False, + ), + ] diff --git a/camps/migrations/0012_auto_20161228_2312.py b/camps/migrations/0012_auto_20161228_2312.py new file mode 100644 index 00000000..c9fc86fc --- /dev/null +++ b/camps/migrations/0012_auto_20161228_2312.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.4 on 2016-12-28 23:12 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('camps', '0011_auto_20161228_1750'), + ] + + operations = [ + migrations.RemoveField( + model_name='camp', + name='logo_large', + ), + migrations.RemoveField( + model_name='camp', + name='logo_small', + ), + ] diff --git a/camps/mixins.py b/camps/mixins.py index cee4d1ad..fca375da 100644 --- a/camps/mixins.py +++ b/camps/mixins.py @@ -1,13 +1,14 @@ -from django.views.generic.detail import SingleObjectMixin from camps.models import Camp from django.shortcuts import get_object_or_404 -class CampViewMixin(Object): +class CampViewMixin(object): def dispatch(self, request, *args, **kwargs): - self.camp = get_object_or_404(Camp, slug=self.kwargs.camp_slug) + self.camp = get_object_or_404(Camp, slug=self.kwargs['camp_slug']) return super(CampViewMixin, self).dispatch(request, *args, **kwargs) def get_queryset(self): - return self.objects.filter(camp=self.camp) + queryset = super(CampViewMixin, self).get_queryset() + return queryset.filter(camp=self.camp) + diff --git a/info/admin.py b/info/admin.py index 8c38f3f3..e8b9235a 100644 --- a/info/admin.py +++ b/info/admin.py @@ -1,3 +1,6 @@ from django.contrib import admin +from .models import * + +admin.site.register(InfoCategory) +admin.site.register(InfoItem) -# Register your models here. diff --git a/info/migrations/0002_auto_20161228_2312.py b/info/migrations/0002_auto_20161228_2312.py new file mode 100644 index 00000000..33317daf --- /dev/null +++ b/info/migrations/0002_auto_20161228_2312.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.4 on 2016-12-28 23:12 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('info', '0001_initial'), + ] + + operations = [ + migrations.AlterModelOptions( + name='infocategory', + options={'ordering': ['-weight', 'headline'], 'verbose_name_plural': 'Info Categories'}, + ), + migrations.AlterField( + model_name='infocategory', + name='weight', + field=models.PositiveIntegerField(default=100, help_text='Determines sorting/ordering. Heavier categories sink to the bottom. Categories with the same weight are ordered alphabetically. Defaults to 100.'), + ), + migrations.AlterField( + model_name='infoitem', + name='weight', + field=models.PositiveIntegerField(default=100, help_text='Determines sorting/ordering. Heavier items sink to the bottom. Items with the same weight are ordered alphabetically. Defaults to 100.'), + ), + ] diff --git a/info/models.py b/info/models.py index 303b083c..04d30a69 100644 --- a/info/models.py +++ b/info/models.py @@ -9,6 +9,7 @@ class InfoCategory(CreatedUpdatedModel): class Meta: ordering = ['-weight', 'headline'] unique_together = (('anchor', 'camp'), ('headline', 'camp')) + verbose_name_plural = "Info Categories" camp = models.ForeignKey( 'camps.Camp', @@ -26,14 +27,18 @@ class InfoCategory(CreatedUpdatedModel): ) weight = models.PositiveIntegerField( - help_text = 'Determines sorting/ordering. Heavier categories sink to the bottom. Categories with the same weight are ordered alphabetically.' + help_text = 'Determines sorting/ordering. Heavier categories sink to the bottom. Categories with the same weight are ordered alphabetically. Defaults to 100.', + default = 100, ) def clean(self): - if InfoItem.objects.filter(camp=self.camp, anchor=self.anchor).exists(): + if InfoItem.objects.filter(category__camp=self.camp, anchor=self.anchor).exists(): # this anchor is already in use on an item, so it cannot be used (must be unique on the page) raise ValidationError({'anchor': 'Anchor is already in use on an info item for this camp'}) + def __str__(self): + return '%s (%s)' % (self.headline, self.camp) + class InfoItem(CreatedUpdatedModel): class Meta: @@ -60,11 +65,12 @@ class InfoItem(CreatedUpdatedModel): ) weight = models.PositiveIntegerField( - help_text = 'Determines sorting/ordering. Heavier items sink to the bottom. Items with the same weight are ordered alphabetically.' + help_text = 'Determines sorting/ordering. Heavier items sink to the bottom. Items with the same weight are ordered alphabetically. Defaults to 100.', + default = 100, ) def clean(self): - if InfoCategory.objects.filter(camp=self.camp, anchor=self.anchor).exists(): + if InfoCategory.objects.filter(camp=self.category.camp, anchor=self.anchor).exists(): # this anchor is already in use on a category, so it cannot be used here (they must be unique on the entire page) raise ValidationError({'anchor': 'Anchor is already in use on an info category for this camp'}) diff --git a/info/templates/info.html b/info/templates/info.html index 1c2d1b2d..2f2cb05a 100644 --- a/info/templates/info.html +++ b/info/templates/info.html @@ -26,60 +26,45 @@ Info | {{ block.super }} } -
-
-

Table of Contents

+ {% if categories %} +
+
+

Table of Contents

{% for category in categories %} {{ category.headline }} {% endfor %}

-
-
- - {% for category in categories %} - -
-
-

When is BornHack happening?

-
- {% for item in category.infoitems %} -
-
- -

- {{ item.title }} - - - -

-
-
-

{{ item.body }}

-
-
- {% endfor %} -
- {% endfor %} - - - + {% for category in categories %} + +
+
+

{{ category.title }}

+
+ {% for item in category.infoitems.all %} +
+
+ +

{{ item.headline }} + + + +

+
+
+

{{ item.body }}

+
+
+ {% endfor %} +
+
+
+ {% endfor %} + {% else %} +

No info found for {{ camp.title }}

+ {% endif %} {% endblock %} + diff --git a/info/views.py b/info/views.py index 3a00a0f7..08e14ea5 100644 --- a/info/views.py +++ b/info/views.py @@ -2,16 +2,15 @@ from django.shortcuts import render from django.views.generic import ListView, DetailView from django.utils import timezone from .models import * +from camps.mixins import CampViewMixin - -class CampInfoView(ListView): +class CampInfoView(CampViewMixin, ListView): model = InfoCategory template_name = 'info.html' context_object_name = 'categories' - def get_queryset(self, **kwargs): - return InfoCategory.objects.filter( - camp__slug=self.kwargs['camp_slug'] - ) - + def get_queryset(self): + queryset = super(CampInfoView, self).get_queryset() + # do not show categories with 0 items + return queryset.exclude(infoitems__isnull=True) diff --git a/program/views.py b/program/views.py index 79e13227..44a37188 100644 --- a/program/views.py +++ b/program/views.py @@ -2,7 +2,7 @@ from collections import OrderedDict import datetime from django.views.generic import ListView, TemplateView, DetailView -from camp.mixins import CampViewMixin +from camps.mixins import CampViewMixin from . import models diff --git a/sponsors/__init__.py b/sponsors/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/sponsors/admin.py b/sponsors/admin.py new file mode 100644 index 00000000..8c38f3f3 --- /dev/null +++ b/sponsors/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/sponsors/apps.py b/sponsors/apps.py new file mode 100644 index 00000000..85079993 --- /dev/null +++ b/sponsors/apps.py @@ -0,0 +1,7 @@ +from __future__ import unicode_literals + +from django.apps import AppConfig + + +class SponsorsConfig(AppConfig): + name = 'sponsors' diff --git a/sponsors/migrations/__init__.py b/sponsors/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/sponsors/models.py b/sponsors/models.py new file mode 100644 index 00000000..bd4b2abe --- /dev/null +++ b/sponsors/models.py @@ -0,0 +1,5 @@ +from __future__ import unicode_literals + +from django.db import models + +# Create your models here. diff --git a/templates/sponsors.html b/sponsors/templates/bornhack-2016-sponsors.html similarity index 100% rename from templates/sponsors.html rename to sponsors/templates/bornhack-2016-sponsors.html diff --git a/sponsors/tests.py b/sponsors/tests.py new file mode 100644 index 00000000..7ce503c2 --- /dev/null +++ b/sponsors/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/sponsors/views.py b/sponsors/views.py new file mode 100644 index 00000000..2beef2e5 --- /dev/null +++ b/sponsors/views.py @@ -0,0 +1,9 @@ +from django.views.generic import TemplateView +from camps.mixins import CampViewMixin + + +class SponsorIndexView(CampViewMixin, TemplateView): + def get_template_name(self): + return '%s-sponsors.html' % self.camp.slug + + diff --git a/static_src/css/bornhack.css b/static_src/css/bornhack.css index dbb1fbff..c549c03b 100644 --- a/static_src/css/bornhack.css +++ b/static_src/css/bornhack.css @@ -1,5 +1,5 @@ body { - margin-top: 90px; + margin-top: 85px; margin-bottom: 35px; } @@ -42,23 +42,7 @@ a, a:active, a:focus { } .navbar-fixed-top { - min-height: 80px; -} - -@media (min-width: 768px) { - .nav li a { - padding: 30px 15px; - } - .nav { - float: right!important; - } -} - -@media (max-width: 767px) { - .nav li { - text-align: center; - font-size: 20px; - } + min-height: 70px; } .navbar-toggle .icon-bar { diff --git a/static_src/img/logo.png b/static_src/img/bornhack-2016/bornhack-2016-logo-large.png similarity index 100% rename from static_src/img/logo.png rename to static_src/img/bornhack-2016/bornhack-2016-logo-large.png diff --git a/static_src/img/logo-new.png b/static_src/img/bornhack-2016/bornhack-2016-logo-small.png similarity index 100% rename from static_src/img/logo-new.png rename to static_src/img/bornhack-2016/bornhack-2016-logo-small.png diff --git a/static_src/img/logo-new-paths.svg b/static_src/img/bornhack-2016/logo-new-paths.svg similarity index 100% rename from static_src/img/logo-new-paths.svg rename to static_src/img/bornhack-2016/logo-new-paths.svg diff --git a/static_src/img/bornhack-2016/logo-new.png b/static_src/img/bornhack-2016/logo-new.png new file mode 100644 index 0000000000000000000000000000000000000000..ede32e9e3c2caf702189b7fe7b3ccb63192401d8 GIT binary patch literal 4222 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 literal 0 HcmV?d00001 diff --git a/static_src/img/logo.svg b/static_src/img/bornhack-2016/logo.svg similarity index 100% rename from static_src/img/logo.svg rename to static_src/img/bornhack-2016/logo.svg diff --git a/static_src/img/logo-small.png b/static_src/img/logo-small.png new file mode 100644 index 0000000000000000000000000000000000000000..1529b2d67e76cfc60df7e144dd22849111b04b10 GIT binary patch literal 4123 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 literal 0 HcmV?d00001 diff --git a/templates/info.html b/templates/2016info.html similarity index 100% rename from templates/info.html rename to templates/2016info.html diff --git a/templates/base.html b/templates/base.html index 7f2547c2..9efb2401 100644 --- a/templates/base.html +++ b/templates/base.html @@ -1,5 +1,7 @@ {% load static from staticfiles %} {% load bootstrap3 %} +{% static "" as baseurl %} + @@ -20,7 +22,6 @@ - - +
+ {% if camp %} + + {% endif %} {% bootstrap_messages %} {% block content %}{% endblock %}
diff --git a/utils/models.py b/utils/models.py index d94a9162..54da5790 100644 --- a/utils/models.py +++ b/utils/models.py @@ -1,5 +1,5 @@ import uuid - +from django.core.exceptions import ValidationError from django.db import models @@ -19,7 +19,7 @@ class CleanedModel(models.Model): print(message) # dont save, just return return - super(CreatedUpdatedModel, self).save(**kwargs) + super(CleanedModel, self).save(**kwargs) class UUIDModel(CleanedModel): diff --git a/villages/migrations/0007_village_camp.py b/villages/migrations/0007_village_camp.py new file mode 100644 index 00000000..338d8b3c --- /dev/null +++ b/villages/migrations/0007_village_camp.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.4 on 2016-12-28 22:08 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('camps', '0011_auto_20161228_1750'), + ('villages', '0006_remove_village_camp'), + ] + + operations = [ + migrations.AddField( + model_name='village', + name='camp', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='camps.Camp'), + ), + ] diff --git a/villages/migrations/0008_auto_20161228_2209.py b/villages/migrations/0008_auto_20161228_2209.py new file mode 100644 index 00000000..aba16e5c --- /dev/null +++ b/villages/migrations/0008_auto_20161228_2209.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.4 on 2016-12-28 22:09 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('villages', '0007_village_camp'), + ] + + operations = [ + migrations.AlterField( + model_name='village', + name='camp', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='camps.Camp'), + ), + ] diff --git a/villages/models.py b/villages/models.py index da7104b0..8860a280 100644 --- a/villages/models.py +++ b/villages/models.py @@ -15,7 +15,7 @@ class Village(CreatedUpdatedModel, UUIDModel): ordering = ['name'] contact = models.ForeignKey('auth.User') - + camp = models.ForeignKey('camps.Camp') name = models.CharField(max_length=255) slug = models.SlugField(max_length=255, blank=True) description = models.TextField( @@ -37,7 +37,7 @@ class Village(CreatedUpdatedModel, UUIDModel): return self.name def get_absolute_url(self): - return reverse_lazy('villages:detail', kwargs={'slug': self.slug}) + return reverse_lazy('village_detail', kwargs={'camp_slug': self.camp.slug, 'slug': self.slug}) def save(self, **kwargs): if ( diff --git a/villages/templates/village_confirm_delete.html b/villages/templates/village_confirm_delete.html index d4fd816c..f3a8207a 100644 --- a/villages/templates/village_confirm_delete.html +++ b/villages/templates/village_confirm_delete.html @@ -8,6 +8,6 @@

- Cancel + Cancel {% endblock %} diff --git a/villages/templates/village_detail.html b/villages/templates/village_detail.html index db73c6d8..0a49e09e 100644 --- a/villages/templates/village_detail.html +++ b/villages/templates/village_detail.html @@ -13,8 +13,8 @@ Village: {{ village.name }} | {{ block.super }} {% if user == village.contact %}
-Edit -Delete +Edit +Delete {% endif %} {% endblock %} diff --git a/villages/templates/village_form.html b/villages/templates/village_form.html index 3b5f8534..2accd283 100644 --- a/villages/templates/village_form.html +++ b/villages/templates/village_form.html @@ -13,4 +13,4 @@ -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/villages/templates/village_list.html b/villages/templates/village_list.html index 6af03edb..7e7ae95e 100644 --- a/villages/templates/village_list.html +++ b/villages/templates/village_list.html @@ -6,7 +6,7 @@ Villages | {{ block.super }} {% endblock %} {% block content %} - +

Villages

If this is your first hackercamp the term 'Village' might be confusing but it is fairly simple: a village is just a spot on the campsite where you and a @@ -16,17 +16,15 @@ Villages | {{ block.super }}

- - It is also possible to rent a tent, chairs and tables for villages here. - + It is also possible to rent a tent, chairs and tables in the shop!

{% if user.is_authenticated %} -Create a village +Create a village {% endif %}
- +{% if villages %} @@ -39,7 +37,7 @@ Villages | {{ block.super }} {% for village in villages %} @@ -53,5 +51,7 @@ Villages | {{ block.super }} {% endfor %}
- + {{ village.name }}
- -{% endblock %} \ No newline at end of file +{% else %} +

No villages for {{ camp.title }} yet!

+{% endif %} +{% endblock %} diff --git a/villages/views.py b/villages/views.py index 901e79cf..69fa59a9 100644 --- a/villages/views.py +++ b/villages/views.py @@ -2,21 +2,20 @@ from django.http import Http404 from django.contrib.auth.mixins import LoginRequiredMixin from django.core.urlresolvers import reverse_lazy from django.http import HttpResponseRedirect -from django.views.generic import ( - ListView, DetailView, CreateView, UpdateView, DeleteView -) +from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView from django.views.generic.detail import SingleObjectMixin - from .models import Village +from camps.models import Camp +from camps.mixins import CampViewMixin -class VillageListView(ListView): +class VillageListView(CampViewMixin, ListView): queryset = Village.objects.not_deleted() template_name = 'village_list.html' context_object_name = 'villages' -class VillageDetailView(DetailView): +class VillageDetailView(CampViewMixin, DetailView): queryset = Village.objects.not_deleted() template_name = 'village_detail.html' context_object_name = 'village' @@ -31,6 +30,7 @@ class VillageCreateView(LoginRequiredMixin, CreateView): def form_valid(self, form): village = form.save(commit=False) village.contact = self.request.user + village.camp = Camp.objects.get(slug=self.request.session['campslug']) village.save() return HttpResponseRedirect(village.get_absolute_url()) @@ -64,3 +64,4 @@ class VillageDeleteView(EnsureUserOwnsVillageMixin, LoginRequiredMixin, DeleteVi success_url = reverse_lazy('villages:list') template_name = 'village_confirm_delete.html' context_object_name = 'village' +