diff options
author | 2019-01-27 12:31:23 +0100 | |
---|---|---|
committer | 2019-01-27 12:31:23 +0100 | |
commit | 2b2c81ad4a54d94a69bb761da968d6eb2dc1c9d3 (patch) | |
tree | c4899f7a42097585cc7a8142383f97a5e1abbc3e | |
parent | Add an API endpoint for reminders. (diff) |
Implement a simple nominations API.
-rw-r--r-- | api/migrations/0031_nomination.py | 26 | ||||
-rw-r--r-- | api/models.py | 29 | ||||
-rw-r--r-- | api/serializers.py | 21 | ||||
-rw-r--r-- | api/urls.py | 15 | ||||
-rw-r--r-- | api/viewsets.py | 40 |
5 files changed, 111 insertions, 20 deletions
diff --git a/api/migrations/0031_nomination.py b/api/migrations/0031_nomination.py new file mode 100644 index 00000000..b739d5cb --- /dev/null +++ b/api/migrations/0031_nomination.py @@ -0,0 +1,26 @@ +# Generated by Django 2.1.5 on 2019-01-27 11:01 + +import api.models +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0030_reminder'), + ] + + operations = [ + migrations.CreateModel( + name='Nomination', + fields=[ + ('active', models.BooleanField(default=True, help_text='Whether this nomination is still relevant.')), + ('reason', models.TextField(help_text='Why this user was nominated.')), + ('user', models.OneToOneField(help_text='The nominated user.', on_delete=django.db.models.deletion.CASCADE, primary_key=True, related_name='nomination', serialize=False, to='api.User')), + ('inserted_at', models.DateTimeField(auto_now_add=True, help_text='The creation date of this nomination.')), + ('author', models.ForeignKey(help_text='The staff member that nominated this user.', on_delete=django.db.models.deletion.CASCADE, related_name='nomination_set', to='api.User')), + ], + bases=(api.models.ModelReprMixin, models.Model), + ), + ] diff --git a/api/models.py b/api/models.py index 5ca274ce..fa68f31c 100644 --- a/api/models.py +++ b/api/models.py @@ -408,3 +408,32 @@ class Reminder(ModelReprMixin, models.Model): def __str__(self): return f"{self.content} on {self.expiration} by {self.author}" + + +class Nomination(ModelReprMixin, models.Model): + """A helper nomination created by staff.""" + + active = models.BooleanField( + default=True, + help_text="Whether this nomination is still relevant." + ) + author = models.ForeignKey( + User, + on_delete=models.CASCADE, + help_text="The staff member that nominated this user.", + related_name='nomination_set' + ) + reason = models.TextField( + help_text="Why this user was nominated." + ) + user = models.OneToOneField( + User, + on_delete=models.CASCADE, + help_text="The nominated user.", + primary_key=True, + related_name='nomination' + ) + inserted_at = models.DateTimeField( + auto_now_add=True, + help_text="The creation date of this nomination." + ) diff --git a/api/serializers.py b/api/serializers.py index fca8008f..97c4a60c 100644 --- a/api/serializers.py +++ b/api/serializers.py @@ -1,14 +1,15 @@ from rest_framework.serializers import ModelSerializer, PrimaryKeyRelatedField, ValidationError +from rest_framework.validators import UniqueValidator from rest_framework_bulk import BulkSerializerMixin from .models import ( DeletedMessage, DocumentationLink, Infraction, MessageDeletionContext, - OffTopicChannelName, Reminder, - Role, SnakeFact, - SnakeIdiom, SnakeName, - SpecialSnake, Tag, - User + Nomination, OffTopicChannelName, + Reminder, Role, + SnakeFact, SnakeIdiom, + SnakeName, SpecialSnake, + Tag, User ) @@ -154,3 +155,13 @@ class UserSerializer(BulkSerializerMixin, ModelSerializer): model = User fields = ('id', 'avatar_hash', 'name', 'discriminator', 'roles', 'in_guild') depth = 1 + + +class NominationSerializer(ModelSerializer): + author = PrimaryKeyRelatedField(queryset=User.objects.all()) + user = PrimaryKeyRelatedField(queryset=User.objects.all()) + + class Meta: + model = Nomination + fields = ('active', 'author', 'reason', 'user', 'inserted_at') + depth = 1 diff --git a/api/urls.py b/api/urls.py index c8548df1..5db89e67 100644 --- a/api/urls.py +++ b/api/urls.py @@ -4,11 +4,12 @@ from rest_framework.routers import DefaultRouter from .views import HealthcheckView, RulesView from .viewsets import ( DeletedMessageViewSet, DocumentationLinkViewSet, - InfractionViewSet, OffTopicChannelNameViewSet, - ReminderViewSet, RoleViewSet, - SnakeFactViewSet, SnakeIdiomViewSet, - SnakeNameViewSet, SpecialSnakeViewSet, - TagViewSet, UserViewSet + InfractionViewSet, NominationViewSet, + OffTopicChannelNameViewSet, ReminderViewSet, + RoleViewSet, SnakeFactViewSet, + SnakeIdiomViewSet, SnakeNameViewSet, + SpecialSnakeViewSet, TagViewSet, + UserViewSet ) @@ -27,6 +28,10 @@ bot_router.register( InfractionViewSet ) bot_router.register( + 'nominations', + NominationViewSet +) +bot_router.register( 'off-topic-channel-names', OffTopicChannelNameViewSet, base_name='offtopicchannelname' diff --git a/api/viewsets.py b/api/viewsets.py index 83945fe8..7ef1ba98 100644 --- a/api/viewsets.py +++ b/api/viewsets.py @@ -14,20 +14,21 @@ from rest_framework_bulk import BulkCreateModelMixin from .models import ( DocumentationLink, Infraction, - MessageDeletionContext, OffTopicChannelName, - Reminder, Role, - SnakeFact, SnakeIdiom, - SnakeName, SpecialSnake, - Tag, User + MessageDeletionContext, Nomination, + OffTopicChannelName, Reminder, + Role, SnakeFact, + SnakeIdiom, SnakeName, + SpecialSnake, Tag, + User ) from .serializers import ( DocumentationLinkSerializer, ExpandedInfractionSerializer, InfractionSerializer, MessageDeletionContextSerializer, - OffTopicChannelNameSerializer, ReminderSerializer, - RoleSerializer, SnakeFactSerializer, - SnakeIdiomSerializer, SnakeNameSerializer, - SpecialSnakeSerializer, TagSerializer, - UserSerializer + NominationSerializer, OffTopicChannelNameSerializer, + ReminderSerializer, RoleSerializer, + SnakeFactSerializer, SnakeIdiomSerializer, + SnakeNameSerializer, SpecialSnakeSerializer, + TagSerializer, UserSerializer ) @@ -857,3 +858,22 @@ class UserViewSet(BulkCreateModelMixin, ModelViewSet): serializer_class = UserSerializer queryset = User.objects.prefetch_related('roles') + + +class NominationViewSet(ModelViewSet): + # TODO: doc me + serializer_class = NominationSerializer + queryset = Nomination.objects.prefetch_related('author', 'user') + frozen_fields = ('author', 'inserted_at', 'user') + + def partial_update(self, request, *args, **kwargs): + for field in request.data: + if field in self.frozen_fields: + raise ValidationError({field: ['This field cannot be updated.']}) + + instance = self.get_object() + serializer = self.get_serializer(instance, data=request.data, partial=True) + serializer.is_valid(raise_exception=True) + serializer.save() + + return Response(serializer.data) |