mirror of
https://github.com/ansible/awx.git
synced 2026-04-17 16:00:18 -02:30
Notification serializers, views, and tasks
* Implement concrete Notification model for notification runs * Implement NotificationTemplate and Notification serializers and views * Implement ancillary views * Implement NotificationTemplate trigger m2m fields on all job templates via a fields mixin * Link NotificationTemplates with an org * Link notifications with the activity stream * Implement Notification celery tasks * Extend Backend field parameters to identify sender and receiver as parameters needed by the message and not the backend itself * Updates to backends to better fit the django email backend model as it relates to Messages * Implement success job chain task + notifications * Implement notifications in error job chain task
This commit is contained in:
@@ -457,6 +457,8 @@ class BaseSerializer(serializers.ModelSerializer):
|
||||
ret.pop(parent_key, None)
|
||||
return ret
|
||||
|
||||
class EmptySerializer(serializers.Serializer):
|
||||
pass
|
||||
|
||||
class BaseFactSerializer(DocumentSerializer):
|
||||
|
||||
@@ -765,7 +767,11 @@ class OrganizationSerializer(BaseSerializer):
|
||||
users = reverse('api:organization_users_list', args=(obj.pk,)),
|
||||
admins = reverse('api:organization_admins_list', args=(obj.pk,)),
|
||||
teams = reverse('api:organization_teams_list', args=(obj.pk,)),
|
||||
activity_stream = reverse('api:organization_activity_stream_list', args=(obj.pk,))
|
||||
activity_stream = reverse('api:organization_activity_stream_list', args=(obj.pk,)),
|
||||
notifiers = reverse('api:organization_notifiers_list', args=(obj.pk,)),
|
||||
notifiers_any = reverse('api:organization_notifications_any_list', args=(obj.pk,)),
|
||||
notifiers_success = reverse('api:organization_notifications_success_list', args=(obj.pk,)),
|
||||
notifiers_error = reverse('api:organization_notifications_error_list', args=(obj.pk,)),
|
||||
))
|
||||
return res
|
||||
|
||||
@@ -845,6 +851,9 @@ class ProjectSerializer(UnifiedJobTemplateSerializer, ProjectOptionsSerializer):
|
||||
project_updates = reverse('api:project_updates_list', args=(obj.pk,)),
|
||||
schedules = reverse('api:project_schedules_list', args=(obj.pk,)),
|
||||
activity_stream = reverse('api:project_activity_stream_list', args=(obj.pk,)),
|
||||
notifiers_any = reverse('api:project_notifications_any_list', args=(obj.pk,)),
|
||||
notifiers_success = reverse('api:project_notifications_success_list', args=(obj.pk,)),
|
||||
notifiers_error = reverse('api:project_notifications_error_list', args=(obj.pk,)),
|
||||
))
|
||||
# Backwards compatibility.
|
||||
if obj.current_update:
|
||||
@@ -888,6 +897,7 @@ class ProjectUpdateSerializer(UnifiedJobSerializer, ProjectOptionsSerializer):
|
||||
res.update(dict(
|
||||
project = reverse('api:project_detail', args=(obj.project.pk,)),
|
||||
cancel = reverse('api:project_update_cancel', args=(obj.pk,)),
|
||||
notifications = reverse('api:project_update_notifications_list', args=(obj.pk,)),
|
||||
))
|
||||
return res
|
||||
|
||||
@@ -1288,6 +1298,9 @@ class InventorySourceSerializer(UnifiedJobTemplateSerializer, InventorySourceOpt
|
||||
activity_stream = reverse('api:inventory_activity_stream_list', args=(obj.pk,)),
|
||||
hosts = reverse('api:inventory_source_hosts_list', args=(obj.pk,)),
|
||||
groups = reverse('api:inventory_source_groups_list', args=(obj.pk,)),
|
||||
notifiers_any = reverse('api:inventory_source_notifications_any_list', args=(obj.pk,)),
|
||||
notifiers_success = reverse('api:inventory_source_notifications_success_list', args=(obj.pk,)),
|
||||
notifiers_error = reverse('api:inventory_source_notifications_error_list', args=(obj.pk,)),
|
||||
))
|
||||
if obj.inventory and obj.inventory.active:
|
||||
res['inventory'] = reverse('api:inventory_detail', args=(obj.inventory.pk,))
|
||||
@@ -1332,6 +1345,7 @@ class InventoryUpdateSerializer(UnifiedJobSerializer, InventorySourceOptionsSeri
|
||||
res.update(dict(
|
||||
inventory_source = reverse('api:inventory_source_detail', args=(obj.inventory_source.pk,)),
|
||||
cancel = reverse('api:inventory_update_cancel', args=(obj.pk,)),
|
||||
notifications = reverse('api:inventory_update_notifications_list', args=(obj.pk,)),
|
||||
))
|
||||
return res
|
||||
|
||||
@@ -1550,6 +1564,9 @@ class JobTemplateSerializer(UnifiedJobTemplateSerializer, JobOptionsSerializer):
|
||||
schedules = reverse('api:job_template_schedules_list', args=(obj.pk,)),
|
||||
activity_stream = reverse('api:job_template_activity_stream_list', args=(obj.pk,)),
|
||||
launch = reverse('api:job_template_launch', args=(obj.pk,)),
|
||||
notifiers_any = reverse('api:job_template_notifications_any_list', args=(obj.pk,)),
|
||||
notifiers_success = reverse('api:job_template_notifications_success_list', args=(obj.pk,)),
|
||||
notifiers_error = reverse('api:job_template_notifications_error_list', args=(obj.pk,)),
|
||||
))
|
||||
if obj.host_config_key:
|
||||
res['callback'] = reverse('api:job_template_callback', args=(obj.pk,))
|
||||
@@ -1604,6 +1621,7 @@ class JobSerializer(UnifiedJobSerializer, JobOptionsSerializer):
|
||||
job_tasks = reverse('api:job_job_tasks_list', args=(obj.pk,)),
|
||||
job_host_summaries = reverse('api:job_job_host_summaries_list', args=(obj.pk,)),
|
||||
activity_stream = reverse('api:job_activity_stream_list', args=(obj.pk,)),
|
||||
notifications = reverse('api:job_notifications_list', args=(obj.pk,)),
|
||||
))
|
||||
if obj.job_template and obj.job_template.active:
|
||||
res['job_template'] = reverse('api:job_template_detail',
|
||||
@@ -2039,7 +2057,15 @@ class NotificationTemplateSerializer(BaseSerializer):
|
||||
|
||||
class Meta:
|
||||
model = NotificationTemplate
|
||||
fields = ('*', 'notification_type', 'notification_configuration')
|
||||
fields = ('*', 'organization', 'notification_type', 'notification_configuration')
|
||||
|
||||
def get_related(self, obj):
|
||||
res = super(NotificationTemplateSerializer, self).get_related(obj)
|
||||
res.update(dict(
|
||||
test = reverse('api:notification_template_test', args=(obj.pk,)),
|
||||
notifications = reverse('api:notification_template_notification_list', args=(obj.pk,)),
|
||||
))
|
||||
return res
|
||||
|
||||
def validate(self, attrs):
|
||||
notification_class = NotificationTemplate.CLASS_FOR_NOTIFICATION_TYPE[attrs['notification_type']]
|
||||
@@ -2047,10 +2073,25 @@ class NotificationTemplateSerializer(BaseSerializer):
|
||||
for field in notification_class.init_parameters:
|
||||
if field not in attrs['notification_configuration']:
|
||||
missing_fields.append(field)
|
||||
# TODO: Type checks
|
||||
if missing_fields:
|
||||
raise serializers.ValidationError("Missing required fields for Notification Configuration: {}".format(missing_fields))
|
||||
return attrs
|
||||
|
||||
class NotificationSerializer(BaseSerializer):
|
||||
|
||||
class Meta:
|
||||
model = Notification
|
||||
fields = ('*', '-name', '-description', 'notifier', 'error', 'status', 'notifications_sent',
|
||||
'notification_type', 'recipients', 'subject', 'body')
|
||||
|
||||
def get_related(self, obj):
|
||||
res = super(NotificationSerializer, self).get_related(obj)
|
||||
res.update(dict(
|
||||
notification_template = reverse('api:notification_template_detail', args=(obj.notifier.pk,)),
|
||||
))
|
||||
return res
|
||||
|
||||
class ScheduleSerializer(BaseSerializer):
|
||||
|
||||
class Meta:
|
||||
|
||||
@@ -20,6 +20,10 @@ organization_urls = patterns('awx.api.views',
|
||||
url(r'^(?P<pk>[0-9]+)/projects/$', 'organization_projects_list'),
|
||||
url(r'^(?P<pk>[0-9]+)/teams/$', 'organization_teams_list'),
|
||||
url(r'^(?P<pk>[0-9]+)/activity_stream/$', 'organization_activity_stream_list'),
|
||||
url(r'^(?P<pk>[0-9]+)/notifiers/$', 'organization_notifiers_list'),
|
||||
url(r'^(?P<pk>[0-9]+)/notifications_any/$', 'organization_notifications_any_list'),
|
||||
url(r'^(?P<pk>[0-9]+)/notifications_error/$', 'organization_notifications_error_list'),
|
||||
url(r'^(?P<pk>[0-9]+)/notifications_success/$', 'organization_notifications_success_list'),
|
||||
)
|
||||
|
||||
user_urls = patterns('awx.api.views',
|
||||
@@ -44,12 +48,16 @@ project_urls = patterns('awx.api.views',
|
||||
url(r'^(?P<pk>[0-9]+)/project_updates/$', 'project_updates_list'),
|
||||
url(r'^(?P<pk>[0-9]+)/activity_stream/$', 'project_activity_stream_list'),
|
||||
url(r'^(?P<pk>[0-9]+)/schedules/$', 'project_schedules_list'),
|
||||
url(r'^(?P<pk>[0-9]+)/notifications_any/$', 'project_notifications_any_list'),
|
||||
url(r'^(?P<pk>[0-9]+)/notifications_error/$', 'project_notifications_error_list'),
|
||||
url(r'^(?P<pk>[0-9]+)/notifications_success/$', 'project_notifications_success_list'),
|
||||
)
|
||||
|
||||
project_update_urls = patterns('awx.api.views',
|
||||
url(r'^(?P<pk>[0-9]+)/$', 'project_update_detail'),
|
||||
url(r'^(?P<pk>[0-9]+)/cancel/$', 'project_update_cancel'),
|
||||
url(r'^(?P<pk>[0-9]+)/stdout/$', 'project_update_stdout'),
|
||||
url(r'^(?P<pk>[0-9]+)/notifications/$', 'project_update_notifications_list'),
|
||||
)
|
||||
|
||||
team_urls = patterns('awx.api.views',
|
||||
@@ -120,12 +128,16 @@ inventory_source_urls = patterns('awx.api.views',
|
||||
url(r'^(?P<pk>[0-9]+)/schedules/$', 'inventory_source_schedules_list'),
|
||||
url(r'^(?P<pk>[0-9]+)/groups/$', 'inventory_source_groups_list'),
|
||||
url(r'^(?P<pk>[0-9]+)/hosts/$', 'inventory_source_hosts_list'),
|
||||
url(r'^(?P<pk>[0-9]+)/notifications_any/$', 'inventory_source_notifications_any_list'),
|
||||
url(r'^(?P<pk>[0-9]+)/notifications_error/$', 'inventory_source_notifications_error_list'),
|
||||
url(r'^(?P<pk>[0-9]+)/notifications_success/$', 'inventory_source_notifications_success_list'),
|
||||
)
|
||||
|
||||
inventory_update_urls = patterns('awx.api.views',
|
||||
url(r'^(?P<pk>[0-9]+)/$', 'inventory_update_detail'),
|
||||
url(r'^(?P<pk>[0-9]+)/cancel/$', 'inventory_update_cancel'),
|
||||
url(r'^(?P<pk>[0-9]+)/stdout/$', 'inventory_update_stdout'),
|
||||
url(r'^(?P<pk>[0-9]+)/notifications/$', 'inventory_update_notifications_list'),
|
||||
)
|
||||
|
||||
inventory_script_urls = patterns('awx.api.views',
|
||||
@@ -153,6 +165,9 @@ job_template_urls = patterns('awx.api.views',
|
||||
url(r'^(?P<pk>[0-9]+)/schedules/$', 'job_template_schedules_list'),
|
||||
url(r'^(?P<pk>[0-9]+)/survey_spec/$', 'job_template_survey_spec'),
|
||||
url(r'^(?P<pk>[0-9]+)/activity_stream/$', 'job_template_activity_stream_list'),
|
||||
url(r'^(?P<pk>[0-9]+)/notifications_any/$', 'job_template_notifications_any_list'),
|
||||
url(r'^(?P<pk>[0-9]+)/notifications_error/$', 'job_template_notifications_error_list'),
|
||||
url(r'^(?P<pk>[0-9]+)/notifications_success/$', 'job_template_notifications_success_list'),
|
||||
)
|
||||
|
||||
job_urls = patterns('awx.api.views',
|
||||
@@ -167,6 +182,7 @@ job_urls = patterns('awx.api.views',
|
||||
url(r'^(?P<pk>[0-9]+)/job_tasks/$', 'job_job_tasks_list'),
|
||||
url(r'^(?P<pk>[0-9]+)/activity_stream/$', 'job_activity_stream_list'),
|
||||
url(r'^(?P<pk>[0-9]+)/stdout/$', 'job_stdout'),
|
||||
url(r'^(?P<pk>[0-9]+)/notifications/$', 'job_notifications_list'),
|
||||
)
|
||||
|
||||
job_host_summary_urls = patterns('awx.api.views',
|
||||
@@ -212,6 +228,13 @@ system_job_urls = patterns('awx.api.views',
|
||||
notification_template_urls = patterns('awx.api.views',
|
||||
url(r'^$', 'notification_template_list'),
|
||||
url(r'^(?P<pk>[0-9]+)/$', 'notification_template_detail'),
|
||||
url(r'^(?P<pk>[0-9]+)/test/$', 'notification_template_test'),
|
||||
url(r'^(?P<pk>[0-9]+)/notifications/$', 'notification_template_notification_list'),
|
||||
)
|
||||
|
||||
notification_urls = patterns('awx.api.views',
|
||||
url(r'^$', 'notification_list'),
|
||||
url(r'^(?P<pk>[0-9]+)/$', 'notification_detail'),
|
||||
)
|
||||
|
||||
schedule_urls = patterns('awx.api.views',
|
||||
@@ -263,6 +286,7 @@ v1_urls = patterns('awx.api.views',
|
||||
url(r'^system_job_templates/', include(system_job_template_urls)),
|
||||
url(r'^system_jobs/', include(system_job_urls)),
|
||||
url(r'^notification_templates/', include(notification_template_urls)),
|
||||
url(r'^notifications/', include(notification_urls)),
|
||||
url(r'^unified_job_templates/$', 'unified_job_template_list'),
|
||||
url(r'^unified_jobs/$', 'unified_job_list'),
|
||||
url(r'^activity_stream/', include(activity_stream_urls)),
|
||||
|
||||
157
awx/api/views.py
157
awx/api/views.py
@@ -56,7 +56,7 @@ from social.backends.utils import load_backends
|
||||
|
||||
# AWX
|
||||
from awx.main.task_engine import TaskSerializer, TASK_FILE, TEMPORARY_TASK_FILE
|
||||
from awx.main.tasks import mongodb_control
|
||||
from awx.main.tasks import mongodb_control, send_notifications
|
||||
from awx.main.access import get_user_queryset
|
||||
from awx.main.ha import is_ha_environment
|
||||
from awx.api.authentication import TaskAuthentication, TokenGetAuthentication
|
||||
@@ -136,6 +136,7 @@ class ApiV1RootView(APIView):
|
||||
data['system_jobs'] = reverse('api:system_job_list')
|
||||
data['schedules'] = reverse('api:schedule_list')
|
||||
data['notification_templates'] = reverse('api:notification_template_list')
|
||||
data['notifications'] = reverse('api:notification_list')
|
||||
data['unified_job_templates'] = reverse('api:unified_job_template_list')
|
||||
data['unified_jobs'] = reverse('api:unified_job_list')
|
||||
data['activity_stream'] = reverse('api:activity_stream_list')
|
||||
@@ -684,6 +685,35 @@ class OrganizationActivityStreamList(SubListAPIView):
|
||||
# Okay, let it through.
|
||||
return super(type(self), self).get(request, *args, **kwargs)
|
||||
|
||||
class OrganizationNotifiersList(SubListCreateAttachDetachAPIView):
|
||||
|
||||
model = NotificationTemplate
|
||||
serializer_class = NotificationTemplateSerializer
|
||||
parent_model = Organization
|
||||
relationship = 'notification_templates'
|
||||
parent_key = 'organization'
|
||||
|
||||
class OrganizationNotificationsAnyList(SubListCreateAttachDetachAPIView):
|
||||
|
||||
model = NotificationTemplate
|
||||
serializer_class = NotificationTemplateSerializer
|
||||
parent_model = Organization
|
||||
relationship = 'notification_any'
|
||||
|
||||
class OrganizationNotificationsErrorList(SubListCreateAttachDetachAPIView):
|
||||
|
||||
model = NotificationTemplate
|
||||
serializer_class = NotificationTemplateSerializer
|
||||
parent_model = Organization
|
||||
relationship = 'notification_erros'
|
||||
|
||||
class OrganizationNotificationsSuccessList(SubListCreateAttachDetachAPIView):
|
||||
|
||||
model = NotificationTemplate
|
||||
serializer_class = NotificationTemplateSerializer
|
||||
parent_model = Organization
|
||||
relationship = 'notification_success'
|
||||
|
||||
class TeamList(ListCreateAPIView):
|
||||
|
||||
model = Team
|
||||
@@ -849,6 +879,26 @@ class ProjectActivityStreamList(SubListAPIView):
|
||||
return qs.filter(project=parent)
|
||||
return qs.filter(Q(project=parent) | Q(credential__in=parent.credential))
|
||||
|
||||
class ProjectNotificationsAnyList(SubListCreateAttachDetachAPIView):
|
||||
|
||||
model = NotificationTemplate
|
||||
serializer_class = NotificationTemplateSerializer
|
||||
parent_model = Project
|
||||
relationship = 'notification_any'
|
||||
|
||||
class ProjectNotificationsErrorList(SubListCreateAttachDetachAPIView):
|
||||
|
||||
model = NotificationTemplate
|
||||
serializer_class = NotificationTemplateSerializer
|
||||
parent_model = Project
|
||||
relationship = 'notification_errors'
|
||||
|
||||
class ProjectNotificationsSuccessList(SubListCreateAttachDetachAPIView):
|
||||
|
||||
model = NotificationTemplate
|
||||
serializer_class = NotificationTemplateSerializer
|
||||
parent_model = Project
|
||||
relationship = 'notification_success'
|
||||
|
||||
class ProjectUpdatesList(SubListAPIView):
|
||||
|
||||
@@ -899,6 +949,12 @@ class ProjectUpdateCancel(RetrieveAPIView):
|
||||
else:
|
||||
return self.http_method_not_allowed(request, *args, **kwargs)
|
||||
|
||||
class ProjectUpdateNotificationsList(SubListAPIView):
|
||||
|
||||
model = Notification
|
||||
serializer_class = NotificationSerializer
|
||||
parent_model = Project
|
||||
relationship = 'notifications'
|
||||
|
||||
class UserList(ListCreateAPIView):
|
||||
|
||||
@@ -1725,6 +1781,27 @@ class InventorySourceActivityStreamList(SubListAPIView):
|
||||
# Okay, let it through.
|
||||
return super(type(self), self).get(request, *args, **kwargs)
|
||||
|
||||
class InventorySourceNotificationsAnyList(SubListCreateAttachDetachAPIView):
|
||||
|
||||
model = NotificationTemplate
|
||||
serializer_class = NotificationTemplateSerializer
|
||||
parent_model = InventorySource
|
||||
relationship = 'notification_any'
|
||||
|
||||
class InventorySourceNotificationsErrorList(SubListCreateAttachDetachAPIView):
|
||||
|
||||
model = NotificationTemplate
|
||||
serializer_class = NotificationTemplateSerializer
|
||||
parent_model = InventorySource
|
||||
relationship = 'notification_errors'
|
||||
|
||||
class InventorySourceNotificationsSuccessList(SubListCreateAttachDetachAPIView):
|
||||
|
||||
model = NotificationTemplate
|
||||
serializer_class = NotificationTemplateSerializer
|
||||
parent_model = InventorySource
|
||||
relationship = 'notification_success'
|
||||
|
||||
class InventorySourceHostsList(SubListAPIView):
|
||||
|
||||
model = Host
|
||||
@@ -1789,6 +1866,13 @@ class InventoryUpdateCancel(RetrieveAPIView):
|
||||
else:
|
||||
return self.http_method_not_allowed(request, *args, **kwargs)
|
||||
|
||||
class InventoryUpdateNotificationsList(SubListAPIView):
|
||||
|
||||
model = Notification
|
||||
serializer_class = NotificationSerializer
|
||||
parent_model = InventoryUpdate
|
||||
relationship = 'notifications'
|
||||
|
||||
class JobTemplateList(ListCreateAPIView):
|
||||
|
||||
model = JobTemplate
|
||||
@@ -1943,6 +2027,27 @@ class JobTemplateActivityStreamList(SubListAPIView):
|
||||
# Okay, let it through.
|
||||
return super(type(self), self).get(request, *args, **kwargs)
|
||||
|
||||
class JobTemplateNotificationsAnyList(SubListCreateAttachDetachAPIView):
|
||||
|
||||
model = NotificationTemplate
|
||||
serializer_class = NotificationTemplateSerializer
|
||||
parent_model = JobTemplate
|
||||
relationship = 'notification_any'
|
||||
|
||||
class JobTemplateNotificationsErrorList(SubListCreateAttachDetachAPIView):
|
||||
|
||||
model = NotificationTemplate
|
||||
serializer_class = NotificationTemplateSerializer
|
||||
parent_model = JobTemplate
|
||||
relationship = 'notification_errors'
|
||||
|
||||
class JobTemplateNotificationsSuccessList(SubListCreateAttachDetachAPIView):
|
||||
|
||||
model = NotificationTemplate
|
||||
serializer_class = NotificationTemplateSerializer
|
||||
parent_model = JobTemplate
|
||||
relationship = 'notification_success'
|
||||
|
||||
class JobTemplateCallback(GenericAPIView):
|
||||
|
||||
model = JobTemplate
|
||||
@@ -2129,7 +2234,7 @@ class SystemJobTemplateDetail(RetrieveAPIView):
|
||||
class SystemJobTemplateLaunch(GenericAPIView):
|
||||
|
||||
model = SystemJobTemplate
|
||||
# FIXME: Add serializer class to define fields in OPTIONS request!
|
||||
serializer_class = EmptySerializer
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
return Response({})
|
||||
@@ -2276,6 +2381,13 @@ class JobRelaunch(RetrieveAPIView, GenericAPIView):
|
||||
headers = {'Location': new_job.get_absolute_url()}
|
||||
return Response(data, status=status.HTTP_201_CREATED, headers=headers)
|
||||
|
||||
class JobNotificationsList(SubListAPIView):
|
||||
|
||||
model = Notification
|
||||
serializer_class = NotificationSerializer
|
||||
parent_model = Job
|
||||
relationship = 'notifications'
|
||||
|
||||
class BaseJobHostSummariesList(SubListAPIView):
|
||||
|
||||
model = JobHostSummary
|
||||
@@ -2926,12 +3038,51 @@ class NotificationTemplateList(ListCreateAPIView):
|
||||
serializer_class = NotificationTemplateSerializer
|
||||
new_in_300 = True
|
||||
|
||||
class NotificationTemplateDetail(RetrieveDestroyAPIView):
|
||||
class NotificationTemplateDetail(RetrieveUpdateDestroyAPIView):
|
||||
|
||||
model = NotificationTemplate
|
||||
serializer_class = NotificationTemplateSerializer
|
||||
new_in_300 = True
|
||||
|
||||
class NotificationTemplateTest(GenericAPIView):
|
||||
|
||||
view_name = 'Notification Template Test'
|
||||
model = NotificationTemplate
|
||||
serializer_class = EmptySerializer
|
||||
new_in_300 = True
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
obj = self.get_object()
|
||||
notification = obj.generate_notification("Tower Notification Test", "Ansible Tower Test Notification")
|
||||
if not notification:
|
||||
return Response({}, status=status.HTTP_400_BAD_REQUEST)
|
||||
else:
|
||||
send_notifications.delay([notification.id])
|
||||
headers = {'Location': notification.get_absolute_url()}
|
||||
return Response({"notification": notification.id},
|
||||
headers=headers,
|
||||
status=status.HTTP_202_ACCEPTED)
|
||||
|
||||
class NotificationTemplateNotificationList(SubListAPIView):
|
||||
|
||||
model = Notification
|
||||
serializer_class = NotificationSerializer
|
||||
parent_model = NotificationTemplate
|
||||
relationship = 'notifications'
|
||||
parent_key = 'notifier'
|
||||
|
||||
class NotificationList(ListAPIView):
|
||||
|
||||
model = Notification
|
||||
serializer_class = NotificationSerializer
|
||||
new_in_300 = True
|
||||
|
||||
class NotificationDetail(RetrieveAPIView):
|
||||
|
||||
model = NotificationTemplate
|
||||
serializer_class = NotificationSerializer
|
||||
new_in_300 = True
|
||||
|
||||
class ActivityStreamList(SimpleListAPIView):
|
||||
|
||||
model = ActivityStream
|
||||
|
||||
Reference in New Issue
Block a user