Using fullCalendar in Django

六月ゝ 毕业季﹏ 提交于 2019-12-22 00:59:35

问题


Somewhat of a follow-up to the question posted here (Django: modifying data with user input through custom template tag?), but since asking the question I've decided to take a different approach. As you can tell I'm a newb so please go easy.

I want a weekly calendar in my Django app that displays shifts in the database. Following is the Shift model.

class Shift(models.Model):
    owner = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='shifts',
        blank=True, null=True) # A shift may not have an owner.

    # Choices for fields. Add more choices as necessary.
    DAYS = (
        ('M', 'Monday'),
        ('TU', 'Tuesday'),
        ('W', 'Wednesday'),
        ('TH', 'Thursday'),
        ('F', 'Friday'),
        ('SA', 'Saturday'),
        ('SU', 'Sunday'),
    )

    day_of_the_week = models.CharField(max_length=2, choices=DAYS, blank=True, null=True)
    start_date = models.DateField(blank=True, null=True)
    end_date = models.DateField(blank=True, null=True)
    start_time = models.TimeField(default='12:00:00')
    end_time = models.TimeField(default='14:00:00')
    hours = models.DurationField(editable=False)
    activated = models.BooleanField(verbose_name='Activate', default=False)
    sale_status = models.BooleanField(verbose_name='Activate sale', default=False)

    ...

    def save(self, *args, **kwargs): # Overwrite save() to calculate and save the duration of a shift.
        temp_date = datetime(1,1,1,0,0,0)
        self.hours = datetime.combine(temp_date, self.end_time) - datetime.combine(temp_date, self.start_time)
        super(Shift, self).save(*args, **kwargs)

An admin creates shifts and assigns owners to the shifts. Once an owner is assigned, the owner can sell the shift, which will change sale_status=False to sale_status=True. Then other users can buy the shift, changing the owner of the shift to the buyer and the shift's sale_status to False. Ideally, these actions (selling and buying shifts) can be performed through the calendar, by clicking on a shift. That means the calendar has to display all the shifts whose activated=True.

I've been digging into this for a while now and decided to use FullCalendar. Going forward, I know I have to modify my views.py for an AJAX view and create a template for the calendar, but I am not sure how to do either. My template currently looks like this:

<head>
<link rel='stylesheet' href='fullcalendar/fullcalendar.css' />
<script src='lib/jquery.min.js'></script>
<script src='lib/moment.min.js'></script>
<script src='fullcalendar/fullcalendar.js'></script>
</head>

<div id="calendar"></div>
<script type='text/javascript'>
$(document).ready(function() {

    // page is now ready, initialize the calendar...

    $('#calendar').fullCalendar({
        // put your options and callbacks here
        events: "shifts/eventsFeed",
        weekends: false,
        editable: false,
    })

});
</script>

This is obviously wrong (does not use Django's template language, eventsFeed is not implemented, etc.) but I'm not sure how to go from here.

Any help, especially with snippets of code, will be greatly appreciated.

Thanks!

Edit: So I was able to get the calendar to load with following codes:

// in views.py
def view_shifts(request):
    """
    View for displaying activated shifts in a weekly calendar format.
    """

    activated_shifts = Shift.objects.filter(activated=True) # Get all the activated shifts.
    shifts = [] # place holder
    for shift in activated_shifts:
        temp = OrderedDict()
        temp['id'] = shift.id
        temp['title'] = shift.title
        temp['start'] = str(shift.start_date) + 'T' + str(shift.start_time)
        temp['end'] = str(shift.end_date) + 'T' + str(shift.end_time)
        shifts.append(temp)

    calendar_config_options = {'header': {
                                    'left': 'prev,next today',
                                    'center': 'title',
                                    'right': 'month,agendaWeek,agendaDay'
                                },
                               'defaultView': 'agendaWeek',
                               'editable': 'True', # View only.
                               'events': json.dumps(shifts),
                               'firstDay': 1 # Week starts on Monday.
                               }

    return render(request, 'shifts/full_calendar.html', {'calendar_config_options': calendar_config_options})

I also added the field title to my Shift. It is simply the string representation of self.owner. My template, called calendar_init.html, is as following:

<script type="text/javascript">
    $(document).ready(function() { // Page is ready.
        // Initialize the calendar.
        $('#calendar').fullCalendar({{ calendar_config_options }});
    });
</script>

Now, when the template is rendered, I get the following:

<!DOCTYPE html>
<head>

    <title>Shifts</title>

    ...

    <script type="text/javascript">
    $(document).ready(function() { // Page is ready.
        // Initialize the calendar.
        $('#calendar').fullCalendar({'firstDay': 1, 'header': {'right': 'month,agendaWeek,agendaDay', 'center': 'title', 'left': 'prev,next today'}, 'defaultView': 'agendaWeek', 'editable': True, 'events': '[{"id": 61, "title": "Unclaimed", "start": "2015-07-21T14:00:00", "end": "2015-07-21T16:00:00"}, {"id": 62, "title": "slee17", "start": "2015-07-21T12:00:00", "end": "2015-07-21T14:00:00"}]'});
    });
</script>

</head>

<body>
<div id="calendar"></div>

However, the calendar is still not loaded with shifts. I've tried using json.loads(json.dumps(shifts)) instead of json.dumps(shifts) and have also tried using the helper functions from http://robotfantastic.org/serializing-python-data-to-json-some-edge-cases.html. Neither have loaded the calendar with shifts. What am I doing wrong here? (The calendar is still being loaded, its configuration is as I have configured, but the calendar is empty.)

Also, two small questions: 1) when I say 'edtiable': True instead of 'editable': 'True', the page goes blank, with no errors. Why is this so? I've also tried doing 'weekends'='False', which still shows the calendar with weekends, so the calendar clearly isn't being configured right when it comes to booleans. I'm not sure why though, since other configuration settings (e.g. header, defaultView, and firstDay) all seemed to have worked fine. 2) I used OrderedDict() because I had a suspicion that the order matters when trying to load events to the calendar, but I'm not sure if this is true. Could I just use a regular Python dictionary?


回答1:


Here's a basic overview of what you need to do. Create a view that returns the JSON data as full calendar expects it. This is pretty simple to do. You can create a custom one by hand with JsonResponse or use Django Rest Framework. Unless you're creating a whole API, I'd go with using JsonResponse.

As for the format of the JsonResponse, you need to specify both start and title. You can find the other possible fields here in full calendar's docs.

Example:

from django.http import JsonResponse

def example(request):
    data = [
        {
            'title': 'event1',
            'start': '2010-01-01'
        },
        {
            'title': 'event2',
            'start': '2010-01-05',
            'end': '2010-01-07'
        }
    ]
    return JsonResponse(data, safe=False)


来源:https://stackoverflow.com/questions/31507308/using-fullcalendar-in-django

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!