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
|
||||
.vscode/
|
||||
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
|
||||
|
||||
# Create your models here.
|
||||
|
||||
from django.urls import reverse
|
||||
|
||||
class Event(models.Model):
|
||||
title = models.CharField(max_length=200)
|
||||
description = models.TextField()
|
||||
start_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%;
|
||||
}
|
||||
|
||||
/* App styles */
|
||||
.title {
|
||||
text-align: center;
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.calendar {
|
||||
width: 98%;
|
||||
margin: auto;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.month {
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
tr, td {
|
||||
.calendar tr, .calendar td {
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
th {
|
||||
.calendar th {
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
td {
|
||||
.calendar td {
|
||||
width: 200px;
|
||||
height: 150px;
|
||||
padding: 20px 0px 0px 5px;
|
||||
}
|
||||
|
||||
.month {
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
.date {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
</head>
|
||||
<body>
|
||||
|
||||
<h1 class="title">{% block title %}{% endblock %}</h1>
|
||||
<hr>
|
||||
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
|
||||
|
|
|
@ -1,5 +1,15 @@
|
|||
{% extends 'cal/base.html' %}
|
||||
|
||||
{% block title %}
|
||||
Calendar
|
||||
{% endblock %}
|
||||
|
||||
{% 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 }}
|
||||
{% 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 = [
|
||||
url(r'^index/$', views.index, name='index'),
|
||||
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)
|
||||
d = ''
|
||||
for event in events_per_day:
|
||||
d += f'<li> {event.title} </li>'
|
||||
d += f'<li> {event.get_html_url} </li>'
|
||||
|
||||
if day != 0:
|
||||
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 django.shortcuts import render
|
||||
from django.http import HttpResponse
|
||||
from datetime import datetime, timedelta, date
|
||||
from django.shortcuts import render, get_object_or_404
|
||||
from django.http import HttpResponse, HttpResponseRedirect
|
||||
from django.views import generic
|
||||
from django.urls import reverse
|
||||
from django.utils.safestring import mark_safe
|
||||
import calendar
|
||||
|
||||
from .models import *
|
||||
from .utils import Calendar
|
||||
from .forms import EventForm
|
||||
|
||||
def index(request):
|
||||
return HttpResponse('hello')
|
||||
|
@ -16,14 +19,42 @@ class CalendarView(generic.ListView):
|
|||
|
||||
def get_context_data(self, **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)
|
||||
html_cal = cal.formatmonth(withyear=True)
|
||||
context['calendar'] = mark_safe(html_cal)
|
||||
context['prev_month'] = prev_month(d)
|
||||
context['next_month'] = next_month(d)
|
||||
return context
|
||||
|
||||
def get_date(req_day):
|
||||
if req_day:
|
||||
year, month = (int(x) for x in req_day.split('-'))
|
||||
def get_date(req_month):
|
||||
if req_month:
|
||||
year, month = (int(x) for x in req_month.split('-'))
|
||||
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)
|
||||
# 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