Unlike arc nodes, for which we just warn about structure, the story tree
    allowed parent/child rules must be strictly enforced.

def validate_generations_for_story_elements(
        sender,
        instance,
        action,
        target_node_type=None,
        target_node=None,
        pos=None,
        *args,
        **kwargs
):
    '''
    Unlike arc nodes, for which we just warn about structure, the story tree
    allowed parent/child rules must be strictly enforced.
    '''
    if action == 'add_child':
        if instance.story_element_type not in STORY_NODE_ELEMENT_DEFINITIONS[target_node_type]['allowed_parents']:
            raise IntegrityError(_('%s is not an allowed child of %s' % (target_node_type,
                                                                         instance.story_element_type)))
    if action == 'update':
        parent = instance.get_parent()
        children = instance.get_children()
        if parent.story_element_type not in STORY_NODE_ELEMENT_DEFINITIONS[target_node_type]['allowed_parents']:
            raise IntegrityError(_('%s is not an allowed child of %s' % (target_node_type, parent.story_element_type)))
        if children:
            for child in children:
                if target_node_type not in STORY_NODE_ELEMENT_DEFINITIONS[child.story_element_type]['allowed_parents']:
                    raise IntegrityError(_('%s is not permitted to be a parent of %s' % (
                        target_node_type, child.story_element_type)))
    if action == 'add_sibling':
        parent = instance.get_parent()
        if parent.story_element_type not in STORY_NODE_ELEMENT_DEFINITIONS[target_node_type]['allowed_parents']:
            raise IntegrityError(_('%s is not an allowed child of %s' % (target_node_type, parent.story_element_type)))
    if action == 'move':
        if not pos or 'sibling' in pos or 'right' in pos or 'left' in pos:
            parent = target_node.get_parent()
            if (parent.story_element_type not in
                STORY_NODE_ELEMENT_DEFINITIONS[instance.story_element_type]['allowed_parents']):
                raise IntegrityError(_('%s is not an allowed child of %s' % (
                    instance.story_element_type,
                    parent.story_element_type
                )))
        if 'child' in pos:
            if (target_node.story_element_type not in
                STORY_NODE_ELEMENT_DEFINITIONS[instance.story_element_type]['allowed_parents']):
                raise IntegrityError(_('%s is not an allowed child of %s' % (
                    instance.story_element_type,
                    target_node.story_element_type
                )))