Source code for evennia.web.api.views
"""
Views are the functions that are called by different url endpoints.
The Django Rest Framework provides collections called 'ViewSets', which
can generate a number of views for the common CRUD operations.
"""
from rest_framework.viewsets import ModelViewSet
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework import status
from django_filters.rest_framework import DjangoFilterBackend
from evennia.objects.models import ObjectDB
from evennia.objects.objects import DefaultCharacter, DefaultExit, DefaultRoom
from evennia.accounts.models import AccountDB
from evennia.scripts.models import ScriptDB
from evennia.web.api.serializers import (
ObjectDBSerializer,
AccountSerializer,
ScriptDBSerializer,
AttributeSerializer,
)
from evennia.web.api.filters import ObjectDBFilterSet, AccountDBFilterSet, ScriptDBFilterSet
from evennia.web.api.permissions import EvenniaPermission
[docs]class TypeclassViewSetMixin(object):
"""
This mixin adds some shared functionality to each viewset of a typeclass. They all use the same
permission classes and filter backend. You can override any of these in your own viewsets.
"""
# permission classes determine who is authorized to call the view
permission_classes = [EvenniaPermission]
# the filter backend allows for retrieval views to have filter arguments passed to it,
# for example: mygame.com/api/objects?db_key=bob to find matches based on objects having a db_key of bob
filter_backends = [DjangoFilterBackend]
[docs] @action(detail=True, methods=["put", "post"])
def set_attribute(self, request, pk=None):
"""
This is an example of a custom action added to a viewset. Based on the name of the
method, it will create a default url_name (used for reversing) and url_path.
The 'pk' argument is automatically passed to this action because it has a url path
of the format <object type>/:pk/set-attribute. The get_object method is automatically
set in the expected viewset classes that will inherit this, using the pk that's
passed along to retrieve the object.
This action will set an attribute if the db_value is defined, or remove it
if no db_value is provided.
"""
attr = AttributeSerializer(data=request.data)
obj = self.get_object()
if attr.is_valid(raise_exception=True):
key = attr.validated_data["db_key"]
value = attr.validated_data.get("db_value")
category = attr.validated_data.get("db_category")
attr_type = attr.validated_data.get("db_attrtype")
if attr_type == "nick":
handler = obj.nicks
else:
handler = obj.attributes
if value:
handler.add(key=key, value=value, category=category)
else:
handler.remove(key=key, category=category)
return Response(
AttributeSerializer(obj.db_attributes.all(), many=True).data,
status=status.HTTP_200_OK,
)
return Response(attr.errors, status=status.HTTP_400_BAD_REQUEST)
[docs]class ObjectDBViewSet(TypeclassViewSetMixin, ModelViewSet):
"""
An example of a basic viewset for all ObjectDB instances. It declares the
serializer to use for both retrieving and changing/creating/deleting
instances. Serializers are similar to django forms, used for the
transmitting of data (typically json).
"""
serializer_class = ObjectDBSerializer
queryset = ObjectDB.objects.all()
filterset_class = ObjectDBFilterSet
[docs]class CharacterViewSet(ObjectDBViewSet):
"""
This overrides the queryset to only retrieve Character objects
based on your DefaultCharacter typeclass path.
"""
queryset = DefaultCharacter.objects.typeclass_search(
DefaultCharacter.path, include_children=True
)
[docs]class RoomViewSet(ObjectDBViewSet):
"""Viewset for Room objects"""
queryset = DefaultRoom.objects.typeclass_search(DefaultRoom.path, include_children=True)
[docs]class ExitViewSet(ObjectDBViewSet):
"""Viewset for Exit objects"""
queryset = DefaultExit.objects.typeclass_search(DefaultExit.path, include_children=True)
[docs]class AccountDBViewSet(TypeclassViewSetMixin, ModelViewSet):
"""Viewset for Account objects"""
serializer_class = AccountSerializer
queryset = AccountDB.objects.all()
filterset_class = AccountDBFilterSet
[docs]class ScriptDBViewSet(TypeclassViewSetMixin, ModelViewSet):
"""Viewset for Script objects"""
serializer_class = ScriptDBSerializer
queryset = ScriptDB.objects.all()
filterset_class = ScriptDBFilterSet