proof that I did something during 33c3

This commit is contained in:
Thomas Steen Rasmussen 2016-12-29 00:15:13 +01:00
parent f8a513ec72
commit 9b089de165
40 changed files with 353 additions and 185 deletions

View File

@ -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',
],
},
},

View File

@ -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<camp_slug>[-_\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<camp_slug>[-_\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<slug>[-_\w+]+)/delete/$',
VillageDeleteView.as_view(),
name='village_delete'
r'^schedule/', include([
url(
r'^(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\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<slug>[-_\w+]+)/$',
SpeakerDetailView.as_view(),
name='speaker_detail'
),
url(
r'^events/$',
EventListView.as_view(),
name='event_index'
),
url(
r'^(?P<slug>[-_\w+]+)/$',
EventDetailView.as_view(),
name='event'
),
])
),
url(
r'(?P<slug>[-_\w+]+)/edit/$',
VillageUpdateView.as_view(),
name='village_update'
r'^sponsors/$',
SponsorIndexView.as_view(),
name='sponsors'
),
url(
r'(?P<slug>[-_\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<slug>[-_\w+]+)/delete/$',
VillageDeleteView.as_view(),
name='village_delete'
),
url(
r'(?P<slug>[-_\w+]+)/edit/$',
VillageUpdateView.as_view(),
name='village_update'
),
url(
r'(?P<slug>[-_\w+]+)/$',
VillageDetailView.as_view(),
name='village_detail'
),
])
),
])),
])),
])
)
]

View File

@ -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
}

View File

@ -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,
),
]

View File

@ -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',
),
]

View File

@ -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)

View File

@ -1,3 +1,6 @@
from django.contrib import admin
from .models import *
admin.site.register(InfoCategory)
admin.site.register(InfoItem)
# Register your models here.

View File

@ -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.'),
),
]

View File

@ -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'})

View File

@ -26,60 +26,45 @@ Info | {{ block.super }}
}
</style>
<div class="row">
<div class="col-md-12">
<h2>Table of Contents</h2>
{% if categories %}
<div class="row">
<div class="col-md-12">
<h3>Table of Contents</h3>
<p class="list-group">
{% for category in categories %}
<a href="#{{ category.anchor }}" class="list-group-item">{{ category.headline }}</a>
{% endfor %}
</p>
</div>
</div>
{% for category in categories %}
<span class="anchor" id="{{ category.anchor }}"></span>
<div class="row">
<div class="col-md-12">
<h2>When is BornHack happening?</h2>
<div class="panel-group">
{% for item in category.infoitems %}
<div class="panel panel-default">
<div class="panel-heading">
<span class="sub-anchor" id="{{ item.anchor }}"></span>
<h4 class="panel-title">
{{ item.title }}
<a href="#{{ item.anchor }}">
<i class="glyphicon glyphicon-link"></i>
</a>
</h4>
</div>
<div class="panel-body">
<p>{{ item.body }}</p>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
{% endfor %}
<script src="{% static 'js/leaflet.js' %}"></script>
<script>
var map = L.map('map', {center: [55.131520, 14.903000], zoom: 10});
L.tileLayer(
'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
{
attribution: '&copy; <a href="http://osm.org/copyright" target="_blank">OpenStreetMap</a> contributors',
}
).addTo(map);
var camp_latlong = [55.011520, 14.975360];
L.marker(camp_latlong).addTo(map);
L.marker(camp_latlong).addTo(map)
.bindPopup('<strong>Coordinates:</strong><br>55.011520, 14.975360<br><strong>Address:</strong><br>Baunevej 11, 3720 Aakirkeby')
.openPopup();
</script>
{% for category in categories %}
<span class="anchor" id="{{ category.anchor }}"></span>
<div class="row">
<div class="col-md-12">
<h2>{{ category.title }}</h2>
<div class="panel-group">
{% for item in category.infoitems.all %}
<div class="panel panel-default">
<div class="panel-heading">
<span class="sub-anchor" id="{{ item.anchor }}"></span>
<h4 class="panel-title">{{ item.headline }}
<a href="#{{ item.anchor }}">
<i class="glyphicon glyphicon-link"></i>
</a>
</h4>
</div>
<div class="panel-body">
<p>{{ item.body }}</p>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
{% endfor %}
{% else %}
<h3>No info found for {{ camp.title }}</h3>
{% endif %}
{% endblock %}

View File

@ -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)

View File

@ -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

0
sponsors/__init__.py Normal file
View File

3
sponsors/admin.py Normal file
View File

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

7
sponsors/apps.py Normal file
View File

@ -0,0 +1,7 @@
from __future__ import unicode_literals
from django.apps import AppConfig
class SponsorsConfig(AppConfig):
name = 'sponsors'

View File

5
sponsors/models.py Normal file
View File

@ -0,0 +1,5 @@
from __future__ import unicode_literals
from django.db import models
# Create your models here.

3
sponsors/tests.py Normal file
View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

9
sponsors/views.py Normal file
View File

@ -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

View File

@ -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 {

View File

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View File

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View File

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

@ -1,5 +1,7 @@
{% load static from staticfiles %}
{% load bootstrap3 %}
{% static "" as baseurl %}
<!DOCTYPE html>
<html lang="en">
<head>
@ -20,7 +22,6 @@
</head>
<body>
<nav class="navbar navbar-fixed-top">
<div class="container-fluid">
<div class="navbar-header">
@ -31,45 +32,50 @@
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">
<img src="{% static 'img/logo-new.png' %}" class="img-responsive" />
{% if request.resolver_match.kwargs.camp_slug %}
<img src="{{ baseurl }}/img/{{ camp.slug }}/{{ camp.slug }}-logo-small.png" class="img-responsive" />
{% else %}
<img src="{% static 'img/logo-small.png' %}" class="img-responsive" />
{% endif %}
</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a href="{% url 'news:index' %}">News</a></li>
<li><a href="{% url 'shop:index' %}">Shop</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Camps <span class="caret"></span></a>
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">{{ camp.title|default:"Camps" }}<span class="caret"></span></a>
<ul class="dropdown-menu">
{% for camp in upcoming_camps %}
<li><a href="{% url 'camp_detail' camp_slug=camp.slug %}">{{ camp.title }}</a></li>
{% endfor %}
<li role="separator" class="divider"></li>
{% for camp in previous_camps %}
<li><a href="{% url 'camp_detail' camp_slug=camp.slug %}">{{ camp.title }}</a></li>
{% for camp in camps %}
<li><a href="{% url 'camp_detail' camp_slug=camp.slug %}">{{ camp.title }}</a></li>
{% endfor %}
</ul>
</li>
{# only include camp specific menu items when relevant #}
{% if request.resolver_match.kwargs.camp_slug %}
<li><a href="{% url 'camp_info' camp_slug=camp.slug %}">Info</a></li>
<li><a href="{% url 'camp_villages' camp_slug=camp.slug %}">Villages</a></li>
<li><a href="{% url 'camp_schedule' camp_slug=camp.slug %}">Schedule</a></li>
<li><a href="{% url 'camp_sponsors' camp_slug=camp.slug %}">Sponsors</a></li>
{% endif %}
<li><a href="{% url 'contact' %}">Contact</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
{% if user.is_authenticated %}
<li><a href="{% url 'profiles:detail' %}">Profile</a></li>
<li><a href="{% url 'profiles:detail' %}">Account</a></li>
{% else %}
<li><a href="{% url 'account_login' %}">Login</a></li>
{% endif %}
</ul>
</ul>
</div>
</div>
</nav>
<div id="main" class="container container-fluid">
{% if camp %}
<div class="row">
<div class="btn-group btn-group-justified">
<a class="btn {% if request.resolver_match.url_name == "camp_detail" %}btn-primary{% else %}btn-default{% endif %}" href="{% url 'camp_detail' camp_slug=camp.slug %}">{{ camp.title }}</a>
<a class="btn {% if request.resolver_match.url_name == "info" %}btn-primary{% else %}btn-default{% endif %}" href="{% url 'info' camp_slug=camp.slug %}">Info</a></li>
<a class="btn {% if request.resolver_match.url_name == "village_list" %}btn-primary{% else %}btn-default{% endif %}" href="{% url 'village_list' camp_slug=camp.slug %}">Villages</a>
<a class="btn {% if request.resolver_match.url_name == "schedule_index" %}btn-primary{% else %}btn-default{% endif %}" href="{% url 'schedule_index' camp_slug=camp.slug %}">Schedule</a>
<a class="btn {% if request.resolver_match.url_name == "sponsors" %}btn-primary{% else %}btn-default{% endif %}" href="{% url 'sponsors' camp_slug=camp.slug %}">Sponsors</a>
</div>
<p>
</div>
{% endif %}
{% bootstrap_messages %}
{% block content %}{% endblock %}
<footer class="row">
@ -78,6 +84,7 @@
<a href="{% url 'general-terms' %}">General Terms &amp; Conditions</a> |
<a href="{% url 'conduct' %}">Code of Conduct</a> |
<a href="{% url 'privacy-policy' %}">Privacy Policy</a>
<a href="{% url 'contact' %}">Contact</a>
{% endblock %}
</div>
</footer>

View File

@ -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):

View File

@ -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'),
),
]

View File

@ -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'),
),
]

View File

@ -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 (

View File

@ -8,6 +8,6 @@
<button type="submit" class="btn btn-danger form-control">Confirm</button>
<br />
<br />
<a href="{% url 'villages:detail' slug=village.slug %}" class="btn btn-default form-control">Cancel</a>
<a href="{% url 'village_detail' slug=village.slug %}" class="btn btn-default form-control">Cancel</a>
</form>
{% endblock %}

View File

@ -13,8 +13,8 @@ Village: {{ village.name }} | {{ block.super }}
{% if user == village.contact %}
<hr />
<a href="{% url 'villages:update' slug=village.slug %}" class="btn btn-primary">Edit</a>
<a href="{% url 'villages:delete' slug=village.slug %}" class="btn btn-danger">Delete</a>
<a href="{% url 'village_update' camp_slug=village.camp.slug slug=village.slug %}" class="btn btn-primary">Edit</a>
<a href="{% url 'village_delete' camp_slug=village.camp.slug slug=village.slug %}" class="btn btn-danger">Delete</a>
{% endif %}
{% endblock %}

View File

@ -13,4 +13,4 @@
<button class="btn btn-primary pull-right" type="submit">Save</button>
</form>
{% endblock %}
{% endblock %}

View File

@ -6,7 +6,7 @@ Villages | {{ block.super }}
{% endblock %}
{% block content %}
<h2>Villages</h2>
<p>
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 }}
</p>
<p class="lead">
<a href="https://bornhack.dk/shop/?category=villages">
It is also possible to rent a tent, chairs and tables for villages here.
</a>
It is also possible to rent a tent, chairs and tables in the shop!
</p>
{% if user.is_authenticated %}
<a href="{% url 'villages:create' %}" class="btn btn-primary">Create a village</a>
<a href="{% url 'village_create' camp_slug=camp.slug %}" class="btn btn-primary">Create a village</a>
{% endif %}
<hr />
{% if villages %}
<table class="table table-hover table-condensed table-striped">
<thead>
<tr>
@ -39,7 +37,7 @@ Villages | {{ block.super }}
{% for village in villages %}
<tr>
<td>
<a href="{% url 'villages:detail' slug=village.slug %}">
<a href="{% url 'village_detail' camp_slug=camp.slug slug=village.slug %}">
{{ village.name }}
</a>
</td>
@ -53,5 +51,7 @@ Villages | {{ block.super }}
{% endfor %}
</tbody>
</table>
{% endblock %}
{% else %}
<h4>No villages for <b>{{ camp.title }}</b> yet!</h4>
{% endif %}
{% endblock %}

View File

@ -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'