Welcome to Django Fiction Outlines API’s documentation!

Contents:

Introduction

Welcome to Django Fiction Outlines API!

Being a reusable Django app for managing fiction outlines. Part of the broader maceoutliner project.

Documentation

The full documentation is at https://django-fiction-outlines-api.readthedocs.io.

Code Repo and Issue Tracker

The code repository and issue list for this project can be found at Github.

License

BSD License for your convenience.

Features

  • Provides a RESTful API for django-fiction-outlines suitable for serialization via JSON, XML, or DRF’s browsable API.
  • NOTE: Django Fiction Outlines API uses an object permission manager called django-rules. This allows extremely flexible permission schemes without crufting up your database or model logic. By default, fiction_outlines will restrict any view or editing to the owner of the object.

Installation

At the command line:

$ easy_install django-fiction-outlines-api

Or, if you have virtualenvwrapper installed:

$ mkvirtualenv django-fiction-outlines-api
$ pip install django-fiction-outlines-api

Add it and dependencies to your INSTALLED_APPS:

INSTALLED_APPS = (
    ...
    '
    'rest_framework',
    'taggit',
    'rules.apps.AutodiscoverRulesConfig',
    'rest_framework_rules',
    'fiction_outlines',
    'fiction_outlines_api',
    ...
)

If you have not already, add rules to you AUTHENTICATION_BACKENDS.

AUTHENTICATION_BACKENDS = (
    'rules.permissions.ObjectPermissionBackend',
    'django.contrib.auth.backends.ModelBackend',
)

Unless you like to live dangerously, it is STRONGLY recommend you configure whichever database you use for outlines to have ATOMIC_REQUESTS to True.

DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.postgresql",
        "NAME": "outlines",
        "ATOMIC_REQUESTS": True,
    }}

Add Django Fiction Outlines API’s URL patterns:

from fiction_outlines_api import urls as fiction_outlines_api_urls


urlpatterns = [
    ...
    url(r'^', include(fiction_outlines_api_urls)),
    ...
]

If you haven’t already installed fiction_outlines you should run python manage.py migrate now.

Usage

It is expected that this API will be embedded into your project’s overall DRF-based API. Simply include this app’s URLs as documented in the Installation instructions, and follow the configuration documentation for DRF. You can generate full documentation for your resulting API either through DRF’s native generation tool or you can use a third-party library such as drf-yasg.

Warning

The same known caveats of django-fiction-outlines also apply here.

  • Do NOT attempt to create a new node using the Django-provided construction method. Use dedicated methods such as add_root, add_child, and add_sibling instead.
  • Do NOT attempt to directly edit path, step, depth, num_child, etc. Use the provided move method.
  • MP_Node uses a lot of raw SQL, so always retrieve the node from the db again after tree manipulation before calling it to do anything else.
  • Object permissions come from django-rules, and the permission logic lies in the view layer. If you want to introduce your own custom logic, you should subclass the provided views in order to reduce the risk of security breaches.
  • For the same reason, if you must define a custom manager, you NEED to subclass treebeard’s base MP_Node manager.

fiction_outlines_api

fiction_outlines_api package

Submodules

fiction_outlines_api.apps module

class fiction_outlines_api.apps.FictionOutlinesApiConfig(app_name, app_module)[source]

Bases: django.apps.config.AppConfig

name = 'fiction_outlines_api'
verbose_name = 'Fiction Outlines API'

fiction_outlines_api.exceptions module

exception fiction_outlines_api.exceptions.ServiceUnavailable(detail=None, code=None)[source]

Bases: rest_framework.exceptions.APIException

default_code = 'service_unavailable'
default_detail = 'Service temporarily unavailable, please try again later.'
status_code = 503
exception fiction_outlines_api.exceptions.TreeUnavailable(detail=None, code=None)[source]

Bases: rest_framework.exceptions.APIException

default_code = 'tree_unavailable'
default_detail = 'We are having temporary issues with outlines at this time. Please try again later.'
status_code = 503

fiction_outlines_api.mixins module

class fiction_outlines_api.mixins.MultiObjectPermissionsMixin[source]

Bases: object

API Mixin that compares n objects and their permissions and returns if both are valid. Objects can be referred to by key afterwards in self.object_dict. permission dict should be:

{‘obj1’: {‘obj_class’: class_model, ‘lookup_url_kwarg’, ‘object_permission_required’: ‘your rules perm here’}, …}

Is it ugly, yes. Does it make doing this in view after view repeatable. Yep.

check_object_permissions(request, perm, obj)[source]

Verifies the object permissions are valid for the current user.

Parameters:
  • request – The request object. The user is retrieved from here.
  • perm – The permission to validate against (in :module:`rules`) format.
  • obj – The object to evaluate.
Raises:

PermissionDenied – when user lacks the required permission.

get_object_permission_queryset(obj_class)[source]

Fetches the queryset for the permission object.

Parameters:obj_class – Model class of the object to retrieve.
Returns:A django queryset for the class.
get_permission_object(pkval, objectpermission, obj_class)[source]

Fetches the permission object and checks it agains the permission specified.

Parameters:
  • pkval – The pk value to use in the search.
  • objectpermission – A permission based on the :module:`rules` format, e.g. “app_name.permission_name”
  • obj_class – The class of the object we are searching for.
Returns:

The found object.

object_class_permission_dict = {}
post(request, *args, **kwargs)[source]
class fiction_outlines_api.mixins.NodeAddMixin[source]

Bases: object

API Mixin for add_sibling and add_child commands.

Attribute fields_required_for_add:
 A tuple of fields that should be required in the submitted serializer in order to create the object.
create(request, *args, **kwargs)[source]

Does the final validation of submitted data and if valid proceeds with creation.

Raises:NotImplementedError – if client attempts to specify many-to-many relationship at creation.
fields_required_for_add = ('description',)
perform_create(serializer)[source]

The actual creation part.

Parameters:serializer – The serializer object representing the object to be created.
Raises:ValidationError – if the data submitted is invalid or violates the structure of the tree.
Returns:A serializer representing the created object.
post(request, *args, **kwargs)[source]

Parses kwargs and kicks off evaluation process.

Parameters:
  • action – Either add_child or add_sibling.
  • position – If add_sibling this is required, and must be a value from :data:POSITIONS. If action is add_child this is ignored.
Raises:

Http404 – if action is not a one of the two permitted options.

class fiction_outlines_api.mixins.NodeMoveMixin[source]

Bases: object

API mixin for move method for nodes.

get_object(pkval)[source]

Fetches an individual object and verifies that the user has the appropriate permissions to move it.

Parameters:

pkval – The primary key value to use in the search.

Returns:

Object

Raises:
  • Http404 – if object cannot be found
  • PermissionDenied – if user does not have the required permissions.
perform_move()[source]

Validates the proposed move, and if valid, will manipulate the tree accordingly.

Raises:
  • ValidationError – if the move request violates tree structure.
  • TreeUnavailable – if the DB tree is out of available nodes.
Returns:

A serializer representing the updated node.

pos = None
post(request, *args, **kwargs)[source]
related_key = None
source_node = None
target_node = None
target_node_type_fieldname = None

fiction_outlines_api.models module

All models come from fiction_outlines so there is nothing to do here.

fiction_outlines_api.rules module

Rules definitions for api. We just import in the default rules from fiction_outlines.

fiction_outlines_api.serializers module

class fiction_outlines_api.serializers.ArcCreateSerializer(instance=None, data=<class 'rest_framework.fields.empty'>, **kwargs)[source]

Bases: rest_framework.serializers.Serializer

Serializer used for arc creation. You can’t create an Arc using it’s primary serializer.

class fiction_outlines_api.serializers.ArcElementNodeSerializer(instance=None, data=<class 'rest_framework.fields.empty'>, **kwargs)[source]

Bases: rest_framework.serializers.ModelSerializer

Serializer for ArcElementNode.

Special read-only attributes:

Attribute is_milestone:
 Does this element represent a milestone in the Arc
Attribute milestone_seq:
 If a milestone, what is the proscribed sequence where it should appear in the context of the other milestones.
Attribute parent_outline:
 Convenience reference to the parent outline object.
Attribute headline:
 Automatically generated from the first line of the description.
class Meta[source]

Bases: object

fields = ('id', 'arc', 'arc_element_type', 'headline', 'description', 'story_element_node', 'assoc_characters', 'assoc_locations', 'milestone_seq', 'is_milestone', 'parent_outline')
model

alias of fiction_outlines.models.ArcElementNode

read_only_fields = ('id', 'arc', 'headline', 'milestone_seq', 'is_milestone', 'parent_outline')
class fiction_outlines_api.serializers.ArcSerializer(instance=None, data=<class 'rest_framework.fields.empty'>, **kwargs)[source]

Bases: rest_framework.serializers.ModelSerializer

Serializer for Arc model.

To create an Arc, make sure to instead use the ArcCreateSerializer and post it to fiction_outlines_api.views.ArcCreateView

class Meta[source]

Bases: object

fields = ('id', 'name', 'mace_type', 'outline', 'name', 'current_errors', 'arc_structure')
model

alias of fiction_outlines.models.Arc

read_only_fields = ('id', 'outline', 'current_errors', 'arc_structure')
get_arc_structure(obj)[source]

Fetches all the fiction_outlines.models.ArcElementNode objects assocaited with this arc as an annotated list.

Parameters:obj – The arc this serializer represents.
Returns:An annotated list ready to be serialized or an empty list.
class fiction_outlines_api.serializers.CharacterInstanceSerializer(instance=None, data=<class 'rest_framework.fields.empty'>, **kwargs)[source]

Bases: rest_framework.serializers.ModelSerializer

Serializer for character instance.

class Meta[source]

Bases: object

extra_kwargs = {'field': {'required': False}}
field = 'name'
fields = ('id', 'outline', 'character', 'name', 'main_character', 'pov_character', 'protagonist', 'antagonist', 'obstacle', 'villain')
model

alias of fiction_outlines.models.CharacterInstance

read_only_fields = ('id', 'outline', 'character', 'name')
class fiction_outlines_api.serializers.CharacterSerializer(instance=None, data=<class 'rest_framework.fields.empty'>, **kwargs)[source]

Bases: taggit_serializer.serializers.TaggitSerializer, rest_framework.serializers.ModelSerializer

Serializer for Character model.

class Meta[source]

Bases: object

fields = ('id', 'name', 'description', 'series', 'tags', 'character_instances')
model

alias of fiction_outlines.models.Character

read_only_fields = ('id', 'character_instances')
class fiction_outlines_api.serializers.LocationInstanceSerializer(instance=None, data=<class 'rest_framework.fields.empty'>, **kwargs)[source]

Bases: rest_framework.serializers.ModelSerializer

Serializer for location instance.

class Meta[source]

Bases: object

extra_kwargs = {'field': {'required': False}}
field = 'outline'
fields = ('id', 'location', 'name', 'outline')
model

alias of fiction_outlines.models.LocationInstance

read_only_fields = ('id', 'location', 'name', 'outline')
class fiction_outlines_api.serializers.LocationSerializer(instance=None, data=<class 'rest_framework.fields.empty'>, **kwargs)[source]

Bases: taggit_serializer.serializers.TaggitSerializer, rest_framework.serializers.ModelSerializer

Serializer for Location model.

class Meta[source]

Bases: object

fields = ('id', 'name', 'description', 'series', 'tags', 'location_instances')
model

alias of fiction_outlines.models.Location

read_only_fields = ('id', 'location_instances')
class fiction_outlines_api.serializers.OutlineSerializer(instance=None, data=<class 'rest_framework.fields.empty'>, **kwargs)[source]

Bases: taggit_serializer.serializers.TaggitSerializer, rest_framework.serializers.ModelSerializer

Serializer for Outline model. Also provides outline_structure, which is a treebeard annotated list of story element nodes.

Special read-only fields:

Attribute length_estimate:
 Auto calculated length (in words) based on the number of characters, locations, and arcs.
Attribute arc_set:
 The fiction_outlines.models.Arc objects associated with this outline.
Attribute characterinstance_set:
 Character instances associated with this outline.
Attribute locationinstance_set:
 Location instances associated with this outline.
Attribute outline_structure:
 An annotated list of fiction_outlines.models.StoryElementNode objects for visualizing the tree structure.
class Meta[source]

Bases: object

fields = ('id', 'title', 'description', 'series', 'tags', 'length_estimate', 'arc_set', 'characterinstance_set', 'locationinstance_set', 'outline_structure')
model

alias of fiction_outlines.models.Outline

read_only_fields = ('id', 'length_estimate', 'arc_set', 'characterinstance_set', 'locationinstance_set', 'outline_structure')
get_outline_structure(obj)[source]

Retrieves all fiction_outlines.StoryElementNode objects associated with this outline, and returns it as an annotated list that can be serialized.

Parameters:obj – The outline object this serializer represents.
Returns:An annotated list for serialization or an empty list.
class fiction_outlines_api.serializers.SeriesSerializer(instance=None, data=<class 'rest_framework.fields.empty'>, **kwargs)[source]

Bases: taggit_serializer.serializers.TaggitSerializer, rest_framework.serializers.ModelSerializer

Serializer for Series model.

class Meta[source]

Bases: object

fields = ('id', 'title', 'description', 'tags')
model

alias of fiction_outlines.models.Series

read_only_fields = ('id',)
class fiction_outlines_api.serializers.StoryElementNodeSerializer(instance=None, data=<class 'rest_framework.fields.empty'>, **kwargs)[source]

Bases: rest_framework.serializers.ModelSerializer

Serializer for StoryElementNode

Two special fields here:

Attribute all_characters:
 All characters associated with this node or its descendants.
Attribute all_locations:
 All locations associated with this node of its descendants.
class Meta[source]

Bases: object

fields = ('id', 'story_element_type', 'name', 'description', 'outline', 'assoc_characters', 'assoc_locations', 'all_characters', 'all_locations', 'impact_rating')
model

alias of fiction_outlines.models.StoryElementNode

read_only_fields = ('all_characters', 'all_locations', 'impact_rating', 'outline', 'id')
fiction_outlines_api.serializers.convert_annotated_list(annotated_list, serializer_class)[source]

Takes an annotated list and a serializer class and returns a version that is suitable for serialization.

fiction_outlines_api.urls module

fiction_outlines_api.views module

class fiction_outlines_api.views.ArcCreateView(**kwargs)[source]

Bases: rest_framework_rules.mixins.PermissionRequiredMixin, rest_framework.generics.CreateAPIView

API for creating arcs. Uses a custom serializer, as Arcs are generated via special methods inside a transaction.

Provides HTTP method:

create(request, *args, **kwargs)[source]
dispatch(request, *args, **kwargs)[source]

.dispatch() is pretty much the same as Django’s regular dispatch, but with extra hooks for startup, finalize, and exception handling.

object_permission_required = 'fiction_outlines.edit_outline'
perform_create(serializer)[source]
permission_required = 'fiction_outlines_api.valid_user'
post(request, *args, **kwargs)[source]
serializer_class

alias of fiction_outlines_api.serializers.ArcCreateSerializer

class fiction_outlines_api.views.ArcDetailView(**kwargs)[source]

Bases: rest_framework_rules.mixins.PermissionRequiredMixin, rest_framework.generics.RetrieveUpdateDestroyAPIView

API for non-create object operations for Arc model.

Provides HTTP methods:

  • GET: Retrieve an individual object.
  • PUT: Update the object with data compatible with a fiction_outlines_api.serializers.ArcSerializer
  • PATCH: Update the object with partial data that corresponds to keys in the serializer.
  • DELETE: Delete the object.
delete(request, *args, **kwargs)[source]
get_queryset()[source]

Get the list of items for this view. This must be an iterable, and may be a queryset. Defaults to using self.queryset.

This method should always be used rather than accessing self.queryset directly, as self.queryset gets evaluated only once, and those results are cached for all subsequent requests.

You may want to override this if you need to provide different querysets depending on the incoming request.

(Eg. return a list of items that is specific to the user)

lookup_url_kwarg = 'arc'
object_permission_required = 'fiction_outlines.view_arc'
patch(request, *args, **kwargs)[source]
permission_required = 'fiction_outlines_api.valid_user'
put(request, *args, **kwargs)[source]
serializer_class

alias of fiction_outlines_api.serializers.ArcSerializer

class fiction_outlines_api.views.ArcNodeCreateView(**kwargs)[source]

Bases: rest_framework_rules.mixins.PermissionRequiredMixin, fiction_outlines_api.mixins.NodeAddMixin, rest_framework.generics.CreateAPIView

API view for add_child and add_sibling. You can only create tree objects in relation to another object in the tree. See mixins.NodeAddMixin for more details.

fields_required_for_add = ('arc_element_type', 'description', 'story_element_node')
get_queryset()[source]

Get the list of items for this view. This must be an iterable, and may be a queryset. Defaults to using self.queryset.

This method should always be used rather than accessing self.queryset directly, as self.queryset gets evaluated only once, and those results are cached for all subsequent requests.

You may want to override this if you need to provide different querysets depending on the incoming request.

(Eg. return a list of items that is specific to the user)

lookup_url_kwarg = 'arcnode'
object_permission_required = 'fiction_outlines.edit_arc_node'
permission_required = 'fiction_outlines_api.valid_user'
serializer_class

alias of fiction_outlines_api.serializers.ArcElementNodeSerializer

class fiction_outlines_api.views.ArcNodeDetailView(**kwargs)[source]

Bases: rest_framework_rules.mixins.PermissionRequiredMixin, rest_framework.generics.RetrieveUpdateDestroyAPIView

API for viewing a tree of fiction_outlines.models.ArcElementNode, as well as some basic updates.

Provides HTTP methods:

delete(request, *args, **kwargs)[source]
destroy(request, *args, **kwargs)[source]

Destroys the object, but first checks that the element doesn’t represent either the Hook or Resolution of an Arc. These types may not be deleted unless you are deleting the whole arc.

Raises:ParseError – if the object represents the Hook or Resolution.
get_queryset()[source]

Get the list of items for this view. This must be an iterable, and may be a queryset. Defaults to using self.queryset.

This method should always be used rather than accessing self.queryset directly, as self.queryset gets evaluated only once, and those results are cached for all subsequent requests.

You may want to override this if you need to provide different querysets depending on the incoming request.

(Eg. return a list of items that is specific to the user)

lookup_url_kwarg = 'arcnode'
object_permission_required = 'fiction_outlines.view_arc_node'
patch(request, *args, **kwargs)[source]
permission_classes = (<class 'rest_framework.permissions.IsAuthenticated'>,)
permission_required = 'fiction_outlines_api.valid_user'
put(request, *args, **kwargs)[source]
serializer_class

alias of fiction_outlines_api.serializers.ArcElementNodeSerializer

update(request, *args, **kwargs)[source]
class fiction_outlines_api.views.ArcNodeMoveView(**kwargs)[source]

Bases: rest_framework_rules.mixins.PermissionRequiredMixin, fiction_outlines_api.mixins.NodeMoveMixin, rest_framework.generics.GenericAPIView

View for moving arc nodes. See mixins.NodeMoveMixin for more details.

get_queryset()[source]

Get the list of items for this view. This must be an iterable, and may be a queryset. Defaults to using self.queryset.

This method should always be used rather than accessing self.queryset directly, as self.queryset gets evaluated only once, and those results are cached for all subsequent requests.

You may want to override this if you need to provide different querysets depending on the incoming request.

(Eg. return a list of items that is specific to the user)

object_permission_required = 'fiction_outlines.edit_arc_node'
permission_classes = (<class 'rest_framework.permissions.IsAuthenticated'>,)
permission_required = 'fiction_outlines_api.valid_user'
related_key = 'arc'
serializer_class

alias of fiction_outlines_api.serializers.ArcElementNodeSerializer

target_node_type_fieldname = 'arc_element_type'
class fiction_outlines_api.views.CharacterDetail(**kwargs)[source]

Bases: rest_framework_rules.mixins.PermissionRequiredMixin, rest_framework.generics.RetrieveUpdateDestroyAPIView

API view for all single item character operations besides create.

Provides HTTP methods:

delete(request, *args, **kwargs)[source]
get_queryset()[source]

Get the list of items for this view. This must be an iterable, and may be a queryset. Defaults to using self.queryset.

This method should always be used rather than accessing self.queryset directly, as self.queryset gets evaluated only once, and those results are cached for all subsequent requests.

You may want to override this if you need to provide different querysets depending on the incoming request.

(Eg. return a list of items that is specific to the user)

lookup_url_kwarg = 'character'
object_permission_required = 'fiction_outlines.view_character'
patch(request, *args, **kwargs)[source]
perform_update(serializer)[source]

Validates that if a series is specified, that the user has rights to it as well.

Raises:PermissionDenied – if the user does not have the required permissions.
permission_classes = (<class 'rest_framework.permissions.IsAuthenticated'>,)
permission_required = 'fiction_outlines_api.valid_user'
put(request, *args, **kwargs)[source]
serializer_class

alias of fiction_outlines_api.serializers.CharacterSerializer

class fiction_outlines_api.views.CharacterInstanceCreateView(**kwargs)[source]

Bases: fiction_outlines_api.mixins.MultiObjectPermissionsMixin, rest_framework_rules.mixins.PermissionRequiredMixin, rest_framework.generics.CreateAPIView

API view for creating a character instance. Expects kwargs in url for character and outline. All other data comes from the serializer.

Provides HTTP methods:

object_class_permission_dict = {'character': {'obj_class': <class 'fiction_outlines.models.Character'>, 'object_permission_required': 'fiction_outlines.edit_character', 'lookup_url_kwarg': 'character'}, 'outline': {'obj_class': <class 'fiction_outlines.models.Outline'>, 'object_permission_required': 'fiction_outlines.edit_outline', 'lookup_url_kwarg': 'outline'}}
perform_create(serializer)[source]

Attempts the actual creation of the instance.

Raises:ParseError – if the character is already associated with the outline.
permission_required = 'fiction_outlines_api.valid_user'
serializer_class

alias of fiction_outlines_api.serializers.CharacterInstanceSerializer

class fiction_outlines_api.views.CharacterInstanceDetailView(**kwargs)[source]

Bases: rest_framework_rules.mixins.PermissionRequiredMixin, rest_framework.generics.RetrieveUpdateDestroyAPIView

API view for non-creation actions on CharacterInstance objects.

Provides HTTP methods:

delete(request, *args, **kwargs)[source]
get_queryset()[source]

Get the list of items for this view. This must be an iterable, and may be a queryset. Defaults to using self.queryset.

This method should always be used rather than accessing self.queryset directly, as self.queryset gets evaluated only once, and those results are cached for all subsequent requests.

You may want to override this if you need to provide different querysets depending on the incoming request.

(Eg. return a list of items that is specific to the user)

lookup_url_kwarg = 'instance'
object_permission_required = 'fiction_outlines.view_character_instance'
patch(request, *args, **kwargs)[source]
permission_required = 'fiction_outlines_api.valid_user'
put(request, *args, **kwargs)[source]
serializer_class

alias of fiction_outlines_api.serializers.CharacterInstanceSerializer

class fiction_outlines_api.views.CharacterList(**kwargs)[source]

Bases: rest_framework.generics.ListCreateAPIView

API view for character list

Provies HTTP methods:

get_queryset()[source]

Get the list of items for this view. This must be an iterable, and may be a queryset. Defaults to using self.queryset.

This method should always be used rather than accessing self.queryset directly, as self.queryset gets evaluated only once, and those results are cached for all subsequent requests.

You may want to override this if you need to provide different querysets depending on the incoming request.

(Eg. return a list of items that is specific to the user)

perform_create(serializer)[source]
permission_classes = (<class 'rest_framework.permissions.IsAuthenticated'>,)
serializer_class

alias of fiction_outlines_api.serializers.CharacterSerializer

class fiction_outlines_api.views.LocationDetail(**kwargs)[source]

Bases: rest_framework_rules.mixins.PermissionRequiredMixin, rest_framework.generics.RetrieveUpdateDestroyAPIView

API view for all single item location operations besides create.

Provides HTTP methods:

delete(request, *args, **kwargs)[source]
get_queryset()[source]

Get the list of items for this view. This must be an iterable, and may be a queryset. Defaults to using self.queryset.

This method should always be used rather than accessing self.queryset directly, as self.queryset gets evaluated only once, and those results are cached for all subsequent requests.

You may want to override this if you need to provide different querysets depending on the incoming request.

(Eg. return a list of items that is specific to the user)

lookup_url_kwarg = 'location'
object_permission_required = 'fiction_outlines.view_location'
patch(request, *args, **kwargs)[source]
perform_update(serializer)[source]

Performs update actions. If a series is specified, it verifies the user has rights to it as well.

Raises:PermissionDenied – if the user does not have the correct permissions.
permission_classes = (<class 'rest_framework.permissions.IsAuthenticated'>,)
permission_required = 'fiction_outlines_api.valid_user'
put(request, *args, **kwargs)[source]
serializer_class

alias of fiction_outlines_api.serializers.LocationSerializer

class fiction_outlines_api.views.LocationInstanceCreateView(**kwargs)[source]

Bases: fiction_outlines_api.mixins.MultiObjectPermissionsMixin, rest_framework_rules.mixins.PermissionRequiredMixin, rest_framework.generics.CreateAPIView

API view for creating a location instance. Expects kwargs in url for location and outline. All other data comes from the serializer.

Provides HTTP method:

object_class_permission_dict = {'location': {'obj_class': <class 'fiction_outlines.models.Location'>, 'object_permission_required': 'fiction_outlines.edit_location', 'lookup_url_kwarg': 'location'}, 'outline': {'obj_class': <class 'fiction_outlines.models.Outline'>, 'object_permission_required': 'fiction_outlines.edit_outline', 'lookup_url_kwarg': 'outline'}}
perform_create(serializer)[source]

Creates the location instance.

Raises:ParseError – if the location is already associated with the outline.
permission_required = 'fiction_outlines_api.valid_user'
serializer_class

alias of fiction_outlines_api.serializers.LocationInstanceSerializer

class fiction_outlines_api.views.LocationInstanceDetailView(**kwargs)[source]

Bases: rest_framework_rules.mixins.PermissionRequiredMixin, rest_framework.generics.RetrieveDestroyAPIView

API view for non-creation actions on LocationInstance objects. As locations instances don’t have editable data, only retrieval and destroy are supported at this time.

Provides HTTP methods:

  • GET: Retrieve an individual object.
  • DELETE: Delete the object.
delete(request, *args, **kwargs)[source]
get_queryset()[source]

Get the list of items for this view. This must be an iterable, and may be a queryset. Defaults to using self.queryset.

This method should always be used rather than accessing self.queryset directly, as self.queryset gets evaluated only once, and those results are cached for all subsequent requests.

You may want to override this if you need to provide different querysets depending on the incoming request.

(Eg. return a list of items that is specific to the user)

lookup_url_kwarg = 'instance'
object_permission_required = 'fiction_outlines.view_location_instance'
permission_required = 'fiction_outlines_api.valid_user'
serializer_class

alias of fiction_outlines_api.serializers.LocationInstanceSerializer

class fiction_outlines_api.views.LocationList(**kwargs)[source]

Bases: rest_framework.generics.ListCreateAPIView

API view for location list

Provides HTTP methods:

get_queryset()[source]

Get the list of items for this view. This must be an iterable, and may be a queryset. Defaults to using self.queryset.

This method should always be used rather than accessing self.queryset directly, as self.queryset gets evaluated only once, and those results are cached for all subsequent requests.

You may want to override this if you need to provide different querysets depending on the incoming request.

(Eg. return a list of items that is specific to the user)

perform_create(serializer)[source]

Creates the object. If a series is specified, verify the user has rights to it as well.

Raises:PermissionDenied – if the user lackst he required permissions.
permission_classes = (<class 'rest_framework.permissions.IsAuthenticated'>,)
serializer_class

alias of fiction_outlines_api.serializers.LocationSerializer

class fiction_outlines_api.views.OutlineDetail(**kwargs)[source]

Bases: rest_framework_rules.mixins.PermissionRequiredMixin, rest_framework.generics.RetrieveUpdateDestroyAPIView

API view for all single item outline operations besides create.

Provides HTTP methods:

  • GET: Retrieve an individual object.
  • PUT: Update the object with data compatible with a fiction_outlines_api.serializers.OutlineSerializer
  • PATCH: Update the object with partial data that corresponds to keys in the serializer.
  • DELETE: Delete the object.
delete(request, *args, **kwargs)[source]
get_queryset()[source]

Get the list of items for this view. This must be an iterable, and may be a queryset. Defaults to using self.queryset.

This method should always be used rather than accessing self.queryset directly, as self.queryset gets evaluated only once, and those results are cached for all subsequent requests.

You may want to override this if you need to provide different querysets depending on the incoming request.

(Eg. return a list of items that is specific to the user)

lookup_url_kwarg = 'outline'
object_permission_required = 'fiction_outlines.view_outline'
patch(request, *args, **kwargs)[source]
perform_update(serializer)[source]

Updates the object. If a series is specified, it verifies the user has permissions for that object as well.

Raises:PermissionDenied – if the user lacks the needed permissions.
permission_classes = (<class 'rest_framework.permissions.IsAuthenticated'>,)
permission_required = 'fiction_outlines_api.valid_user'
put(request, *args, **kwargs)[source]
serializer_class

alias of fiction_outlines_api.serializers.OutlineSerializer

class fiction_outlines_api.views.OutlineList(**kwargs)[source]

Bases: rest_framework.generics.ListCreateAPIView

API view for Outline list

Provides HTTP methods:

get_queryset()[source]

Get the list of items for this view. This must be an iterable, and may be a queryset. Defaults to using self.queryset.

This method should always be used rather than accessing self.queryset directly, as self.queryset gets evaluated only once, and those results are cached for all subsequent requests.

You may want to override this if you need to provide different querysets depending on the incoming request.

(Eg. return a list of items that is specific to the user)

perform_create(serializer)[source]

Creates the object. If a series is specified, it verfies that the user has rights to it as well.

Raises:PermissionDenied – if the user does not have the required permissions.
permission_classes = (<class 'rest_framework.permissions.IsAuthenticated'>,)
serializer_class

alias of fiction_outlines_api.serializers.OutlineSerializer

class fiction_outlines_api.views.SeriesDetail(**kwargs)[source]

Bases: rest_framework_rules.mixins.PermissionRequiredMixin, rest_framework.generics.RetrieveUpdateDestroyAPIView

Retrieves details of a series, and enables editing of the object.

Provides HTTP methods:

delete(request, *args, **kwargs)[source]
get_queryset()[source]

Get the list of items for this view. This must be an iterable, and may be a queryset. Defaults to using self.queryset.

This method should always be used rather than accessing self.queryset directly, as self.queryset gets evaluated only once, and those results are cached for all subsequent requests.

You may want to override this if you need to provide different querysets depending on the incoming request.

(Eg. return a list of items that is specific to the user)

lookup_url_kwarg = 'series'
object_permission_required = 'fiction_outlines.view_series'
permission_classes = (<class 'rest_framework.permissions.IsAuthenticated'>,)
permission_required = 'fiction_outlines_api.valid_user'
put(request, *args, **kwargs)[source]
serializer_class

alias of fiction_outlines_api.serializers.SeriesSerializer

class fiction_outlines_api.views.SeriesList(**kwargs)[source]

Bases: rest_framework.generics.ListCreateAPIView

API view for series list.

Provides HTTP methods:

get_queryset()[source]

Get the list of items for this view. This must be an iterable, and may be a queryset. Defaults to using self.queryset.

This method should always be used rather than accessing self.queryset directly, as self.queryset gets evaluated only once, and those results are cached for all subsequent requests.

You may want to override this if you need to provide different querysets depending on the incoming request.

(Eg. return a list of items that is specific to the user)

perform_create(serializer)[source]
permission_classes = (<class 'rest_framework.permissions.IsAuthenticated'>,)
serializer_class

alias of fiction_outlines_api.serializers.SeriesSerializer

class fiction_outlines_api.views.StoryNodeCreateView(**kwargs)[source]

Bases: rest_framework_rules.mixins.PermissionRequiredMixin, fiction_outlines_api.mixins.NodeAddMixin, rest_framework.generics.CreateAPIView

View for adding story nodes. You can only create tree elements in relation to other objects in the same tree. See mixins.NodeAddMixin for more details.

fields_required_for_add = ('story_element_type', 'name', 'description')
get_queryset()[source]

Get the list of items for this view. This must be an iterable, and may be a queryset. Defaults to using self.queryset.

This method should always be used rather than accessing self.queryset directly, as self.queryset gets evaluated only once, and those results are cached for all subsequent requests.

You may want to override this if you need to provide different querysets depending on the incoming request.

(Eg. return a list of items that is specific to the user)

lookup_url_kwarg = 'storynode'
object_permission_required = 'fiction_outlines.edit_story_node'
permission_required = 'fiction_outlines_api.valid_user'
serializer_class

alias of fiction_outlines_api.serializers.StoryElementNodeSerializer

class fiction_outlines_api.views.StoryNodeDetailView(**kwargs)[source]

Bases: rest_framework_rules.mixins.PermissionRequiredMixin, rest_framework.generics.RetrieveUpdateDestroyAPIView

API for viewing and editing a story node.

Provides HTTP methods:

delete(request, *args, **kwargs)[source]
get_queryset()[source]

Get the list of items for this view. This must be an iterable, and may be a queryset. Defaults to using self.queryset.

This method should always be used rather than accessing self.queryset directly, as self.queryset gets evaluated only once, and those results are cached for all subsequent requests.

You may want to override this if you need to provide different querysets depending on the incoming request.

(Eg. return a list of items that is specific to the user)

lookup_url_kwarg = 'storynode'
object_permission_required = 'fiction_outlines.view_story_node'
patch(request, *args, **kwargs)[source]
permission_classes = (<class 'rest_framework.permissions.IsAuthenticated'>,)
permission_required = 'fiction_outlines_api.valid_user'
put(request, *args, **kwargs)[source]
serializer_class

alias of fiction_outlines_api.serializers.StoryElementNodeSerializer

update(request, *args, **kwargs)[source]

Updates the node, after first running it through validation to ensure it won’t violate the tree structure.

Raises:ParseError – if the edit would violate the tree structure.
class fiction_outlines_api.views.StoryNodeMoveView(**kwargs)[source]

Bases: rest_framework_rules.mixins.PermissionRequiredMixin, fiction_outlines_api.mixins.NodeMoveMixin, rest_framework.generics.GenericAPIView

View for moving story nodes. See mixins.NodeMoveMixin for more details.

get_queryset()[source]

Get the list of items for this view. This must be an iterable, and may be a queryset. Defaults to using self.queryset.

This method should always be used rather than accessing self.queryset directly, as self.queryset gets evaluated only once, and those results are cached for all subsequent requests.

You may want to override this if you need to provide different querysets depending on the incoming request.

(Eg. return a list of items that is specific to the user)

object_permission_required = 'fiction_outlines.edit_story_node'
permission_required = 'fiction_outlines_api.valid_user'
related_key = 'outline'
serializer_class

alias of fiction_outlines_api.serializers.StoryElementNodeSerializer

target_node_type_fieldname = 'story_element_type'

Module contents

Contributing

Contributions are welcome, and they are greatly appreciated! Every little bit helps, and credit will always be given.

You can contribute in many ways:

Types of Contributions

Report Bugs

Report bugs at https://github.com/maceoutliner/django-fiction-outlines-api/issues.

If you are reporting a bug, please include:

  • Your operating system name and version.
  • Any details about your local setup that might be helpful in troubleshooting.
  • Detailed steps to reproduce the bug.

Fix Bugs

Look through the GitHub issues for bugs. Anything tagged with “bug” is open to whoever wants to implement it.

Implement Features

Look through the GitHub issues for features. Anything tagged with “feature” is open to whoever wants to implement it.

Write Documentation

Django Fiction Outlines API could always use more documentation, whether as part of the official Django Fiction Outlines docs, in docstrings, or even on the web in blog posts, articles, and such.

Submit Feedback

The best way to send feedback is to file an issue at https://github.com/maceoutliner/django-fiction-outlines-api/issues.

If you are proposing a feature:

  • Explain in detail how it would work.
  • Keep the scope as narrow as possible, to make it easier to implement.
  • Remember that this is a volunteer-driven project, and that contributions are welcome :)

Get Started!

Ready to contribute? Here’s how to set up django-fiction-outlines-api for local development.

  1. Fork the django-fiction-outlines-api repo on GitHub.

  2. Clone your fork locally:

    $ git clone git@github.com:your_name_here/django-fiction-outlines-api.git
    
  3. Install your local copy into a virtualenv. Assuming you have pipenv installed, this is how you set up your fork for local development:

    $ cd django-fiction-outlines-api/
    $ pipenv install --dev
    

Alternatively:

$ pip install test_requirements.txt
  1. Create a branch for local development:

    $ git checkout -b name-of-your-bugfix-or-feature
    

    Now you can make your changes locally.

    It is preferred and appreciated if you follow this style guide for your commit messages.

  2. When you’re done making changes, check that your changes pass flake8 and the tests.:

    $ flake8 fiction_outlines_api tests
    $ pytest
    

    To get flake8 and tox, just pip install them into your virtualenv.

  3. Commit your changes and push your branch to GitHub:

    $ git add .
    $ git commit -m "Your detailed description of your changes."
    $ git push origin name-of-your-bugfix-or-feature
    
  4. Submit a pull request through the GitHub website.

Pull Request Guidelines

Before you submit a pull request, check that it meets these guidelines:

  1. The pull request should include tests.
  2. If the pull request adds functionality, the docs should be updated. Put your new functionality into a function with a docstring, and add the feature to the list in README.rst.
  3. The pull request should work for Python for Python 3.6 and up. Check https://travis-ci.org/maceoutliner/django-fiction-outlines-api/pull_requests and make sure that the tests pass for all supported Python versions. (Don’t submit issues or PR to enable Python 2 support. They will not be merged.)
  4. Where appropriate, squash your commits using git rebase -i.

Appropriate Conduct

All contributors and project participants are expected to follow our Contributor Covenant Code of Conduct.

Contributor Covenant Code of Conduct

Our Pledge

In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.

Our Standards

Examples of behavior that contributes to creating a positive environment include:

  • Using welcoming and inclusive language
  • Being respectful of differing viewpoints and experiences
  • Gracefully accepting constructive criticism
  • Focusing on what is best for the community
  • Showing empathy towards other community members

Examples of unacceptable behavior by participants include:

  • The use of sexualized language or imagery and unwelcome sexual attention or advances
  • Trolling, insulting/derogatory comments, and personal or political attacks
  • Public or private harassment
  • Publishing others’ private information, such as a physical or electronic address, without explicit permission
  • Other conduct which could reasonably be considered inappropriate in a professional setting

Our Responsibilities

Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.

Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.

Scope

This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.

Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at coc@maceoutliner.org. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.

Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project’s leadership.

Attribution

This Code of Conduct is adapted from the Contributor Covenant, version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html

BSD License

The Clear BSD License

Copyright (c) 2018, Daniel Andrlik All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted (subject to the limitations in the disclaimer below) provided that the following conditions are met:

  • Redistributions of source code must retain the above copyright notice,

this list of conditions and the following disclaimer.

  • Redistributions in binary form must reproduce the above copyright

notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

  • Neither the name of the copyright holder nor the names of its

contributors may be used to endorse or promote products derived from this software without specific prior written permission.

NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY’S PATENT RIGHTS ARE GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Credits

Development Lead

Contributors

None yet. Why not be the first?

History

0.1.3 (2018-06-21)

  • Move dependency back to official django-taggit-serializer package now that our pull request has been merged.

0.1.0 (2018-04-07)

  • First release on PyPI.