Event API & User Event view
This commit is contained in:
parent
111fce5d91
commit
0ce7dc2f25
Binary file not shown.
|
@ -148,8 +148,16 @@ INSTALLED_APPS = (
|
||||||
'sekizai',
|
'sekizai',
|
||||||
'intern_area',
|
'intern_area',
|
||||||
'website',
|
'website',
|
||||||
|
'rest_framework',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
REST_FRAMEWORK = {
|
||||||
|
'DEFAULT_PERMISSION_CLASSES': ('rest_framework.permissions.IsAdminUser',),
|
||||||
|
'PAGINATE_BY': 10
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
CRISPY_TEMPLATE_PACK = 'bootstrap'
|
CRISPY_TEMPLATE_PACK = 'bootstrap'
|
||||||
|
|
||||||
# A sample logging configuration. The only tangible logging
|
# A sample logging configuration. The only tangible logging
|
||||||
|
|
|
@ -9,6 +9,10 @@ import intern_area.views
|
||||||
|
|
||||||
import website.views
|
import website.views
|
||||||
|
|
||||||
|
import eventplanner.views
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
admin.autodiscover()
|
admin.autodiscover()
|
||||||
|
|
||||||
urlpatterns = patterns('',
|
urlpatterns = patterns('',
|
||||||
|
@ -28,4 +32,8 @@ urlpatterns = patterns('',
|
||||||
url(r'^website/$', website.views.home_view),
|
url(r'^website/$', website.views.home_view),
|
||||||
url(r'^login/$', website.views.login_view),
|
url(r'^login/$', website.views.login_view),
|
||||||
url(r'^logout/$', website.views.logout_view),
|
url(r'^logout/$', website.views.logout_view),
|
||||||
|
url(r'^events/$', eventplanner.views.events_view),
|
||||||
|
url(r'^eventParticipation/$', eventplanner.views.event_participation_list ),
|
||||||
|
url(r'^eventParticipation/(\w+)/$', eventplanner.views.event_participation_detail ),
|
||||||
|
url(r'^eventParticipation/(\w+)/(\d+)$', eventplanner.views.event_participation_detail ),
|
||||||
)
|
)
|
|
@ -51,5 +51,10 @@ class EventParticipation( models.Model ):
|
||||||
status = models.CharField ( max_length=3, choices = OPTIONS, default='?' )
|
status = models.CharField ( max_length=3, choices = OPTIONS, default='?' )
|
||||||
comment = models.CharField ( max_length=64, blank=True )
|
comment = models.CharField ( max_length=64, blank=True )
|
||||||
|
|
||||||
|
def get_musician_username(self):
|
||||||
|
return self.musician.user.username
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
unique_together = ("event", "musician")
|
unique_together = ("event", "musician")
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
from rest_framework import serializers
|
||||||
|
from models import EventParticipation
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ParticipationSerializer(serializers.ModelSerializer):
|
||||||
|
event = serializers.PrimaryKeyRelatedField( many=False, read_only = False )
|
||||||
|
musician = serializers.Field( source='get_musician_username' )
|
||||||
|
# musician = serializers.PrimaryKeyRelatedField( many=False, read_only = False )
|
||||||
|
|
||||||
|
def get_identity(self, data):
|
||||||
|
""" This hook is required for bulk update. """
|
||||||
|
try:
|
||||||
|
return ( data.get('event', None), data.get('musician') )
|
||||||
|
except AttributeError:
|
||||||
|
return None
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = EventParticipation
|
||||||
|
fields = ('event', 'musician', 'status', 'comment')
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,175 @@
|
||||||
|
{% extends "website/base.html" %}
|
||||||
|
|
||||||
|
{% load sekizai_tags staticfiles %}
|
||||||
|
|
||||||
|
|
||||||
|
<!-- No Feature slider -->
|
||||||
|
{% block feature_slider %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Static Navbar at top -->
|
||||||
|
{% block navbar_options %} navbar navbar-inverse navbar-static-top {% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
|
||||||
|
{% addtoblock "js" %}
|
||||||
|
<script>
|
||||||
|
|
||||||
|
function getCookie(name) {
|
||||||
|
var cookieValue = null;
|
||||||
|
if (document.cookie && document.cookie != '') {
|
||||||
|
var cookies = document.cookie.split(';');
|
||||||
|
for (var i = 0; i < cookies.length; i++) {
|
||||||
|
var cookie = jQuery.trim(cookies[i]);
|
||||||
|
// Does this cookie string begin with the name we want?
|
||||||
|
if (cookie.substring(0, name.length + 1) == (name + '=')) {
|
||||||
|
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cookieValue;
|
||||||
|
}
|
||||||
|
var csrftoken = getCookie('csrftoken');
|
||||||
|
|
||||||
|
|
||||||
|
function csrfSafeMethod(method) {
|
||||||
|
// these HTTP methods do not require CSRF protection
|
||||||
|
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
|
||||||
|
}
|
||||||
|
$.ajaxSetup({
|
||||||
|
crossDomain: false, // obviates need for sameOrigin test
|
||||||
|
beforeSend: function(xhr, settings) {
|
||||||
|
if (!csrfSafeMethod(settings.type)) {
|
||||||
|
xhr.setRequestHeader("X-CSRFToken", csrftoken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function setEventButtonStatus( button, status ) {
|
||||||
|
others = button.siblings();
|
||||||
|
all = button.add( button.siblings() );
|
||||||
|
|
||||||
|
all.removeClass("btn-danger").
|
||||||
|
removeClass("btn-warning").
|
||||||
|
removeClass("btn-success").
|
||||||
|
removeClass("btn-info");
|
||||||
|
|
||||||
|
others.addClass("btn-info");
|
||||||
|
|
||||||
|
if ( status === "Yes" ) {
|
||||||
|
button.addClass("btn-success");
|
||||||
|
}
|
||||||
|
else if ( status === "No" ) {
|
||||||
|
button.addClass("btn-danger");
|
||||||
|
}
|
||||||
|
else if ( status === "?" ) {
|
||||||
|
button.addClass("btn-warning");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function putStatus( button, status ) {
|
||||||
|
p = button.parent();
|
||||||
|
putObject = [ { "event": p.data("event-id"),
|
||||||
|
"musician": p.data("username"),
|
||||||
|
"status": status } ];
|
||||||
|
|
||||||
|
request = $.ajax( {
|
||||||
|
type: "PUT",
|
||||||
|
url: "/eventParticipation/" + p.data("username") + "/" + p.data("event-id"),
|
||||||
|
contentType: "application/json",
|
||||||
|
data: JSON.stringify(putObject)
|
||||||
|
});
|
||||||
|
|
||||||
|
setEventButtonStatus( button, status );
|
||||||
|
//request.done(function(jqXHR, textStatus) {
|
||||||
|
// setEventButtonStatus( button, status )
|
||||||
|
//});
|
||||||
|
}
|
||||||
|
|
||||||
|
$(function(){
|
||||||
|
|
||||||
|
$(".event-status-yes").click(function () {
|
||||||
|
putStatus( $(this), "Yes" );
|
||||||
|
});
|
||||||
|
|
||||||
|
$(".event-status-no").click(function () {
|
||||||
|
putStatus( $(this), "No" );
|
||||||
|
});
|
||||||
|
|
||||||
|
$(".event-status-dontknow").click(function () {
|
||||||
|
putStatus( $(this), "?" );
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{% endaddtoblock %}
|
||||||
|
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="row-fluid eventTable">
|
||||||
|
<div class="span12">
|
||||||
|
|
||||||
|
<h2>Termine</h2>
|
||||||
|
|
||||||
|
<div class="box-content">
|
||||||
|
<table class="table table-striped">
|
||||||
|
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th id='eventTitle'>Termin</th>
|
||||||
|
<th id='date' >Datum</th>
|
||||||
|
<th id='time' >Uhrzeit</th>
|
||||||
|
<th id='place' >Ort</th>
|
||||||
|
<th id='status' >Status ändern</th>
|
||||||
|
<th id='comment' >Kommentar</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
|
||||||
|
{% for event in events %}
|
||||||
|
<tr>
|
||||||
|
<td class="center"> <a href="{{ event.pk }}"> {{ event.title }} </a> </td>
|
||||||
|
<td class="center"> {{ event.date }} </td>
|
||||||
|
<td class="center"> {{ event.time }} </td>
|
||||||
|
<!-- <td class="center"> {{ event.location }} </td> -->
|
||||||
|
<td class="center"> Ort </td>
|
||||||
|
|
||||||
|
<td class="center">
|
||||||
|
<div class="btn-group event-status-select" data-event-id="{{event.pk}}" data-username="{{user.username}}" >
|
||||||
|
<button class="btn event-status-yes {% if event.participation.status == "Yes" %} btn-success {% else %} btn-info {% endif %}">
|
||||||
|
<i class="icon-ok-sign icon-white"></i>
|
||||||
|
</button>
|
||||||
|
<button class="btn event-status-dontknow {% if event.participation.status == "?" %} btn-warning {% else %} btn-info {% endif %}">
|
||||||
|
<i class="icon-question-sign icon-white "></i>
|
||||||
|
</button>
|
||||||
|
<button class="btn event-status-no {% if event.participation.status == "No" %} btn-danger {% else %} btn-info {% endif %}">
|
||||||
|
<i class="icon-remove-sign icon-white"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
<div class="input-append">
|
||||||
|
<input id="appendedInputButton" size="16" type="text" value="{{ event.participation.comment }}" ><button class="btn" type="button">OK</button>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div><!--/span-->
|
||||||
|
|
||||||
|
</div><!--/row-->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
|
@ -1 +1,87 @@
|
||||||
# Create your views here.
|
|
||||||
|
from django.shortcuts import render, get_object_or_404
|
||||||
|
from django.http import HttpResponse
|
||||||
|
|
||||||
|
from models import Event, EventParticipation
|
||||||
|
from musicians.models import Musician
|
||||||
|
|
||||||
|
from serializers import ParticipationSerializer
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
|
||||||
|
from rest_framework.decorators import api_view
|
||||||
|
from rest_framework.response import Response
|
||||||
|
from rest_framework import status
|
||||||
|
|
||||||
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
|
|
||||||
|
# ---------------------------------------- API ---------------------------------------------------------
|
||||||
|
|
||||||
|
@csrf_exempt
|
||||||
|
@api_view( ['GET'] )
|
||||||
|
def event_participation_list( request ):
|
||||||
|
"""
|
||||||
|
API for participation
|
||||||
|
"""
|
||||||
|
if request.method == 'GET':
|
||||||
|
event_participations = EventParticipation.objects.filter( event__date__gte = datetime.date.today() )
|
||||||
|
serializer = ParticipationSerializer( event_participations, many=True)
|
||||||
|
return Response( serializer.data )
|
||||||
|
|
||||||
|
elif request.method == 'POST':
|
||||||
|
serializer = ParticipationSerializer( data=request.DATA )
|
||||||
|
if serializer.is_valid():
|
||||||
|
print serializer.data
|
||||||
|
serializer.save()
|
||||||
|
return Response( serializer.data, status=status.HTTP_201_CREATED )
|
||||||
|
else:
|
||||||
|
return Response( serializer.errors, status = status.HTTP_400_BAD_REQUEST )
|
||||||
|
|
||||||
|
|
||||||
|
@csrf_exempt
|
||||||
|
@api_view( ['GET', 'PUT'] )
|
||||||
|
def event_participation_detail( request, username, eventId = None ):
|
||||||
|
try:
|
||||||
|
participationQs = EventParticipation.objects.filter( musician__user__username = username )
|
||||||
|
if eventId:
|
||||||
|
participationQs = participationQs.filter( event__pk = eventId )
|
||||||
|
|
||||||
|
except EventParticipation.DoesNotExist:
|
||||||
|
return HttpResponse( status=404)
|
||||||
|
|
||||||
|
|
||||||
|
if request.method == 'GET':
|
||||||
|
serializer = ParticipationSerializer( participationQs )
|
||||||
|
return Response( serializer.data )
|
||||||
|
|
||||||
|
elif request.method == 'PUT':
|
||||||
|
serializer = ParticipationSerializer ( participationQs, data = request.DATA, many=True )
|
||||||
|
if serializer.is_valid():
|
||||||
|
serializer.save()
|
||||||
|
return Response( serializer.data )
|
||||||
|
else:
|
||||||
|
return Response( status = status.HTTP_400_BAD_REQUEST )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------------------------ Normal Views ----------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def events_view( request ):
|
||||||
|
# All events in the future sorted by date
|
||||||
|
all_future_events = list ( Event.objects.filter( date__gte = datetime.date.today() ) )
|
||||||
|
|
||||||
|
|
||||||
|
musician = get_object_or_404( Musician, user=request.user )
|
||||||
|
|
||||||
|
for e in all_future_events:
|
||||||
|
e.participation = EventParticipation.objects.get( event = e, musician = musician )
|
||||||
|
|
||||||
|
context = { 'events' : all_future_events }
|
||||||
|
return render ( request, 'eventplanner/event_view.html', context )
|
||||||
|
|
|
@ -70,6 +70,7 @@
|
||||||
{% endaddtoblock %}
|
{% endaddtoblock %}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div id="sign_in">
|
<div id="sign_in">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
|
@ -13,8 +13,6 @@ def home_view(request):
|
||||||
return render( request, 'website/mainpage.html' )
|
return render( request, 'website/mainpage.html' )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def logout_view(request):
|
def logout_view(request):
|
||||||
logout( request )
|
logout( request )
|
||||||
return redirect( login_view )
|
return redirect( login_view )
|
||||||
|
|
Loading…
Reference in New Issue