在 Django 中使用 fullCalendar

Using fullCalendar in Django

这里发布的问题的一些跟进 (),但自从提出这个问题后,我决定采取不同的方法。正如你所知道的,我是一个新手,所以请放轻松。

我想要在我的 Django 应用程序中显示每周日历,以显示数据库中的班次。以下是 Shift 模型。

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)

管理员创建班次并将所有者分配给班次。分配所有者后,所有者可以出售班次,这会将 sale_status=False 更改为 sale_status=True。然后其他用户可以购买班次,将班次的owner改为买家,班次的sale_status改为False。理想情况下,这些操作(买卖班次)可以通过日历通过单击班次来执行。这意味着日历必须显示 activated=True.

的所有班次

我已经对此进行了一段时间的研究,并决定使用 FullCalendar。展望未来,我知道我必须为 AJAX 视图修改我的 views.py 并为日历创建一个模板,但我不知道该怎么做。我的模板目前看起来像这样:

<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>

这显然是错误的(没有使用 Django 的模板语言,没有实现 eventsFeed 等)但我不确定如何从这里开始。

任何帮助,尤其是代码片段方面的帮助,我们将不胜感激。

谢谢!

编辑:所以我能够使用以下代码加载日历:

// 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})

我还将字段 title 添加到我的 Shift。它只是 self.owner 的字符串表示形式。 我的模板名为 calendar_init.html,如下所示:

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

现在,呈现模板时,我得到以下信息:

<!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>

但是,日历仍未加载班次。我试过使用 json.loads(json.dumps(shifts)) 而不是 json.dumps(shifts),也试过使用 http://robotfantastic.org/serializing-python-data-to-json-some-edge-cases.html 中的辅助函数。两者都没有用轮班加载日历。我在这里做错了什么? (日历还在加载中,它的配置和我配置的一样,但是日历是空的。)

另外,两个小问题: 1) 当我说 'edtiable': True 而不是 'editable': 'True' 时,页面变为空白,没有任何错误。为什么会这样?我也试过做 'weekends'='False',它仍然显示带有周末的日历,所以当涉及到布尔值时,日历显然没有正确配置。我不确定为什么,因为其他配置设置(例如 headerdefaultViewfirstDay)似乎都运行良好。 2) 我使用 OrderedDict() 因为我怀疑在尝试将 events 加载到日历时顺序很重要,但我不确定这是否属实。我可以只使用普通的 Python 字典吗?

下面是您需要执行的操作的基本概述。创建一个 returns JSON 数据的视图,如完整日历所期望的那样。这很容易做到。您可以使用 JsonResponse 或使用 Django Rest Framework 手动创建一个自定义的。除非你要创建一个整体 API,否则我会使用 JsonResponse。

关于JsonResponse的格式,需要同时指定starttitle。您可以在此处的完整日历 docs.

中找到其他可能的字段

示例:

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)