基于Django的会议文档Web应用自定义提醒模块开发问询
自定义会议提醒模块实现方案(Django + PostgreSQL + Ubuntu)
嘿,我之前刚好给一个Django会议管理系统做过类似的提醒模块,给你一步步拆解实现思路:
一、数据库模型设计
首先得把用户的个性化提醒规则存起来,关联到对应的会议和用户。我们可以新建一个Reminder模型,支持两种提醒方式:提前N分钟提醒或者自定义绝对时间提醒,同时记录提醒类型和发送状态:
# your_app/models.py from django.db import models from django.contrib.auth.models import User from django.utils import timezone from .models import Meeting # 假设你的会议模型是Meeting class Reminder(models.Model): # 提醒方式选项(虽然不涉及发送,但先存类型) REMINDER_TYPES = ( ('sms', '短信'), ('email', '邮件'), ('in_app', '站内通知'), ) user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='meeting_reminders') meeting = models.ForeignKey(Meeting, on_delete=models.CASCADE, related_name='reminders') # 二选一:提前分钟数 或 绝对提醒时间 offset_minutes = models.IntegerField(null=True, blank=True, help_text="提前多少分钟提醒,例如60=提前1小时") absolute_time = models.DateTimeField(null=True, blank=True, help_text="自定义具体提醒时间(如2018-04-25 19:30)") reminder_type = models.CharField(max_length=20, choices=REMINDER_TYPES) is_sent = models.BooleanField(default=False, help_text="是否已发送提醒") created_at = models.DateTimeField(auto_now_add=True) def get_trigger_time(self): """计算实际触发提醒的时间""" if self.absolute_time: return self.absolute_time elif self.offset_minutes: return self.meeting.start_time - timezone.timedelta(minutes=self.offset_minutes) return None
别忘了执行迁移:
python manage.py makemigrations python manage.py migrate
二、定时任务触发提醒
因为提醒需要在指定时间自动触发,我们用Celery来处理定时任务(Ubuntu环境下非常适合),搭配Redis做消息队列。
1. 安装依赖
pip install celery redis
2. 配置Celery
在项目根目录新建celery.py:
# project_name/celery.py import os from celery import Celery os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'project_name.settings') app = Celery('project_name') app.config_from_object('django.conf:settings', namespace='CELERY') app.autodiscover_tasks()
在project_name/__init__.py里添加:
from .celery import app as celery_app __all__ = ('celery_app',)
3. 编写提醒检查任务
在你的app下新建tasks.py:
# your_app/tasks.py from celery import shared_task from django.utils import timezone from django.db.models import F, Q from .models import Reminder from .utils import send_reminder # 你自己实现的发送逻辑(无需关心具体发送方式) @shared_task def check_and_trigger_reminders(): """每隔一段时间检查需要触发的提醒""" now = timezone.now() # 筛选出未发送且到了触发时间的提醒 pending_reminders = Reminder.objects.filter( is_sent=False, Q(absolute_time__lte=now) | Q( offset_minutes__isnull=False, meeting__start_time__lte=now + timezone.timedelta(minutes=F('offset_minutes')) ) ) for reminder in pending_reminders: # 调用发送函数(你只需实现这个函数的逻辑,比如调用短信API/发邮件等) send_reminder(reminder) # 标记为已发送 reminder.is_sent = True reminder.save()
4. 设置定时任务频率
在settings.py里配置Celery Beat(定时调度):
# settings.py CELERY_BROKER_URL = 'redis://localhost:6379/0' CELERY_RESULT_BACKEND = 'redis://localhost:6379/0' CELERY_TIMEZONE = 'Asia/Shanghai' # 改成你的时区 CELERY_BEAT_SCHEDULE = { 'check-reminders-every-5-minutes': { 'task': 'your_app.tasks.check_and_trigger_reminders', 'schedule': 300.0, # 每5分钟执行一次(单位:秒) }, }
三、用户界面:设置提醒的表单
给会议详情页添加一个表单,让用户可以设置个性化提醒:
1. 编写表单类
# your_app/forms.py from django import forms from .models import Reminder class ReminderForm(forms.ModelForm): class Meta: model = Reminder fields = ['offset_minutes', 'absolute_time', 'reminder_type'] widgets = { 'absolute_time': forms.DateTimeInput(attrs={'type': 'datetime-local', 'class': 'form-control'}), 'offset_minutes': forms.NumberInput(attrs={'class': 'form-control', 'placeholder': '输入提前分钟数'}), 'reminder_type': forms.Select(attrs={'class': 'form-control'}), } def clean(self): """验证必须选一种提醒方式""" cleaned_data = super().clean() offset = cleaned_data.get('offset_minutes') absolute_time = cleaned_data.get('absolute_time') if not offset and not absolute_time: raise forms.ValidationError("请选择提前提醒时间或自定义提醒时间!") return cleaned_data
2. 视图集成表单
在会议详情视图里处理表单提交:
# your_app/views.py from django.views.generic import DetailView from django.contrib import messages from .models import Meeting from .forms import ReminderForm class MeetingDetailView(DetailView): model = Meeting template_name = 'meeting/detail.html' def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # 把表单传入模板 context['reminder_form'] = ReminderForm() return context def post(self, request, *args, **kwargs): self.object = self.get_object() form = ReminderForm(request.POST) if form.is_valid(): reminder = form.save(commit=False) reminder.user = request.user reminder.meeting = self.object reminder.save() messages.success(request, "提醒设置成功!") return self.render_to_response(self.get_context_data(reminder_form=form))
3. 模板渲染表单
在会议详情模板里添加表单:
<!-- templates/meeting/detail.html --> <h3>设置会议提醒</h3> <form method="post" class="mt-3"> {% csrf_token %} <div class="form-group"> {{ reminder_form.offset_minutes.label_tag }} {{ reminder_form.offset_minutes }} <small class="form-text text-muted">例如:60 代表提前1小时提醒</small> </div> <div class="form-group"> {{ reminder_form.absolute_time.label_tag }} {{ reminder_form.absolute_time }} <small class="form-text text-muted">或自定义具体提醒时间</small> </div> <div class="form-group"> {{ reminder_form.reminder_type.label_tag }} {{ reminder_form.reminder_type }} </div> <button type="submit" class="btn btn-primary">保存提醒</button> </form>
四、Ubuntu部署注意事项
因为你用Apache部署Django,Celery需要单独作为后台服务运行,我们用systemd配置:
- 创建
/etc/systemd/system/celery.service文件:
[Unit] Description=Celery Worker & Beat Service After=network.target redis-server.service [Service] User=www-data Group=www-data WorkingDirectory=/path/to/your/django/project Environment="PATH=/path/to/your/virtualenv/bin" ExecStart=/path/to/your/virtualenv/bin/celery -A project_name worker --loglevel=info -B [Install] WantedBy=multi-user.target
- 启动并启用服务:
sudo systemctl daemon-reload sudo systemctl start celery sudo systemctl enable celery
这样Celery就会随系统启动,持续检查并触发提醒。
关键注意点
- 时区问题:确保Django的
settings.py里USE_TZ = True,并设置正确的TIME_ZONE,避免时间计算错误。 - 重复提醒:模型里的
is_sent字段一定要标记已发送,避免重复触发。 - 容错处理:可以给Celery任务添加重试机制,避免因发送失败导致提醒丢失。
内容的提问来源于stack exchange,提问作者Adrian Chrostowski
相关产品推荐
相关产品推荐

