Add prev, next month and new, edit event functionality
This commit is contained in:
parent
c3eb1b27d4
commit
45eab3154b
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,3 +1,5 @@
|
||||||
db.sqlite3
|
db.sqlite3
|
||||||
.vscode/
|
.vscode/
|
||||||
env/
|
env/
|
||||||
|
static/
|
||||||
|
*.pyc
|
||||||
|
|
18
cal/forms.py
Normal file
18
cal/forms.py
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
from django.forms import ModelForm, DateInput
|
||||||
|
from cal.models import Event
|
||||||
|
|
||||||
|
class EventForm(ModelForm):
|
||||||
|
class Meta:
|
||||||
|
model = Event
|
||||||
|
# datetime-local is a HTML5 input type, format to make date time show on fields
|
||||||
|
widgets = {
|
||||||
|
'start_time': DateInput(attrs={'type': 'datetime-local'}, format='%Y-%m-%dT%H:%M'),
|
||||||
|
'end_time': DateInput(attrs={'type': 'datetime-local'}, format='%Y-%m-%dT%H:%M'),
|
||||||
|
}
|
||||||
|
fields = '__all__'
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(EventForm, self).__init__(*args, **kwargs)
|
||||||
|
# input_formats parses HTML5 datetime-local input to datetime field
|
||||||
|
self.fields['start_time'].input_formats = ('%Y-%m-%dT%H:%M',)
|
||||||
|
self.fields['end_time'].input_formats = ('%Y-%m-%dT%H:%M',)
|
|
@ -1,10 +1,13 @@
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
from django.urls import reverse
|
||||||
# Create your models here.
|
|
||||||
|
|
||||||
|
|
||||||
class Event(models.Model):
|
class Event(models.Model):
|
||||||
title = models.CharField(max_length=200)
|
title = models.CharField(max_length=200)
|
||||||
description = models.TextField()
|
description = models.TextField()
|
||||||
start_time = models.DateTimeField()
|
start_time = models.DateTimeField()
|
||||||
end_time = models.DateTimeField()
|
end_time = models.DateTimeField()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def get_html_url(self):
|
||||||
|
url = reverse('cal:event_edit', args=(self.id,))
|
||||||
|
return f'<a href="{url}"> {self.title} </a>'
|
||||||
|
|
|
@ -1,28 +1,73 @@
|
||||||
.calendar {
|
/* Common styles */
|
||||||
|
body {
|
||||||
|
font-family: "ptsans", "Lato", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
outline: none;
|
||||||
|
color: black;
|
||||||
|
background-color: transparent;
|
||||||
|
box-shadow: 0 0 0 0;
|
||||||
|
margin-right: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clearfix {
|
||||||
|
margin: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form {
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form input, .form select, .form textarea {
|
||||||
|
border-radius: 5px;
|
||||||
|
border: 1px solid #17a2b8;
|
||||||
|
outline: none;
|
||||||
|
background: none;
|
||||||
|
padding: 5px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* App styles */
|
||||||
|
.title {
|
||||||
|
text-align: center;
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar {
|
||||||
|
width: 98%;
|
||||||
|
margin: auto;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.month {
|
.calendar tr, .calendar td {
|
||||||
font-size: 25px;
|
|
||||||
}
|
|
||||||
|
|
||||||
tr, td {
|
|
||||||
border: 1px solid black;
|
border: 1px solid black;
|
||||||
}
|
}
|
||||||
|
|
||||||
th {
|
.calendar th {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
td {
|
.calendar td {
|
||||||
width: 200px;
|
width: 200px;
|
||||||
height: 150px;
|
height: 150px;
|
||||||
padding: 20px 0px 0px 5px;
|
padding: 20px 0px 0px 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.month {
|
||||||
|
font-size: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
.date {
|
.date {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,9 @@
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
|
<h1 class="title">{% block title %}{% endblock %}</h1>
|
||||||
|
<hr>
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,15 @@
|
||||||
{% extends 'cal/base.html' %}
|
{% extends 'cal/base.html' %}
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
Calendar
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
<div class="clearfix">
|
||||||
|
<a class="btn btn-info left" href="{% url 'cal:calendar' %}?{{ prev_month }}"> Previous Month </a>
|
||||||
|
<a class="btn btn-info right" href="{% url 'cal:calendar' %}?{{ next_month }}"> Next Month </a>
|
||||||
|
<a class="btn btn-info right" href="{% url 'cal:event_new' %}"> New Event </a>
|
||||||
|
</div>
|
||||||
|
|
||||||
{{ calendar }}
|
{{ calendar }}
|
||||||
{% endblock %}
|
{% endblock %}
|
34
cal/templates/cal/event.html
Normal file
34
cal/templates/cal/event.html
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
{% extends 'cal/base.html' %}
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
Event
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="clearfix">
|
||||||
|
<a class="btn btn-info left" href="{% url 'cal:calendar' %}"> Calendar </a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% if form.errors %}
|
||||||
|
{% for field in form %}
|
||||||
|
{% for error in field.errors %}
|
||||||
|
<div class="alert alert-danger">
|
||||||
|
{{ field.label }} <strong>{{ error|escape }}</strong>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
|
{% for error in form.non_field_errors %}
|
||||||
|
<div class="alert alert-danger">
|
||||||
|
{{ field.label }} <strong>{{ error|escape }}</strong>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<form method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
<table class="form form-table">
|
||||||
|
{{ form }}
|
||||||
|
<tr><td colspan="2"><button type="submit" class="btn btn-info right"> Submit </button></td></tr>
|
||||||
|
</table>
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
|
@ -5,4 +5,6 @@ app_name = 'cal'
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'^index/$', views.index, name='index'),
|
url(r'^index/$', views.index, name='index'),
|
||||||
url(r'^calendar/$', views.CalendarView.as_view(), name='calendar'),
|
url(r'^calendar/$', views.CalendarView.as_view(), name='calendar'),
|
||||||
|
url(r'^event/new/$', views.event, name='event_new'),
|
||||||
|
url(r'^event/edit/(?P<event_id>\d+)/$', views.event, name='event_edit'),
|
||||||
]
|
]
|
||||||
|
|
|
@ -14,7 +14,7 @@ class Calendar(HTMLCalendar):
|
||||||
events_per_day = events.filter(start_time__day=day)
|
events_per_day = events.filter(start_time__day=day)
|
||||||
d = ''
|
d = ''
|
||||||
for event in events_per_day:
|
for event in events_per_day:
|
||||||
d += f'<li> {event.title} </li>'
|
d += f'<li> {event.get_html_url} </li>'
|
||||||
|
|
||||||
if day != 0:
|
if day != 0:
|
||||||
return f"<td><span class='date'>{day}</span><ul> {d} </ul></td>"
|
return f"<td><span class='date'>{day}</span><ul> {d} </ul></td>"
|
||||||
|
|
47
cal/views.py
47
cal/views.py
|
@ -1,11 +1,14 @@
|
||||||
from datetime import datetime
|
from datetime import datetime, timedelta, date
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render, get_object_or_404
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse, HttpResponseRedirect
|
||||||
from django.views import generic
|
from django.views import generic
|
||||||
|
from django.urls import reverse
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
|
import calendar
|
||||||
|
|
||||||
from .models import *
|
from .models import *
|
||||||
from .utils import Calendar
|
from .utils import Calendar
|
||||||
|
from .forms import EventForm
|
||||||
|
|
||||||
def index(request):
|
def index(request):
|
||||||
return HttpResponse('hello')
|
return HttpResponse('hello')
|
||||||
|
@ -16,14 +19,42 @@ class CalendarView(generic.ListView):
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
d = get_date(self.request.GET.get('day', None))
|
d = get_date(self.request.GET.get('month', None))
|
||||||
cal = Calendar(d.year, d.month)
|
cal = Calendar(d.year, d.month)
|
||||||
html_cal = cal.formatmonth(withyear=True)
|
html_cal = cal.formatmonth(withyear=True)
|
||||||
context['calendar'] = mark_safe(html_cal)
|
context['calendar'] = mark_safe(html_cal)
|
||||||
|
context['prev_month'] = prev_month(d)
|
||||||
|
context['next_month'] = next_month(d)
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def get_date(req_day):
|
def get_date(req_month):
|
||||||
if req_day:
|
if req_month:
|
||||||
year, month = (int(x) for x in req_day.split('-'))
|
year, month = (int(x) for x in req_month.split('-'))
|
||||||
return date(year, month, day=1)
|
return date(year, month, day=1)
|
||||||
return datetime.today()
|
return datetime.today()
|
||||||
|
|
||||||
|
def prev_month(d):
|
||||||
|
first = d.replace(day=1)
|
||||||
|
prev_month = first - timedelta(days=1)
|
||||||
|
month = 'month=' + str(prev_month.year) + '-' + str(prev_month.month)
|
||||||
|
return month
|
||||||
|
|
||||||
|
def next_month(d):
|
||||||
|
days_in_month = calendar.monthrange(d.year, d.month)[1]
|
||||||
|
last = d.replace(day=days_in_month)
|
||||||
|
next_month = last + timedelta(days=1)
|
||||||
|
month = 'month=' + str(next_month.year) + '-' + str(next_month.month)
|
||||||
|
return month
|
||||||
|
|
||||||
|
def event(request, event_id=None):
|
||||||
|
instance = Event()
|
||||||
|
if event_id:
|
||||||
|
instance = get_object_or_404(Event, pk=event_id)
|
||||||
|
else:
|
||||||
|
instance = Event()
|
||||||
|
|
||||||
|
form = EventForm(request.POST or None, instance=instance)
|
||||||
|
if request.POST and form.is_valid():
|
||||||
|
form.save()
|
||||||
|
return HttpResponseRedirect(reverse('cal:calendar'))
|
||||||
|
return render(request, 'cal/event.html', {'form': form})
|
|
@ -118,4 +118,7 @@ USE_TZ = True
|
||||||
# Static files (CSS, JavaScript, Images)
|
# Static files (CSS, JavaScript, Images)
|
||||||
# https://docs.djangoproject.com/en/2.0/howto/static-files/
|
# https://docs.djangoproject.com/en/2.0/howto/static-files/
|
||||||
|
|
||||||
STATIC_URL = '/static/'
|
# Physical system path where the static files are stored.
|
||||||
|
STATIC_ROOT = os.path.join(BASE_DIR, 'static').replace('\\', '/')
|
||||||
|
# URL that your STATIC files will be accessible through the browser.
|
||||||
|
STATIC_URL = '/static/'
|
BIN
images/calendar_v2.0.png
Normal file
BIN
images/calendar_v2.0.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 169 KiB |
BIN
images/calendar_v2.0_form_edit.png
Normal file
BIN
images/calendar_v2.0_form_edit.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 131 KiB |
BIN
images/calendar_v2.0_form_new.png
Normal file
BIN
images/calendar_v2.0_form_new.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 132 KiB |
Loading…
Reference in a new issue