I suppose that this is pretty simple to someone who knows JavaScript, but I just can't figure it out on my own.
I've implemented FullCalendar into my Django application, and what I want is simple Event save on users click(saving events to the database after user's action, after the click release and drawn event).
I can add an event using Django form, and have no problem with that, but I want to save the event on click, as I said before. So the user clicks on the desired time, draw the event 'bubble' and let the click off. So when that event is drawn, it needs to be saved directly to the database or passed to the Django form.
I don't have much experience in JS so please don't mind me.
Thank you in advance.
PS: I repeat, everything works fine, I can add an event, delete it, etc, but only with my form.
Let's start with the zakazi.html (page where all the events are created) :
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% load static %}
{% block title %} Zakaži {% endblock title %}
{% block content_row %}
<link rel="stylesheet" href="https://netdna.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.css">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"
integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
crossorigin="anonymous"></script>
{{ form.media }}
{% include 'main/partials/_link_fullcalendar.html' %} # all the cdn's for fullcalendar(link tags)
<div style="display: flex; width: 100%; margin: 0 auto;text-align: center">
<div class="container" style="width: 350px;">
<div class="row">
<div class="col">
<form method="post" action="{% url 'main:add_event' opp.pk %}">
{{ form|crispy }}
{% csrf_token %}
<button type="submit" class="btn btn-primary">Potvrdi</button>
</form>
</div>
</div>
</div>
<div class="container"
style="display: flex; overflow-x: scroll; height: 750px; width: max-content;">
{% if calendars %}
{% for cal in calendars %}
<script>
document.addEventListener('DOMContentLoaded', function () {
let calendarEl = document.getElementById('{{ cal.id }}');
//////////////////////////////////////////////////////////////////////////////////////////////
let calendar1 = new FullCalendar.Calendar(calendarEl, {
minTime: "07:00:00",
maxTime: "22:00:00",
businessHours: {
startTime: '09:00', // a start time (10am in this example)
endTime: '21:00', // an end time (6pm in this example)
},
height: 'auto',
locale: 'sr',
plugins: ['dayGrid', 'timeGrid', 'list', 'interaction'],
defaultView: 'timeGridDay',
header: {
left: 'today',
center: '{{ cal.name|title }}',
right: 'timeGridDay,dayGridWeek,timeGridThreeDay'
},
views: {
timeGridThreeDay: {
type: 'timeGrid',
duration: {days: 3},
buttonText: '3 Dana'
}
},
navLinks: false, // can click day/week names to navigate views
select: function (arg) {
let title = prompt('Naziv posla');
if (title) {
calendar.addEvent({
title: title,
start: arg.start,
end: arg.end,
allDay: arg.allDay
})
}
calendar.unselect()
},
editable: true,
selectable: true,
selectMirror: true,
eventLimit: true, // allow "more" link when too many events
eventTextColor: 'black',
events: [
{% for i in events %}
{% if i.calendar_id == cal.id %}
{
id: "{{ i.event_id }}",
calendar: "{{ i.calendar }}",
calendar_id: "{{ i.calendar_id }}",
title: "{{ i.event_name}}",
start: '{{ i.start_date|date:"Y-m-d" }}T{{ i.start_date|time:"H:i" }}',
end: '{{ i.end_date|date:"Y-m-d" }}T{{ i.end_date|time:"H:i" }}',
},
{% endif %}
{% endfor %}
]
});
//////////////////////////////////////////////////////////////////////////////////////////////
calendar1.render();
//////////////////////////////////////////////////////////////////////////////////////////////
})
;
</script>
{% endfor %}
{% endif %}
<div style="display: flex; height: 1000px" class="container">
{% for cal in calendars %}
<p>{{ cal.name|title }}{{ cal.id }}</p>
<div class="container" id='{{ cal.id }}'></div>
{% endfor %}
</div>
</div>
</div>
<!---------------------------------------------- FULLCALENDAR SCRIPT----------------------------------------------->
{% include 'main/partials/_fullcalendar_script.html' %}
<!---------------------------------------------- FULLCALENDAR SCRIPT END ------------------------------------------>
{% endblock content_row %}
My views.py (all_events and add_events functions):
#################################################### EVENTS #########################################################
def events(request):
all_events = Events.objects.all()
get_event_types = Events.objects.only('event_type')
calendars = Calendar.objects.all()
if request.GET:
event_arr = []
if request.GET.get('event_type') == "all":
all_events = Events.objects.all()
else:
all_events = Events.objects.filter(event_type__icontains=request.GET.get('event_type'))
for i in all_events:
event_sub_arr = {}
event_sub_arr['id'] = i.event_id
event_sub_arr['calendar'] = i.calendar
event_sub_arr['calendar_id'] = i.calendar.id
event_sub_arr['title'] = i.event_name
start_date = datetime.strptime(str(i.start_date.date()), "%Y-%m-%dT%H:%M:%S").strftime("%Y-%m-%dT%H:%M:%S")
end_date = datetime.strptime(str(i.end_date.date()), "%Y-%m-%dT%H:%M:%S").strftime("%Y-%m-%dT%H:%M:%S")
event_sub_arr['start'] = start_date
event_sub_arr['end'] = end_date
event_arr.append(event_sub_arr)
return HttpResponse(json.dumps(event_arr))
context = {
"calendars": calendars,
"events": all_events,
"get_event_types": get_event_types,
}
return render(request, 'main/selectable.html', context)
################################################## ADD EVENTS #########################################################
def add_event(request, pk):
opp = get_object_or_404(OpportunityList, pk=pk)
events_all = Events.objects.all()
calendars = Calendar.objects.all()
opp_locked = get_object_or_404(Locked, pk=pk)
user = User.objects.get(username=request.user.username)
form = AddEventForm()
if request.method == 'POST':
form = AddEventForm(request.POST or None)
if form.is_valid():
event = Events.objects.create(
event_name=form.cleaned_data['event_name'],
event_comment=form.cleaned_data['event_comment'],
status=form.cleaned_data['status'],
start_date=form.cleaned_data['start_date'],
end_date=form.cleaned_data['end_date'],
calendar=form.cleaned_data['calendar'],
opp_eluid=int(opp_locked.locked_eluid.eluid),
zakazan=True,
added_by=user,
)
opp_locked.opp_comment = form.cleaned_data['event_comment']
opp_locked.is_locked = False
opp_locked.zakazan = True
opp_locked.save()
event.save()
messages.success(request, '...' + opp_locked.opp_comment)
return redirect('opportunity:optika')
context = {
'form': form,
'opp': opp,
'events': events_all,
"calendars": calendars
}
return render(request, 'opportunity/detalji/zakazi.html', context) # html for adding events to calendar, where the form is
And the form :
class ZakaziForma(forms.ModelForm):
class Meta:
model = Events
fields = ['event_name', 'event_comment', 'status', 'start_date', 'end_date', 'calendar',
'opp_eluid']
labels = {
'event_name': 'Naziv Posla:',
'event_comment': 'Komentar:',
'status': 'Status:',
'start_date': 'Početak:',
'end_date': 'Završetak:',
'calendar': 'Kalendar',
}
widgets = {
'start_date': DateTimePicker(options={'useCurrent': True, 'collapse': False},
attrs={'icon-toggle': True, }),
'end_date': DateTimePicker(options={'useCurrent': True, 'collapse': False}),
'opp_eluid': forms.HiddenInput(),
}
My urls :
...
path('calendar/dodaj/<int:pk>', add_event, name='add_event'),
...
I think you are trying this in a too complex way. If you use fullcalender and jquery you can just add something like the following in you script code:
$(document).ready(function() {
$('#calendar').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay',
},
defaultView: 'agendaWeek',
navLinks: true,
selectable: true,
selectHelper: true,
select: function(start, end) {
title='new';
if (title) {
eventData = {
title: title,
start: start,
end: end,
backgroundColor: '#00ff00',
};
$('#calendar').fullCalendar('renderEvent', eventData, true); // stick? = true
}
$.ajax({ url: '/addevent/',
data: {
'start': start,
'end': end,
},
});
;
...here you need to addd the code that draws the events
So what happens is that JS renders the event in the browser and sends the data via an ajax call to the django server. Of course you need to add the ajax view in your urls and views code.