From 1c8685d15e9ab2006af1dac867e99162d7de781e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?V=C3=AD=C3=B0ir=20Valberg=20Gu=C3=B0mundsson?=
Date: Wed, 8 Aug 2018 22:18:39 +0200
Subject: [PATCH 1/7] Initial work on rideshare feature.
---
src/bornhack/settings.py | 1 +
src/bornhack/urls.py | 5 +++
src/rideshare/__init__.py | 0
src/rideshare/admin.py | 3 ++
src/rideshare/apps.py | 5 +++
src/rideshare/migrations/0001_initial.py | 36 ++++++++++++++++
src/rideshare/migrations/__init__.py | 0
src/rideshare/models.py | 22 ++++++++++
.../rideshare/ride_confirm_delete.html | 10 +++++
.../templates/rideshare/ride_detail.html | 12 ++++++
.../templates/rideshare/ride_form.html | 15 +++++++
.../templates/rideshare/ride_list.html | 18 ++++++++
src/rideshare/tests.py | 3 ++
src/rideshare/urls.py | 43 +++++++++++++++++++
src/rideshare/views.py | 43 +++++++++++++++++++
src/templates/includes/menuitems.html | 1 +
16 files changed, 217 insertions(+)
create mode 100644 src/rideshare/__init__.py
create mode 100644 src/rideshare/admin.py
create mode 100644 src/rideshare/apps.py
create mode 100644 src/rideshare/migrations/0001_initial.py
create mode 100644 src/rideshare/migrations/__init__.py
create mode 100644 src/rideshare/models.py
create mode 100644 src/rideshare/templates/rideshare/ride_confirm_delete.html
create mode 100644 src/rideshare/templates/rideshare/ride_detail.html
create mode 100644 src/rideshare/templates/rideshare/ride_form.html
create mode 100644 src/rideshare/templates/rideshare/ride_list.html
create mode 100644 src/rideshare/tests.py
create mode 100644 src/rideshare/urls.py
create mode 100644 src/rideshare/views.py
diff --git a/src/bornhack/settings.py b/src/bornhack/settings.py
index 8bf4cd27..91590962 100644
--- a/src/bornhack/settings.py
+++ b/src/bornhack/settings.py
@@ -46,6 +46,7 @@ INSTALLED_APPS = [
'bar',
'backoffice',
'events',
+ 'rideshare',
'allauth',
'allauth.account',
diff --git a/src/bornhack/urls.py b/src/bornhack/urls.py
index cda0e36c..fb665d83 100644
--- a/src/bornhack/urls.py
+++ b/src/bornhack/urls.py
@@ -182,6 +182,11 @@ urlpatterns = [
include('teams.urls', namespace='teams')
),
+ path(
+ 'rideshare/',
+ include('rideshare.urls', namespace='rideshare')
+ ),
+
path(
'backoffice/',
include('backoffice.urls', namespace='backoffice')
diff --git a/src/rideshare/__init__.py b/src/rideshare/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/src/rideshare/admin.py b/src/rideshare/admin.py
new file mode 100644
index 00000000..8c38f3f3
--- /dev/null
+++ b/src/rideshare/admin.py
@@ -0,0 +1,3 @@
+from django.contrib import admin
+
+# Register your models here.
diff --git a/src/rideshare/apps.py b/src/rideshare/apps.py
new file mode 100644
index 00000000..9a8b366f
--- /dev/null
+++ b/src/rideshare/apps.py
@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+
+class RideshareConfig(AppConfig):
+ name = 'rideshare'
diff --git a/src/rideshare/migrations/0001_initial.py b/src/rideshare/migrations/0001_initial.py
new file mode 100644
index 00000000..b1a843f3
--- /dev/null
+++ b/src/rideshare/migrations/0001_initial.py
@@ -0,0 +1,36 @@
+# Generated by Django 2.0.4 on 2018-08-08 20:18
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+import uuid
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ('camps', '0028_auto_20180525_1025'),
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Ride',
+ fields=[
+ ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
+ ('created', models.DateTimeField(auto_now_add=True)),
+ ('updated', models.DateTimeField(auto_now=True)),
+ ('seats', models.PositiveIntegerField()),
+ ('location', models.CharField(max_length=100)),
+ ('when', models.DateTimeField()),
+ ('description', models.TextField()),
+ ('camp', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='camps.Camp')),
+ ('user', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)),
+ ],
+ options={
+ 'abstract': False,
+ },
+ ),
+ ]
diff --git a/src/rideshare/migrations/__init__.py b/src/rideshare/migrations/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/src/rideshare/models.py b/src/rideshare/models.py
new file mode 100644
index 00000000..c06cca1c
--- /dev/null
+++ b/src/rideshare/models.py
@@ -0,0 +1,22 @@
+from django.db import models
+from django.urls import reverse
+
+from utils.models import UUIDModel, CampRelatedModel
+
+
+class Ride(UUIDModel, CampRelatedModel):
+ camp = models.ForeignKey('camps.Camp', on_delete=models.PROTECT)
+ user = models.ForeignKey('auth.User', on_delete=models.PROTECT)
+ seats = models.PositiveIntegerField()
+ location = models.CharField(max_length=100)
+ when = models.DateTimeField()
+ description = models.TextField()
+
+ def get_absolute_url(self):
+ return reverse(
+ 'rideshare:detail',
+ kwargs={
+ 'pk': self.pk,
+ 'camp_slug': self.camp.slug
+ }
+ )
diff --git a/src/rideshare/templates/rideshare/ride_confirm_delete.html b/src/rideshare/templates/rideshare/ride_confirm_delete.html
new file mode 100644
index 00000000..73d954b8
--- /dev/null
+++ b/src/rideshare/templates/rideshare/ride_confirm_delete.html
@@ -0,0 +1,10 @@
+{% extends 'base.html' %}
+
+{% block content %}
+
+
+
+{% endblock %}
diff --git a/src/rideshare/templates/rideshare/ride_detail.html b/src/rideshare/templates/rideshare/ride_detail.html
new file mode 100644
index 00000000..6e41af13
--- /dev/null
+++ b/src/rideshare/templates/rideshare/ride_detail.html
@@ -0,0 +1,12 @@
+{% extends 'base.html' %}
+{% load commonmark %}
+
+{% block content %}
+
+{{ object.location }}
+
+{{ object.datetime }}
+
+{{ object.description }}
+
+{% endblock %}
diff --git a/src/rideshare/templates/rideshare/ride_form.html b/src/rideshare/templates/rideshare/ride_form.html
new file mode 100644
index 00000000..c520b609
--- /dev/null
+++ b/src/rideshare/templates/rideshare/ride_form.html
@@ -0,0 +1,15 @@
+{% extends 'base.html' %}
+{% load commonmark %}
+{% load bootstrap3 %}
+
+{% block content %}
+
+
+
+{% endblock %}
diff --git a/src/rideshare/templates/rideshare/ride_list.html b/src/rideshare/templates/rideshare/ride_list.html
new file mode 100644
index 00000000..41ebf72c
--- /dev/null
+++ b/src/rideshare/templates/rideshare/ride_list.html
@@ -0,0 +1,18 @@
+{% extends 'base.html' %}
+
+{% block content %}
+
+
+ Create ride
+
+
+
+
+{% for ride in ride_list %}
+
+ {{ ride.from_location }} at {{ ride.from_datetime}}
+
+
+{% endfor %}
+
+{% endblock %}
diff --git a/src/rideshare/tests.py b/src/rideshare/tests.py
new file mode 100644
index 00000000..7ce503c2
--- /dev/null
+++ b/src/rideshare/tests.py
@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.
diff --git a/src/rideshare/urls.py b/src/rideshare/urls.py
new file mode 100644
index 00000000..e528e248
--- /dev/null
+++ b/src/rideshare/urls.py
@@ -0,0 +1,43 @@
+from django.urls import path, include
+
+from .views import (
+ RideList,
+ RideCreate,
+ RideDetail,
+ RideUpdate,
+ RideDelete,
+)
+
+app_name = 'rideshare'
+
+urlpatterns = [
+ path(
+ '',
+ RideList.as_view(),
+ name='list'
+ ),
+ path(
+ 'create/',
+ RideCreate.as_view(),
+ name='create'
+ ),
+ path(
+ '/', include([
+ path(
+ '',
+ RideDetail.as_view(),
+ name='detail'
+ ),
+ path(
+ 'update/',
+ RideUpdate.as_view(),
+ name='update'
+ ),
+ path(
+ 'delete/',
+ RideDelete.as_view(),
+ name='delete'
+ ),
+ ])
+ )
+]
diff --git a/src/rideshare/views.py b/src/rideshare/views.py
new file mode 100644
index 00000000..de0eaa03
--- /dev/null
+++ b/src/rideshare/views.py
@@ -0,0 +1,43 @@
+from django.contrib.auth.mixins import LoginRequiredMixin
+from django.views.generic import (
+ ListView,
+ DetailView,
+ CreateView,
+ UpdateView,
+ DeleteView,
+)
+from django.http import HttpResponseRedirect
+
+from camps.mixins import CampViewMixin
+
+from .models import Ride
+
+
+class RideList(LoginRequiredMixin, CampViewMixin, ListView):
+ model = Ride
+
+
+class RideDetail(LoginRequiredMixin, CampViewMixin, DetailView):
+ model = Ride
+
+
+class RideCreate(LoginRequiredMixin, CampViewMixin, CreateView):
+ model = Ride
+ fields = ['location', 'when', 'seats', 'description']
+
+ def form_valid(self, form, **kwargs):
+ ride = form.save(commit=False)
+ ride.camp = self.camp
+ ride.user = self.request.user
+ ride.save()
+ self.object = ride
+ return HttpResponseRedirect(self.get_success_url())
+
+
+class RideUpdate(LoginRequiredMixin, CampViewMixin, UpdateView):
+ model = Ride
+ fields = ['location', 'when', 'seats', 'description']
+
+
+class RideDelete(LoginRequiredMixin, CampViewMixin, DeleteView):
+ model = Ride
diff --git a/src/templates/includes/menuitems.html b/src/templates/includes/menuitems.html
index 9b021d07..401da54e 100644
--- a/src/templates/includes/menuitems.html
+++ b/src/templates/includes/menuitems.html
@@ -5,6 +5,7 @@
+
{% if request.user.is_staff %}
{% endif %}
From 6aa37716d6459de47c399ffacf8dcbe4efab0466 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?V=C3=AD=C3=B0ir=20Valberg=20Gu=C3=B0mundsson?=
Date: Thu, 9 Aug 2018 14:36:21 +0200
Subject: [PATCH 2/7] Fleshing out some templates.
---
.../templates/rideshare/ride_detail.html | 35 ++++++++++++++++--
.../templates/rideshare/ride_list.html | 36 +++++++++++++++++--
src/rideshare/urls.py | 6 ++++
src/rideshare/views.py | 9 +++++
src/templates/includes/menuitems.html | 2 ++
5 files changed, 83 insertions(+), 5 deletions(-)
diff --git a/src/rideshare/templates/rideshare/ride_detail.html b/src/rideshare/templates/rideshare/ride_detail.html
index 6e41af13..09383672 100644
--- a/src/rideshare/templates/rideshare/ride_detail.html
+++ b/src/rideshare/templates/rideshare/ride_detail.html
@@ -3,10 +3,39 @@
{% block content %}
-{{ object.location }}
+
+
+ Back
+
+
+
+
+
+
+
+ {{ object.seats }}
+ seats free, going from
+ {{ object.location }}
+ at
+ {{ object.when|date:"jS \o\f F \a\t H:i T" }}
+
+
+
+
Description:
+
+ {{ object.description|untrustedcommonmark }}
+
+
+
+
+
-{{ object.datetime }}
-{{ object.description }}
{% endblock %}
diff --git a/src/rideshare/templates/rideshare/ride_list.html b/src/rideshare/templates/rideshare/ride_list.html
index 41ebf72c..ca022df6 100644
--- a/src/rideshare/templates/rideshare/ride_list.html
+++ b/src/rideshare/templates/rideshare/ride_list.html
@@ -2,17 +2,49 @@
{% block content %}
+
+
+
+On this page participants of {{ camp.title }} can communicate about ridesharing to and from the festival.
+
+
Create ride
-
+
+
+
+ When
+ |
+ Location
+ |
+ Seats
+ |
+ |
{% for ride in ride_list %}
+
+
+ {{ ride.when|date:"c" }}
+ |
+ {{ ride.location }}
+ |
+ {{ ride.seats }}
+ |
+
+ Details
+
- {{ ride.from_location }} at {{ ride.from_datetime}}
+{% empty %}
+ |
+
+ No rideshares yet!
{% endfor %}
+ |
{% endblock %}
diff --git a/src/rideshare/urls.py b/src/rideshare/urls.py
index e528e248..6f07621d 100644
--- a/src/rideshare/urls.py
+++ b/src/rideshare/urls.py
@@ -6,6 +6,7 @@ from .views import (
RideDetail,
RideUpdate,
RideDelete,
+ RideContactConfirm,
)
app_name = 'rideshare'
@@ -38,6 +39,11 @@ urlpatterns = [
RideDelete.as_view(),
name='delete'
),
+ path(
+ 'confirm/',
+ RideContactConfirm.as_view(),
+ name='contact-confirm'
+ ),
])
)
]
diff --git a/src/rideshare/views.py b/src/rideshare/views.py
index de0eaa03..f11eed0e 100644
--- a/src/rideshare/views.py
+++ b/src/rideshare/views.py
@@ -5,6 +5,7 @@ from django.views.generic import (
CreateView,
UpdateView,
DeleteView,
+ TemplateView,
)
from django.http import HttpResponseRedirect
@@ -41,3 +42,11 @@ class RideUpdate(LoginRequiredMixin, CampViewMixin, UpdateView):
class RideDelete(LoginRequiredMixin, CampViewMixin, DeleteView):
model = Ride
+
+
+class RideContactConfirm(LoginRequiredMixin, CampViewMixin, DetailView):
+ model = Ride
+ template_name = "rideshare/ride_contact_confirm.html"
+
+
+# class RideContact(View):
diff --git a/src/templates/includes/menuitems.html b/src/templates/includes/menuitems.html
index 401da54e..fe144075 100644
--- a/src/templates/includes/menuitems.html
+++ b/src/templates/includes/menuitems.html
@@ -5,7 +5,9 @@
+ {% if request.user.is_authenticated %}
+ {% endif %}
{% if request.user.is_staff %}
{% endif %}
From 3229838d0ad880eb5aa8d77fab774a622c36dec9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?V=C3=AD=C3=B0ir=20Valberg=20Gu=C3=B0mundsson?=
Date: Fri, 10 Aug 2018 17:41:19 +0200
Subject: [PATCH 3/7] Adding contact options.
---
.../rideshare/emails/contact_mail.html | 13 +++++
.../rideshare/emails/contact_mail.txt | 13 +++++
.../templates/rideshare/ride_detail.html | 25 ++++++++--
.../templates/rideshare/ride_list.html | 8 +++-
src/rideshare/urls.py | 6 ---
src/rideshare/views.py | 48 +++++++++++++++----
6 files changed, 93 insertions(+), 20 deletions(-)
create mode 100644 src/rideshare/templates/rideshare/emails/contact_mail.html
create mode 100644 src/rideshare/templates/rideshare/emails/contact_mail.txt
diff --git a/src/rideshare/templates/rideshare/emails/contact_mail.html b/src/rideshare/templates/rideshare/emails/contact_mail.html
new file mode 100644
index 00000000..6855a686
--- /dev/null
+++ b/src/rideshare/templates/rideshare/emails/contact_mail.html
@@ -0,0 +1,13 @@
+Hello!
+
+The following message has been submitted to your rideshare on {{ rideshare_url }}.
+
+<message>
+
+ {{ message }}
+
+</message>
+
+Best regards,
+
+The BornHack Teamp
diff --git a/src/rideshare/templates/rideshare/emails/contact_mail.txt b/src/rideshare/templates/rideshare/emails/contact_mail.txt
new file mode 100644
index 00000000..8225c0d5
--- /dev/null
+++ b/src/rideshare/templates/rideshare/emails/contact_mail.txt
@@ -0,0 +1,13 @@
+Hello!
+
+The following message has been submitted to your rideshare on {{ rideshare_url }}.
+
+
+
+{{ message }}
+
+
+
+Best regards,
+
+The BornHack Team
diff --git a/src/rideshare/templates/rideshare/ride_detail.html b/src/rideshare/templates/rideshare/ride_detail.html
index 09383672..bb9e90f5 100644
--- a/src/rideshare/templates/rideshare/ride_detail.html
+++ b/src/rideshare/templates/rideshare/ride_detail.html
@@ -1,5 +1,6 @@
{% extends 'base.html' %}
{% load commonmark %}
+{% load bootstrap3 %}
{% block content %}
@@ -26,14 +27,32 @@
{{ object.description|untrustedcommonmark }}
+ {% if user == object.user %}
+ {% else %}
+
+
+ {% endif %}
diff --git a/src/rideshare/templates/rideshare/ride_list.html b/src/rideshare/templates/rideshare/ride_list.html
index ca022df6..7b39ac5e 100644
--- a/src/rideshare/templates/rideshare/ride_list.html
+++ b/src/rideshare/templates/rideshare/ride_list.html
@@ -10,9 +10,13 @@
On this page participants of {{ camp.title }} can communicate about ridesharing to and from the festival.
-
- Create ride
+
+
+ Create ride
+
+
+
diff --git a/src/rideshare/urls.py b/src/rideshare/urls.py
index 6f07621d..e528e248 100644
--- a/src/rideshare/urls.py
+++ b/src/rideshare/urls.py
@@ -6,7 +6,6 @@ from .views import (
RideDetail,
RideUpdate,
RideDelete,
- RideContactConfirm,
)
app_name = 'rideshare'
@@ -39,11 +38,6 @@ urlpatterns = [
RideDelete.as_view(),
name='delete'
),
- path(
- 'confirm/',
- RideContactConfirm.as_view(),
- name='contact-confirm'
- ),
])
)
]
diff --git a/src/rideshare/views.py b/src/rideshare/views.py
index f11eed0e..19e4ef31 100644
--- a/src/rideshare/views.py
+++ b/src/rideshare/views.py
@@ -1,19 +1,31 @@
+from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin
+from django.urls import reverse
from django.views.generic import (
ListView,
DetailView,
CreateView,
UpdateView,
DeleteView,
- TemplateView,
+ FormView
)
from django.http import HttpResponseRedirect
+from django import forms
from camps.mixins import CampViewMixin
+from utils.email import add_outgoing_email
from .models import Ride
+class ContactRideForm(forms.Form):
+ message = forms.CharField(
+ widget=forms.Textarea(attrs={"placeholder": "Remember to include your contact information!"}),
+ label="Write a message to this rideshare",
+ help_text="ATTENTION!: Pressing send will send an email with the above text. It is up to you to include your contact information so the person receiving the email can contact you.",
+ )
+
+
class RideList(LoginRequiredMixin, CampViewMixin, ListView):
model = Ride
@@ -21,6 +33,32 @@ class RideList(LoginRequiredMixin, CampViewMixin, ListView):
class RideDetail(LoginRequiredMixin, CampViewMixin, DetailView):
model = Ride
+ def get_context_data(self, **kwargs):
+ context = super().get_context_data(**kwargs)
+ context['form'] = ContactRideForm()
+ return context
+
+ def post(self, request, **kwargs):
+ form = ContactRideForm(request.POST)
+ if form.is_valid():
+ ride = self.get_object()
+ add_outgoing_email(
+ text_template='rideshare/emails/contact_mail.txt',
+ to_recipients=[ride.user.emailaddress_set.get(primary=True).email],
+ formatdict=dict(
+ rideshare_url="https://bornhack.dk{}".format(
+ reverse(
+ 'rideshare:detail',
+ kwargs={"camp_slug": self.camp.slug, "pk": ride.pk}
+ )
+ ),
+ message=form.cleaned_data['message'],
+ ),
+ subject="BornHack rideshare message!",
+ )
+ messages.info(request, "Your message has been sent.")
+ return HttpResponseRedirect(ride.get_absolute_url())
+
class RideCreate(LoginRequiredMixin, CampViewMixin, CreateView):
model = Ride
@@ -42,11 +80,3 @@ class RideUpdate(LoginRequiredMixin, CampViewMixin, UpdateView):
class RideDelete(LoginRequiredMixin, CampViewMixin, DeleteView):
model = Ride
-
-
-class RideContactConfirm(LoginRequiredMixin, CampViewMixin, DetailView):
- model = Ride
- template_name = "rideshare/ride_contact_confirm.html"
-
-
-# class RideContact(View):
From c83ebfed082883a4d20175dab4b74883b0e08f43 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?V=C3=AD=C3=B0ir=20Valberg=20Gu=C3=B0mundsson?=
Date: Fri, 10 Aug 2018 18:37:27 +0200
Subject: [PATCH 4/7] Adding admin for rideshare.Ride
---
src/rideshare/admin.py | 7 ++++++-
src/rideshare/models.py | 8 ++++++++
2 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/src/rideshare/admin.py b/src/rideshare/admin.py
index 8c38f3f3..c0f1917e 100644
--- a/src/rideshare/admin.py
+++ b/src/rideshare/admin.py
@@ -1,3 +1,8 @@
from django.contrib import admin
-# Register your models here.
+from .models import Ride
+
+
+@admin.register(Ride)
+class RideModelAdmin(admin.ModelAdmin):
+ list_filter = ('camp', 'user')
diff --git a/src/rideshare/models.py b/src/rideshare/models.py
index c06cca1c..42e5a033 100644
--- a/src/rideshare/models.py
+++ b/src/rideshare/models.py
@@ -20,3 +20,11 @@ class Ride(UUIDModel, CampRelatedModel):
'camp_slug': self.camp.slug
}
)
+
+ def __str__(self):
+ return "{} seats from {} at {} by {}".format(
+ self.seats,
+ self.location,
+ self.when,
+ self.user
+ )
From d6321cf5e849417e3d5d73f1f179f3065cd3411a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?V=C3=AD=C3=B0ir=20Valberg=20Gu=C3=B0mundsson?=
Date: Fri, 10 Aug 2018 18:39:21 +0200
Subject: [PATCH 5/7] Use list_display instead.
---
src/rideshare/admin.py | 1 +
src/rideshare/models.py | 8 --------
2 files changed, 1 insertion(+), 8 deletions(-)
diff --git a/src/rideshare/admin.py b/src/rideshare/admin.py
index c0f1917e..6a674531 100644
--- a/src/rideshare/admin.py
+++ b/src/rideshare/admin.py
@@ -5,4 +5,5 @@ from .models import Ride
@admin.register(Ride)
class RideModelAdmin(admin.ModelAdmin):
+ list_display = ('location', 'when', 'seats', 'user')
list_filter = ('camp', 'user')
diff --git a/src/rideshare/models.py b/src/rideshare/models.py
index 42e5a033..c06cca1c 100644
--- a/src/rideshare/models.py
+++ b/src/rideshare/models.py
@@ -20,11 +20,3 @@ class Ride(UUIDModel, CampRelatedModel):
'camp_slug': self.camp.slug
}
)
-
- def __str__(self):
- return "{} seats from {} at {} by {}".format(
- self.seats,
- self.location,
- self.when,
- self.user
- )
From effe016b577f0dbdcedbc42b1f8d8217f90ffc39 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?V=C3=AD=C3=B0ir=20Valberg=20Gu=C3=B0mundsson?=
Date: Fri, 10 Aug 2018 18:46:35 +0200
Subject: [PATCH 6/7] Ensure only the creator of the ride can edit and delete
it.
---
src/rideshare/views.py | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/src/rideshare/views.py b/src/rideshare/views.py
index 19e4ef31..94305103 100644
--- a/src/rideshare/views.py
+++ b/src/rideshare/views.py
@@ -1,5 +1,5 @@
from django.contrib import messages
-from django.contrib.auth.mixins import LoginRequiredMixin
+from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.urls import reverse
from django.views.generic import (
ListView,
@@ -73,10 +73,15 @@ class RideCreate(LoginRequiredMixin, CampViewMixin, CreateView):
return HttpResponseRedirect(self.get_success_url())
-class RideUpdate(LoginRequiredMixin, CampViewMixin, UpdateView):
+class IsRideOwnerMixin(UserPassesTestMixin):
+ def test_func(self):
+ return self.get_object().user == self.request.user
+
+
+class RideUpdate(LoginRequiredMixin, CampViewMixin, IsRideOwnerMixin, UpdateView):
model = Ride
fields = ['location', 'when', 'seats', 'description']
-class RideDelete(LoginRequiredMixin, CampViewMixin, DeleteView):
+class RideDelete(LoginRequiredMixin, CampViewMixin, IsRideOwnerMixin, DeleteView):
model = Ride
From b864a2cd569bb47181f809489f00a04fe492f2a4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?V=C3=AD=C3=B0ir=20Valberg=20Gu=C3=B0mundsson?=
Date: Fri, 10 Aug 2018 18:46:54 +0200
Subject: [PATCH 7/7] Adding str representation anyway.
---
src/rideshare/models.py | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/src/rideshare/models.py b/src/rideshare/models.py
index c06cca1c..42e5a033 100644
--- a/src/rideshare/models.py
+++ b/src/rideshare/models.py
@@ -20,3 +20,11 @@ class Ride(UUIDModel, CampRelatedModel):
'camp_slug': self.camp.slug
}
)
+
+ def __str__(self):
+ return "{} seats from {} at {} by {}".format(
+ self.seats,
+ self.location,
+ self.when,
+ self.user
+ )