From 934fafb6b573a93aa6101c5b9be300c0eb3f6691 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Sat, 4 Nov 2023 11:56:51 -0500 Subject: [PATCH 01/16] Basic views into it's own folder. --- api_v2/views/__init__.py | 3 +++ api_v2/{ => views}/views.py | 0 2 files changed, 3 insertions(+) create mode 100644 api_v2/views/__init__.py rename api_v2/{ => views}/views.py (100%) diff --git a/api_v2/views/__init__.py b/api_v2/views/__init__.py new file mode 100644 index 00000000..74e35f0b --- /dev/null +++ b/api_v2/views/__init__.py @@ -0,0 +1,3 @@ +"""The initialization for views for open5e's api v2.""" + +from .views import * \ No newline at end of file diff --git a/api_v2/views.py b/api_v2/views/views.py similarity index 100% rename from api_v2/views.py rename to api_v2/views/views.py From 714f1f32b9c22bad41533978ad9588b2c7826df6 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Sat, 4 Nov 2023 12:03:21 -0500 Subject: [PATCH 02/16] Fixing a bug with a plant. --- data/v2/wizards-of-the-coast/srd/CreatureType.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/v2/wizards-of-the-coast/srd/CreatureType.json b/data/v2/wizards-of-the-coast/srd/CreatureType.json index 21c58454..7dcb5f73 100644 --- a/data/v2/wizards-of-the-coast/srd/CreatureType.json +++ b/data/v2/wizards-of-the-coast/srd/CreatureType.json @@ -1,7 +1,7 @@ [ { "model": "api_v2.creaturetype", - "pk": "Plant", + "pk": "plant", "fields": { "name": "Plant", "desc": "Plants in this context are vegetable creatures, not ordinary flora. Most of them are ambulatory, and some are carnivorous. The quintessential plants are the shambling mound and the treant. Fungal creatures such as the gas spore and the myconid also fall into this category.", From 945fdc9bcb72ea596c8dcedca099a8d4955873a5 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Sat, 4 Nov 2023 12:03:31 -0500 Subject: [PATCH 03/16] splitting serializers into a folder. --- api_v2/serializers/__init__.py | 3 +++ api_v2/{ => serializers}/serializers.py | 0 2 files changed, 3 insertions(+) create mode 100644 api_v2/serializers/__init__.py rename api_v2/{ => serializers}/serializers.py (100%) diff --git a/api_v2/serializers/__init__.py b/api_v2/serializers/__init__.py new file mode 100644 index 00000000..c2e9fc92 --- /dev/null +++ b/api_v2/serializers/__init__.py @@ -0,0 +1,3 @@ +"""The initialization for serializers for open5e's api v2.""" + +from .serializers import * diff --git a/api_v2/serializers.py b/api_v2/serializers/serializers.py similarity index 100% rename from api_v2/serializers.py rename to api_v2/serializers/serializers.py From 63301cf38794abab08adffc0f81328389516ba0d Mon Sep 17 00:00:00 2001 From: BuildTools Date: Sat, 4 Nov 2023 12:31:36 -0500 Subject: [PATCH 04/16] Items and backgrounds split out. --- api_v2/serializers/__init__.py | 5 ++ api_v2/serializers/abstracts.py | 44 ++++++++++++++++ api_v2/serializers/background.py | 0 api_v2/serializers/item.py | 50 ++++++++++++++++++ api_v2/serializers/serializers.py | 85 +------------------------------ 5 files changed, 100 insertions(+), 84 deletions(-) create mode 100644 api_v2/serializers/abstracts.py create mode 100644 api_v2/serializers/background.py create mode 100644 api_v2/serializers/item.py diff --git a/api_v2/serializers/__init__.py b/api_v2/serializers/__init__.py index c2e9fc92..32c737b6 100644 --- a/api_v2/serializers/__init__.py +++ b/api_v2/serializers/__init__.py @@ -1,3 +1,8 @@ """The initialization for serializers for open5e's api v2.""" from .serializers import * + +from .item import ArmorSerializer +from .item import WeaponSerializer +from .item import ItemSerializer +from .item import ItemSetSerializer \ No newline at end of file diff --git a/api_v2/serializers/abstracts.py b/api_v2/serializers/abstracts.py new file mode 100644 index 00000000..4ef63840 --- /dev/null +++ b/api_v2/serializers/abstracts.py @@ -0,0 +1,44 @@ +"""Abstract serializers.""" +from rest_framework import serializers + +from api_v2 import models + + +class GameContentSerializer(serializers.HyperlinkedModelSerializer): + + # Adding dynamic "fields" qs parameter. + def __init__(self, *args, **kwargs): + # Add default fields variable. + + # Instantiate the superclass normally + super(GameContentSerializer, self).__init__(*args, **kwargs) + + # The request doesn't exist when generating an OAS file, so we have to check that first + if self.context['request']: + fields = self.context['request'].query_params.get('fields') + if fields: + fields = fields.split(',') + # Drop any fields that are not specified in the `fields` argument. + allowed = set(fields) + existing = set(self.fields.keys()) + for field_name in existing - allowed: + self.fields.pop(field_name) + + depth = self.context['request'].query_params.get('depth') + if depth: + try: + depth_value = int(depth) + if depth_value > 0 and depth_value < 3: + # This value going above 1 could cause performance issues. + # Limited to 1 and 2 for now. + self.Meta.depth = depth_value + # Depth does not reset by default on subsequent requests with malformed urls. + else: + self.Meta.depth = 0 + except ValueError: + pass # it was not castable to an int. + else: + self.Meta.depth = 0 #The default. + + class Meta: + abstract = True diff --git a/api_v2/serializers/background.py b/api_v2/serializers/background.py new file mode 100644 index 00000000..e69de29b diff --git a/api_v2/serializers/item.py b/api_v2/serializers/item.py new file mode 100644 index 00000000..360b74bc --- /dev/null +++ b/api_v2/serializers/item.py @@ -0,0 +1,50 @@ +"""Serializer for the Item, Itemset, armor, and weapon models""" +from rest_framework import serializers + +from api_v2 import models + +from .abstracts import GameContentSerializer + + +class ArmorSerializer(GameContentSerializer): + key = serializers.ReadOnlyField() + ac_display = serializers.ReadOnlyField() + + class Meta: + model = models.Armor + fields = '__all__' + +class WeaponSerializer(GameContentSerializer): + key = serializers.ReadOnlyField() + is_versatile = serializers.ReadOnlyField() + is_martial = serializers.ReadOnlyField() + is_melee = serializers.ReadOnlyField() + ranged_attack_possible = serializers.ReadOnlyField() + range_melee = serializers.ReadOnlyField() + is_reach = serializers.ReadOnlyField() + properties = serializers.ReadOnlyField() + + class Meta: + model = models.Weapon + fields = '__all__' + + +class ItemSerializer(GameContentSerializer): + key = serializers.ReadOnlyField() + is_magic_item = serializers.ReadOnlyField() + weapon = WeaponSerializer(read_only=True, context={'request': {}}) + armor = ArmorSerializer(read_only=True, context={'request': {}}) + + + class Meta: + model = models.Item + fields = '__all__' + + +class ItemSetSerializer(GameContentSerializer): + key = serializers.ReadOnlyField() + items = ItemSerializer(many=True, read_only=True, context={'request':{}}) + + class Meta: + model = models.ItemSet + fields = '__all__' diff --git a/api_v2/serializers/serializers.py b/api_v2/serializers/serializers.py index cf8641de..e344ff40 100644 --- a/api_v2/serializers/serializers.py +++ b/api_v2/serializers/serializers.py @@ -1,48 +1,8 @@ from math import floor -from rest_framework import serializers from django.core.exceptions import ObjectDoesNotExist -from api_v2 import models - - -class GameContentSerializer(serializers.HyperlinkedModelSerializer): - - # Adding dynamic "fields" qs parameter. - def __init__(self, *args, **kwargs): - # Add default fields variable. - - # Instantiate the superclass normally - super(GameContentSerializer, self).__init__(*args, **kwargs) - - # The request doesn't exist when generating an OAS file, so we have to check that first - if self.context['request']: - fields = self.context['request'].query_params.get('fields') - if fields: - fields = fields.split(',') - # Drop any fields that are not specified in the `fields` argument. - allowed = set(fields) - existing = set(self.fields.keys()) - for field_name in existing - allowed: - self.fields.pop(field_name) - - depth = self.context['request'].query_params.get('depth') - if depth: - try: - depth_value = int(depth) - if depth_value > 0 and depth_value < 3: - # This value going above 1 could cause performance issues. - # Limited to 1 and 2 for now. - self.Meta.depth = depth_value - # Depth does not reset by default on subsequent requests with malformed urls. - else: - self.Meta.depth = 0 - except ValueError: - pass # it was not castable to an int. - else: - self.Meta.depth = 0 #The default. - class Meta: - abstract = True + class RulesetSerializer(serializers.HyperlinkedModelSerializer): @@ -77,49 +37,6 @@ class Meta: fields = "__all__" -class ArmorSerializer(GameContentSerializer): - key = serializers.ReadOnlyField() - ac_display = serializers.ReadOnlyField() - - class Meta: - model = models.Armor - fields = '__all__' - - -class WeaponSerializer(GameContentSerializer): - key = serializers.ReadOnlyField() - is_versatile = serializers.ReadOnlyField() - is_martial = serializers.ReadOnlyField() - is_melee = serializers.ReadOnlyField() - ranged_attack_possible = serializers.ReadOnlyField() - range_melee = serializers.ReadOnlyField() - is_reach = serializers.ReadOnlyField() - properties = serializers.ReadOnlyField() - - class Meta: - model = models.Weapon - fields = '__all__' - - -class ItemSerializer(GameContentSerializer): - key = serializers.ReadOnlyField() - is_magic_item = serializers.ReadOnlyField() - weapon = WeaponSerializer(read_only=True, context={'request': {}}) - armor = ArmorSerializer(read_only=True, context={'request': {}}) - - - class Meta: - model = models.Item - fields = '__all__' - - -class ItemSetSerializer(GameContentSerializer): - key = serializers.ReadOnlyField() - items = ItemSerializer(many=True, read_only=True, context={'request':{}}) - - class Meta: - model = models.ItemSet - fields = '__all__' class FeatBenefitSerializer(serializers.ModelSerializer): class Meta: From 86ce4908cc8574b0d8f27f47a96d44897f3b4bba Mon Sep 17 00:00:00 2001 From: BuildTools Date: Sat, 4 Nov 2023 12:32:41 -0500 Subject: [PATCH 05/16] Adding back in import. --- api_v2/serializers/item.py | 1 - api_v2/serializers/serializers.py | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/api_v2/serializers/item.py b/api_v2/serializers/item.py index 360b74bc..e418fdc0 100644 --- a/api_v2/serializers/item.py +++ b/api_v2/serializers/item.py @@ -1,5 +1,4 @@ """Serializer for the Item, Itemset, armor, and weapon models""" -from rest_framework import serializers from api_v2 import models diff --git a/api_v2/serializers/serializers.py b/api_v2/serializers/serializers.py index e344ff40..e630216d 100644 --- a/api_v2/serializers/serializers.py +++ b/api_v2/serializers/serializers.py @@ -1,8 +1,11 @@ from math import floor from django.core.exceptions import ObjectDoesNotExist +from rest_framework import serializers +from api_v2 import models +from .abstracts import GameContentSerializer class RulesetSerializer(serializers.HyperlinkedModelSerializer): From 7bfd4175197f2401b8f532f8d61d727d35a50816 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Sat, 4 Nov 2023 12:33:14 -0500 Subject: [PATCH 06/16] Adding in another import. --- api_v2/serializers/item.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/api_v2/serializers/item.py b/api_v2/serializers/item.py index e418fdc0..2d78a220 100644 --- a/api_v2/serializers/item.py +++ b/api_v2/serializers/item.py @@ -1,5 +1,7 @@ """Serializer for the Item, Itemset, armor, and weapon models""" +from rest_framework import serializers + from api_v2 import models from .abstracts import GameContentSerializer From 7e3c205f90f8af7ada7e6222034e04cda59da89f Mon Sep 17 00:00:00 2001 From: BuildTools Date: Sat, 4 Nov 2023 12:34:37 -0500 Subject: [PATCH 07/16] Fixing backgrounds. --- api_v2/serializers/__init__.py | 5 ++++- api_v2/serializers/background.py | 23 +++++++++++++++++++++++ api_v2/serializers/serializers.py | 15 --------------- 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/api_v2/serializers/__init__.py b/api_v2/serializers/__init__.py index 32c737b6..f3246309 100644 --- a/api_v2/serializers/__init__.py +++ b/api_v2/serializers/__init__.py @@ -5,4 +5,7 @@ from .item import ArmorSerializer from .item import WeaponSerializer from .item import ItemSerializer -from .item import ItemSetSerializer \ No newline at end of file +from .item import ItemSetSerializer + +from .background import BackgroundBenefitSerializer +from .background import BackgroundSerializer \ No newline at end of file diff --git a/api_v2/serializers/background.py b/api_v2/serializers/background.py index e69de29b..0eeeb692 100644 --- a/api_v2/serializers/background.py +++ b/api_v2/serializers/background.py @@ -0,0 +1,23 @@ +"""Serializer for the BackgroundBenefit and Background models.""" + +from rest_framework import serializers + +from api_v2 import models + +from .abstracts import GameContentSerializer + +class BackgroundBenefitSerializer(serializers.ModelSerializer): + class Meta: + model = models.BackgroundBenefit + fields = ['name','desc','type'] + + +class BackgroundSerializer(GameContentSerializer): + key = serializers.ReadOnlyField() + benefits = BackgroundBenefitSerializer( + many=True + ) + + class Meta: + model = models.Background + fields = '__all__' diff --git a/api_v2/serializers/serializers.py b/api_v2/serializers/serializers.py index e630216d..8e6a47c0 100644 --- a/api_v2/serializers/serializers.py +++ b/api_v2/serializers/serializers.py @@ -289,18 +289,3 @@ def get_actions(self, creature): return result -class BackgroundBenefitSerializer(serializers.ModelSerializer): - class Meta: - model = models.BackgroundBenefit - fields = ['name','desc','type'] - - -class BackgroundSerializer(GameContentSerializer): - key = serializers.ReadOnlyField() - benefits = BackgroundBenefitSerializer( - many=True - ) - - class Meta: - model = models.Background - fields = '__all__' From b1f741e5610d8cb95ae569fd8343f67f6895e418 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Sat, 4 Nov 2023 12:43:11 -0500 Subject: [PATCH 08/16] Adjusting additional serializers. --- api_v2/serializers/__init__.py | 17 +- api_v2/serializers/creature.py | 223 +++++++++++++++++++++++ api_v2/serializers/document.py | 35 ++++ api_v2/serializers/feat.py | 22 +++ api_v2/serializers/race.py | 27 +++ api_v2/serializers/serializers.py | 284 +----------------------------- 6 files changed, 323 insertions(+), 285 deletions(-) create mode 100644 api_v2/serializers/creature.py create mode 100644 api_v2/serializers/document.py create mode 100644 api_v2/serializers/feat.py create mode 100644 api_v2/serializers/race.py diff --git a/api_v2/serializers/__init__.py b/api_v2/serializers/__init__.py index f3246309..ac1a82d2 100644 --- a/api_v2/serializers/__init__.py +++ b/api_v2/serializers/__init__.py @@ -1,6 +1,6 @@ """The initialization for serializers for open5e's api v2.""" -from .serializers import * +#from .serializers import * from .item import ArmorSerializer from .item import WeaponSerializer @@ -8,4 +8,17 @@ from .item import ItemSetSerializer from .background import BackgroundBenefitSerializer -from .background import BackgroundSerializer \ No newline at end of file +from .background import BackgroundSerializer + +from .document import RulesetSerializer +from .document import LicenseSerializer +from .document import PublisherSerializer +from .document import DocumentSerializer + +from .feat import FeatBenefitSerializer +from .feat import FeatSerializer + +from .race import TraitSerializer +from .race import RaceSerializer + +from .creature import CreatureSerializer \ No newline at end of file diff --git a/api_v2/serializers/creature.py b/api_v2/serializers/creature.py new file mode 100644 index 00000000..631f3f7c --- /dev/null +++ b/api_v2/serializers/creature.py @@ -0,0 +1,223 @@ +"""Serializers and helper methods for the Creature model.""" + +from rest_framework import serializers + +from api_v2 import models + +from .abstracts import GameContentSerializer + + + +def calc_damage_amount(die_count, die_type, bonus): + die_values = { + 'D4': 2.5, + 'D6': 3.5, + 'D8': 4.5, + 'D10': 5.5, + 'D12': 6.5, + 'D20': 10.5, + } + return floor(die_count * die_values[die_type] + bonus) + +def make_damage_obj(die_count, die_type, bonus, damage_type): + if die_count: + return { + 'amount': calc_damage_amount( + die_count, + die_type, + bonus + ), + 'die_count': die_count, + 'die_type': die_type, + 'bonus': bonus, + 'type': damage_type, + } + return { + 'amount': 1, + 'type': damage_type, + } + +def make_attack_obj(attack): + + obj = { + 'name': attack.name, + 'attack_type': attack.attack_type, + 'to_hit_mod': attack.to_hit_mod, + } + + if attack.reach_ft: + obj['reach_ft'] = attack.reach_ft + if attack.range_ft: + obj['range_ft'] = attack.range_ft + if attack.long_range_ft: + obj['long_range_ft'] = attack.long_range_ft + + obj['target_creature_only'] = attack.target_creature_only + + if attack.damage_type: + obj['damage'] = make_damage_obj( + attack.damage_die_count, + attack.damage_die_type, + attack.damage_bonus, + attack.damage_type + ) + + if attack.extra_damage_type: + obj['extra_damage'] = make_damage_obj( + attack.extra_damage_die_count, + attack.extra_damage_die_type, + attack.extra_damage_bonus, + attack.extra_damage_type + ) + + return obj + +def make_action_obj(action): + + obj = { 'name': action.name, 'desc': action.desc } + + match action.uses_type: + case 'PER_DAY': + obj['uses_per_day'] = action.uses_param + case 'RECHARGE_ON_ROLL': + obj['recharge_on_roll'] = action.uses_param + case 'RECHARGE_AFTER_REST': + obj['recharge_after_rest'] = True + + attacks = action.creatureattack_set.all() + + if len(attacks) > 0: + obj['attacks'] = [make_attack_obj(attack) for attack in attacks] + + return obj + +class CreatureSerializer(GameContentSerializer): + + key = serializers.ReadOnlyField() + ability_scores = serializers.SerializerMethodField() + modifiers = serializers.SerializerMethodField() + saving_throws = serializers.SerializerMethodField() + all_saving_throws = serializers.SerializerMethodField() + skill_bonuses = serializers.SerializerMethodField() + all_skill_bonuses = serializers.SerializerMethodField() + actions = serializers.SerializerMethodField() + + class Meta: + model = models.Creature + fields = [ + 'url', + 'document', + 'key', + 'name', + 'category', + 'size', + 'type', + 'subtype', + 'alignment', + 'weight', + 'armor_class', + 'hit_points', + 'ability_scores', + 'modifiers', + 'saving_throws', + 'all_saving_throws', + 'skill_bonuses', + 'all_skill_bonuses', + 'passive_perception', + 'actions', + ] + + def get_ability_scores(self, creature): + return creature.get_ability_scores() + + def get_modifiers(self, creature): + return creature.get_modifiers() + + def get_saving_throws(self, creature): + entries = creature.get_saving_throws().items() + return { key: value for key, value in entries if value is not None } + + def get_all_saving_throws(self, creature): + defaults = creature.get_modifiers() + entries = creature.get_saving_throws().items() + return { key: (defaults[key] if value is None else value) for key, value in entries } + + def get_skill_bonuses(self, creature): + entries = creature.get_skill_bonuses().items() + return { key: value for key, value in entries if value is not None } + + def get_all_skill_bonuses(self, creature): + defaults = { + 'acrobatics': creature.modifier_dexterity, + 'animal_handling': creature.modifier_wisdom, + 'arcana': creature.modifier_intelligence, + 'athletics': creature.modifier_strength, + 'deception': creature.modifier_charisma, + 'history': creature.modifier_intelligence, + 'insight': creature.modifier_wisdom, + 'intimidation': creature.modifier_charisma, + 'investigation': creature.modifier_intelligence, + 'medicine': creature.modifier_wisdom, + 'nature': creature.modifier_intelligence, + 'perception': creature.modifier_wisdom, + 'performance': creature.modifier_charisma, + 'persuasion': creature.modifier_charisma, + 'religion': creature.modifier_intelligence, + 'sleight_of_hand': creature.modifier_dexterity, + 'stealth': creature.modifier_dexterity, + 'survival': creature.modifier_wisdom, + } + entries = creature.get_skill_bonuses().items() + return { key: (defaults[key] if value is None else value) for key, value in entries } + + def get_actions(self, creature): + result = [] + for action in creature.creatureaction_set.all(): + # item = { 'name': action.name, 'desc': action.desc } + # match action.uses_type: + # case 'PER_DAY': + # item['uses_per_day'] = action.uses_param + # case 'RECHARGE_ON_ROLL': + # item['recharge_on_roll'] = action.uses_param + # case 'RECHARGE_AFTER_REST': + # item['recharge_after_rest'] = True + # try: + # attack = models.CreatureAttackAction.objects.get(pk=action.key) + # item['attack_type'] = attack.attack_type + # item['to_hit_mod'] = attack.to_hit_mod + # if attack.reach_ft: + # item['reach_ft'] = attack.reach_ft + # if attack.range_ft: + # item['range_ft'] = attack.range_ft + # if attack.long_range_ft: + # item['long_range_ft'] = attack.long_range_ft + # item['target_creature_only'] = attack.target_creature_only + # if attack.damage_type: + # item['damage'] = make_damage_obj( + # attack.damage_die_count, + # attack.damage_die_type, + # attack.damage_bonus, + # attack.damage_type + # ) + # if attack.extra_damage_type: + # item['extra_damage'] = make_damage_obj( + # attack.extra_damage_die_count, + # attack.extra_damage_die_type, + # attack.extra_damage_bonus, + # attack.extra_damage_type + # ) + # if attack.versatile_weapon: + # item['two_handed_damage'] = make_damage_obj( + # attack.damage_die_count, + # attack.versatile_weapon, + # attack.damage_bonus, + # attack.damage_type + # ) + # except ObjectDoesNotExist: + # pass + # result.append(item) + action_obj = make_action_obj(action) + result.append(action_obj) + return result + + diff --git a/api_v2/serializers/document.py b/api_v2/serializers/document.py new file mode 100644 index 00000000..811140be --- /dev/null +++ b/api_v2/serializers/document.py @@ -0,0 +1,35 @@ +"""Serializers for Ruleset, License, Publisher, and Document models.""" +from rest_framework import serializers + +from api_v2 import models + +class RulesetSerializer(serializers.HyperlinkedModelSerializer): + key = serializers.ReadOnlyField() + + class Meta: + model = models.Ruleset + fields = '__all__' + + +class LicenseSerializer(serializers.HyperlinkedModelSerializer): + key = serializers.ReadOnlyField() + + class Meta: + model = models.License + fields = '__all__' + + +class PublisherSerializer(serializers.HyperlinkedModelSerializer): + key = serializers.ReadOnlyField() + + class Meta: + model = models.Publisher + fields = '__all__' + + +class DocumentSerializer(serializers.HyperlinkedModelSerializer): + key = serializers.ReadOnlyField() + + class Meta: + model = models.Document + fields = "__all__" \ No newline at end of file diff --git a/api_v2/serializers/feat.py b/api_v2/serializers/feat.py new file mode 100644 index 00000000..1b6c3d9f --- /dev/null +++ b/api_v2/serializers/feat.py @@ -0,0 +1,22 @@ +"""Serializer for the FeatBenefitSerializer and FeatSerializer models.""" + +from rest_framework import serializers + +from api_v2 import models + +from .abstracts import GameContentSerializer + +class FeatBenefitSerializer(serializers.ModelSerializer): + class Meta: + model = models.FeatBenefit + fields = ['desc'] + +class FeatSerializer(GameContentSerializer): + key = serializers.ReadOnlyField() + has_prerequisite = serializers.ReadOnlyField() + benefits = FeatBenefitSerializer( + many=True) + + class Meta: + model = models.Feat + fields = '__all__' diff --git a/api_v2/serializers/race.py b/api_v2/serializers/race.py new file mode 100644 index 00000000..22c3d1b3 --- /dev/null +++ b/api_v2/serializers/race.py @@ -0,0 +1,27 @@ +"""Serializers for the Trait and Race models.""" + +from rest_framework import serializers + +from api_v2 import models + +from .abstracts import GameContentSerializer + + +class TraitSerializer(serializers.ModelSerializer): + + class Meta: + model = models.Trait + fields = ['name', 'desc'] + + +class RaceSerializer(GameContentSerializer): + key = serializers.ReadOnlyField() + is_subrace = serializers.ReadOnlyField() + is_selectable = serializers.ReadOnlyField() + traits = TraitSerializer( + many=True) + + class Meta: + model = models.Race + fields = '__all__' + diff --git a/api_v2/serializers/serializers.py b/api_v2/serializers/serializers.py index 8e6a47c0..2da45383 100644 --- a/api_v2/serializers/serializers.py +++ b/api_v2/serializers/serializers.py @@ -1,291 +1,9 @@ from math import floor from django.core.exceptions import ObjectDoesNotExist - from rest_framework import serializers + from api_v2 import models from .abstracts import GameContentSerializer - -class RulesetSerializer(serializers.HyperlinkedModelSerializer): - key = serializers.ReadOnlyField() - - class Meta: - model = models.Ruleset - fields = '__all__' - - -class LicenseSerializer(serializers.HyperlinkedModelSerializer): - key = serializers.ReadOnlyField() - - class Meta: - model = models.License - fields = '__all__' - - -class PublisherSerializer(serializers.HyperlinkedModelSerializer): - key = serializers.ReadOnlyField() - - class Meta: - model = models.Publisher - fields = '__all__' - - -class DocumentSerializer(serializers.HyperlinkedModelSerializer): - key = serializers.ReadOnlyField() - - class Meta: - model = models.Document - fields = "__all__" - - - -class FeatBenefitSerializer(serializers.ModelSerializer): - class Meta: - model = models.FeatBenefit - fields = ['desc'] - -class FeatSerializer(GameContentSerializer): - key = serializers.ReadOnlyField() - has_prerequisite = serializers.ReadOnlyField() - benefits = FeatBenefitSerializer( - many=True) - - class Meta: - model = models.Feat - fields = '__all__' - - -class TraitSerializer(serializers.ModelSerializer): - - class Meta: - model = models.Trait - fields = ['name', 'desc'] - - -class RaceSerializer(GameContentSerializer): - key = serializers.ReadOnlyField() - is_subrace = serializers.ReadOnlyField() - is_selectable = serializers.ReadOnlyField() - traits = TraitSerializer( - many=True) - - class Meta: - model = models.Race - fields = '__all__' - - -def calc_damage_amount(die_count, die_type, bonus): - die_values = { - 'D4': 2.5, - 'D6': 3.5, - 'D8': 4.5, - 'D10': 5.5, - 'D12': 6.5, - 'D20': 10.5, - } - return floor(die_count * die_values[die_type] + bonus) - -def make_damage_obj(die_count, die_type, bonus, damage_type): - if die_count: - return { - 'amount': calc_damage_amount( - die_count, - die_type, - bonus - ), - 'die_count': die_count, - 'die_type': die_type, - 'bonus': bonus, - 'type': damage_type, - } - return { - 'amount': 1, - 'type': damage_type, - } - -def make_attack_obj(attack): - - obj = { - 'name': attack.name, - 'attack_type': attack.attack_type, - 'to_hit_mod': attack.to_hit_mod, - } - - if attack.reach_ft: - obj['reach_ft'] = attack.reach_ft - if attack.range_ft: - obj['range_ft'] = attack.range_ft - if attack.long_range_ft: - obj['long_range_ft'] = attack.long_range_ft - - obj['target_creature_only'] = attack.target_creature_only - - if attack.damage_type: - obj['damage'] = make_damage_obj( - attack.damage_die_count, - attack.damage_die_type, - attack.damage_bonus, - attack.damage_type - ) - - if attack.extra_damage_type: - obj['extra_damage'] = make_damage_obj( - attack.extra_damage_die_count, - attack.extra_damage_die_type, - attack.extra_damage_bonus, - attack.extra_damage_type - ) - - return obj - -def make_action_obj(action): - - obj = { 'name': action.name, 'desc': action.desc } - - match action.uses_type: - case 'PER_DAY': - obj['uses_per_day'] = action.uses_param - case 'RECHARGE_ON_ROLL': - obj['recharge_on_roll'] = action.uses_param - case 'RECHARGE_AFTER_REST': - obj['recharge_after_rest'] = True - - attacks = action.creatureattack_set.all() - - if len(attacks) > 0: - obj['attacks'] = [make_attack_obj(attack) for attack in attacks] - - return obj - -class CreatureSerializer(GameContentSerializer): - - key = serializers.ReadOnlyField() - ability_scores = serializers.SerializerMethodField() - modifiers = serializers.SerializerMethodField() - saving_throws = serializers.SerializerMethodField() - all_saving_throws = serializers.SerializerMethodField() - skill_bonuses = serializers.SerializerMethodField() - all_skill_bonuses = serializers.SerializerMethodField() - actions = serializers.SerializerMethodField() - - class Meta: - model = models.Creature - fields = [ - 'url', - 'document', - 'key', - 'name', - 'category', - 'size', - 'type', - 'subtype', - 'alignment', - 'weight', - 'armor_class', - 'hit_points', - 'ability_scores', - 'modifiers', - 'saving_throws', - 'all_saving_throws', - 'skill_bonuses', - 'all_skill_bonuses', - 'passive_perception', - 'actions', - ] - - def get_ability_scores(self, creature): - return creature.get_ability_scores() - - def get_modifiers(self, creature): - return creature.get_modifiers() - - def get_saving_throws(self, creature): - entries = creature.get_saving_throws().items() - return { key: value for key, value in entries if value is not None } - - def get_all_saving_throws(self, creature): - defaults = creature.get_modifiers() - entries = creature.get_saving_throws().items() - return { key: (defaults[key] if value is None else value) for key, value in entries } - - def get_skill_bonuses(self, creature): - entries = creature.get_skill_bonuses().items() - return { key: value for key, value in entries if value is not None } - - def get_all_skill_bonuses(self, creature): - defaults = { - 'acrobatics': creature.modifier_dexterity, - 'animal_handling': creature.modifier_wisdom, - 'arcana': creature.modifier_intelligence, - 'athletics': creature.modifier_strength, - 'deception': creature.modifier_charisma, - 'history': creature.modifier_intelligence, - 'insight': creature.modifier_wisdom, - 'intimidation': creature.modifier_charisma, - 'investigation': creature.modifier_intelligence, - 'medicine': creature.modifier_wisdom, - 'nature': creature.modifier_intelligence, - 'perception': creature.modifier_wisdom, - 'performance': creature.modifier_charisma, - 'persuasion': creature.modifier_charisma, - 'religion': creature.modifier_intelligence, - 'sleight_of_hand': creature.modifier_dexterity, - 'stealth': creature.modifier_dexterity, - 'survival': creature.modifier_wisdom, - } - entries = creature.get_skill_bonuses().items() - return { key: (defaults[key] if value is None else value) for key, value in entries } - - def get_actions(self, creature): - result = [] - for action in creature.creatureaction_set.all(): - # item = { 'name': action.name, 'desc': action.desc } - # match action.uses_type: - # case 'PER_DAY': - # item['uses_per_day'] = action.uses_param - # case 'RECHARGE_ON_ROLL': - # item['recharge_on_roll'] = action.uses_param - # case 'RECHARGE_AFTER_REST': - # item['recharge_after_rest'] = True - # try: - # attack = models.CreatureAttackAction.objects.get(pk=action.key) - # item['attack_type'] = attack.attack_type - # item['to_hit_mod'] = attack.to_hit_mod - # if attack.reach_ft: - # item['reach_ft'] = attack.reach_ft - # if attack.range_ft: - # item['range_ft'] = attack.range_ft - # if attack.long_range_ft: - # item['long_range_ft'] = attack.long_range_ft - # item['target_creature_only'] = attack.target_creature_only - # if attack.damage_type: - # item['damage'] = make_damage_obj( - # attack.damage_die_count, - # attack.damage_die_type, - # attack.damage_bonus, - # attack.damage_type - # ) - # if attack.extra_damage_type: - # item['extra_damage'] = make_damage_obj( - # attack.extra_damage_die_count, - # attack.extra_damage_die_type, - # attack.extra_damage_bonus, - # attack.extra_damage_type - # ) - # if attack.versatile_weapon: - # item['two_handed_damage'] = make_damage_obj( - # attack.damage_die_count, - # attack.versatile_weapon, - # attack.damage_bonus, - # attack.damage_type - # ) - # except ObjectDoesNotExist: - # pass - # result.append(item) - action_obj = make_action_obj(action) - result.append(action_obj) - return result - - From a71b7f718986dd16657d6ebec029025fc1677cc0 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Sat, 4 Nov 2023 12:44:27 -0500 Subject: [PATCH 09/16] Fixing an import. --- api_v2/serializers/creature.py | 2 ++ api_v2/serializers/serializers.py | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/api_v2/serializers/creature.py b/api_v2/serializers/creature.py index 631f3f7c..23866dae 100644 --- a/api_v2/serializers/creature.py +++ b/api_v2/serializers/creature.py @@ -1,5 +1,7 @@ """Serializers and helper methods for the Creature model.""" +from math import floor + from rest_framework import serializers from api_v2 import models diff --git a/api_v2/serializers/serializers.py b/api_v2/serializers/serializers.py index 2da45383..978c8778 100644 --- a/api_v2/serializers/serializers.py +++ b/api_v2/serializers/serializers.py @@ -1,4 +1,3 @@ -from math import floor from django.core.exceptions import ObjectDoesNotExist from rest_framework import serializers From 42e4f410dee327a09bf9cb01571a011e8a56f79d Mon Sep 17 00:00:00 2001 From: BuildTools Date: Sat, 4 Nov 2023 12:54:59 -0500 Subject: [PATCH 10/16] Bringing creaturetype out. --- api_v2/serializers/__init__.py | 3 +- api_v2/serializers/creature.py | 7 +++- api_v2/views/__init__.py | 5 ++- api_v2/views/creature.py | 65 ++++++++++++++++++++++++++++++++++ api_v2/views/views.py | 54 ---------------------------- server/urls.py | 1 + 6 files changed, 78 insertions(+), 57 deletions(-) create mode 100644 api_v2/views/creature.py diff --git a/api_v2/serializers/__init__.py b/api_v2/serializers/__init__.py index ac1a82d2..aef30944 100644 --- a/api_v2/serializers/__init__.py +++ b/api_v2/serializers/__init__.py @@ -21,4 +21,5 @@ from .race import TraitSerializer from .race import RaceSerializer -from .creature import CreatureSerializer \ No newline at end of file +from .creature import CreatureSerializer +from .creature import CreatureTypeSerializer \ No newline at end of file diff --git a/api_v2/serializers/creature.py b/api_v2/serializers/creature.py index 23866dae..3ef8ea07 100644 --- a/api_v2/serializers/creature.py +++ b/api_v2/serializers/creature.py @@ -114,7 +114,6 @@ class Meta: 'category', 'size', 'type', - 'subtype', 'alignment', 'weight', 'armor_class', @@ -223,3 +222,9 @@ def get_actions(self, creature): return result +class CreatureTypeSerializer(GameContentSerializer): + key = serializers.ReadOnlyField() + + class Meta: + model = models.CreatureType + fields = '__all__' diff --git a/api_v2/views/__init__.py b/api_v2/views/__init__.py index 74e35f0b..67c817ca 100644 --- a/api_v2/views/__init__.py +++ b/api_v2/views/__init__.py @@ -1,3 +1,6 @@ """The initialization for views for open5e's api v2.""" -from .views import * \ No newline at end of file +from .views import * + +from .creature import CreatureFilterSet, CreatureViewSet +from .creature import CreatureTypeViewSet \ No newline at end of file diff --git a/api_v2/views/creature.py b/api_v2/views/creature.py new file mode 100644 index 00000000..dc5146da --- /dev/null +++ b/api_v2/views/creature.py @@ -0,0 +1,65 @@ +from rest_framework import viewsets + +from django_filters import FilterSet + +from api_v2 import models +from api_v2 import serializers + + +class CreatureFilterSet(FilterSet): + + class Meta: + model = models.Creature + fields = { + 'key': ['in', 'iexact', 'exact' ], + 'name': ['iexact', 'exact'], + 'document__key': ['in','iexact','exact'], + 'size': ['exact'], + 'armor_class': ['exact','lt','lte','gt','gte'], + 'ability_score_strength': ['exact','lt','lte','gt','gte'], + 'ability_score_dexterity': ['exact','lt','lte','gt','gte'], + 'ability_score_constitution': ['exact','lt','lte','gt','gte'], + 'ability_score_intelligence': ['exact','lt','lte','gt','gte'], + 'ability_score_wisdom': ['exact','lt','lte','gt','gte'], + 'ability_score_charisma': ['exact','lt','lte','gt','gte'], + 'saving_throw_charisma': ['isnull'], + 'saving_throw_strength': ['isnull'], + 'saving_throw_dexterity': ['isnull'], + 'saving_throw_constitution': ['isnull'], + 'saving_throw_intelligence': ['isnull'], + 'saving_throw_wisdom': ['isnull'], + 'saving_throw_charisma': ['isnull'], + 'skill_bonus_acrobatics': ['isnull'], + 'skill_bonus_animal_handling': ['isnull'], + 'skill_bonus_arcana': ['isnull'], + 'skill_bonus_athletics': ['isnull'], + 'skill_bonus_deception': ['isnull'], + 'skill_bonus_history': ['isnull'], + 'skill_bonus_insight': ['isnull'], + 'skill_bonus_intimidation': ['isnull'], + 'skill_bonus_investigation': ['isnull'], + 'skill_bonus_medicine': ['isnull'], + 'skill_bonus_nature': ['isnull'], + 'skill_bonus_perception': ['isnull'], + 'skill_bonus_performance': ['isnull'], + 'skill_bonus_persuasion': ['isnull'], + 'skill_bonus_religion': ['isnull'], + 'skill_bonus_sleight_of_hand': ['isnull'], + 'skill_bonus_stealth': ['isnull'], + 'skill_bonus_survival': ['isnull'], + 'passive_perception': ['exact','lt','lte','gt','gte'], + } + +class CreatureViewSet(viewsets.ReadOnlyModelViewSet): + """ + list: API endpoint for returning a list of creatures. + retrieve: API endpoint for returning a particular creature. + """ + queryset = models.Creature.objects.all().order_by('pk') + serializer_class = serializers.CreatureSerializer + filterset_class = CreatureFilterSet + + +class CreatureTypeViewSet(viewsets.ReadOnlyModelViewSet): + queryset = models.CreatureType.objects.all().order_by('pk') + serializer_class = serializers.CreatureTypeSerializer \ No newline at end of file diff --git a/api_v2/views/views.py b/api_v2/views/views.py index 84bfb5b7..ef9c3646 100644 --- a/api_v2/views/views.py +++ b/api_v2/views/views.py @@ -184,60 +184,6 @@ class FeatViewSet(viewsets.ReadOnlyModelViewSet): serializer_class = serializers.FeatSerializer filterset_class = FeatFilterSet - -class CreatureFilterSet(FilterSet): - - class Meta: - model = models.Creature - fields = { - 'key': ['in', 'iexact', 'exact' ], - 'name': ['iexact', 'exact'], - 'document__key': ['in','iexact','exact'], - 'size': ['exact'], - 'armor_class': ['exact','lt','lte','gt','gte'], - 'ability_score_strength': ['exact','lt','lte','gt','gte'], - 'ability_score_dexterity': ['exact','lt','lte','gt','gte'], - 'ability_score_constitution': ['exact','lt','lte','gt','gte'], - 'ability_score_intelligence': ['exact','lt','lte','gt','gte'], - 'ability_score_wisdom': ['exact','lt','lte','gt','gte'], - 'ability_score_charisma': ['exact','lt','lte','gt','gte'], - 'saving_throw_charisma': ['isnull'], - 'saving_throw_strength': ['isnull'], - 'saving_throw_dexterity': ['isnull'], - 'saving_throw_constitution': ['isnull'], - 'saving_throw_intelligence': ['isnull'], - 'saving_throw_wisdom': ['isnull'], - 'saving_throw_charisma': ['isnull'], - 'skill_bonus_acrobatics': ['isnull'], - 'skill_bonus_animal_handling': ['isnull'], - 'skill_bonus_arcana': ['isnull'], - 'skill_bonus_athletics': ['isnull'], - 'skill_bonus_deception': ['isnull'], - 'skill_bonus_history': ['isnull'], - 'skill_bonus_insight': ['isnull'], - 'skill_bonus_intimidation': ['isnull'], - 'skill_bonus_investigation': ['isnull'], - 'skill_bonus_medicine': ['isnull'], - 'skill_bonus_nature': ['isnull'], - 'skill_bonus_perception': ['isnull'], - 'skill_bonus_performance': ['isnull'], - 'skill_bonus_persuasion': ['isnull'], - 'skill_bonus_religion': ['isnull'], - 'skill_bonus_sleight_of_hand': ['isnull'], - 'skill_bonus_stealth': ['isnull'], - 'skill_bonus_survival': ['isnull'], - 'passive_perception': ['exact','lt','lte','gt','gte'], - } - -class CreatureViewSet(viewsets.ReadOnlyModelViewSet): - """ - list: API endpoint for returning a list of creatures. - retrieve: API endpoint for returning a particular creature. - """ - queryset = models.Creature.objects.all().order_by('pk') - serializer_class = serializers.CreatureSerializer - filterset_class = CreatureFilterSet - class RaceFilterSet(FilterSet): class Meta: diff --git a/server/urls.py b/server/urls.py index a6c59aa1..8312c2de 100644 --- a/server/urls.py +++ b/server/urls.py @@ -64,6 +64,7 @@ router_v2.register(r'feats',views_v2.FeatViewSet) router_v2.register(r'races',views_v2.RaceViewSet) router_v2.register(r'creatures',views_v2.CreatureViewSet) + router_v2.register(r'creaturetype',views_v2.CreatureTypeViewSet) # Wire up our API using automatic URL routing. # Additionally, we include login URLs for the browsable API. From e2ae29526c893b07e80c821303691c6bbe593a77 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Sat, 4 Nov 2023 12:57:47 -0500 Subject: [PATCH 11/16] Backgrounds working. --- api_v2/views/__init__.py | 4 +++- api_v2/views/background.py | 29 +++++++++++++++++++++++++++++ api_v2/views/views.py | 18 ------------------ 3 files changed, 32 insertions(+), 19 deletions(-) create mode 100644 api_v2/views/background.py diff --git a/api_v2/views/__init__.py b/api_v2/views/__init__.py index 67c817ca..d04e5dea 100644 --- a/api_v2/views/__init__.py +++ b/api_v2/views/__init__.py @@ -3,4 +3,6 @@ from .views import * from .creature import CreatureFilterSet, CreatureViewSet -from .creature import CreatureTypeViewSet \ No newline at end of file +from .creature import CreatureTypeViewSet + +from .background import BackgroundFilterSet, BackgroundViewSet \ No newline at end of file diff --git a/api_v2/views/background.py b/api_v2/views/background.py new file mode 100644 index 00000000..534b7461 --- /dev/null +++ b/api_v2/views/background.py @@ -0,0 +1,29 @@ +"""Viewset and Filterset for the Background Serializers.""" +from rest_framework import viewsets + +from django_filters import FilterSet + +from api_v2 import models +from api_v2 import serializers + + + + +class BackgroundFilterSet(FilterSet): + class Meta: + model = models.Background + fields = { + 'key': ['in', 'iexact', 'exact'], + 'name': ['iexact', 'exact'], + 'document__key': ['in', 'iexact', 'exact'], + } + + +class BackgroundViewSet(viewsets.ReadOnlyModelViewSet): + """ + list: API endpoint for returning a list of backgrounds. + retrieve: API endpoint for returning a particular background. + """ + queryset = models.Background.objects.all().order_by('pk') + serializer_class = serializers.BackgroundSerializer + filterset_class = BackgroundFilterSet diff --git a/api_v2/views/views.py b/api_v2/views/views.py index ef9c3646..728a611b 100644 --- a/api_v2/views/views.py +++ b/api_v2/views/views.py @@ -205,21 +205,3 @@ class RaceViewSet(viewsets.ReadOnlyModelViewSet): filterset_class = RaceFilterSet -class BackgroundFilterSet(FilterSet): - class Meta: - model = models.Background - fields = { - 'key': ['in', 'iexact', 'exact'], - 'name': ['iexact', 'exact'], - 'document__key': ['in', 'iexact', 'exact'], - } - - -class BackgroundViewSet(viewsets.ReadOnlyModelViewSet): - """ - list: API endpoint for returning a list of backgrounds. - retrieve: API endpoint for returning a particular background. - """ - queryset = models.Background.objects.all().order_by('pk') - serializer_class = serializers.BackgroundSerializer - filterset_class = BackgroundFilterSet From bf03d2c772041da0690d0f7266569e398d83298f Mon Sep 17 00:00:00 2001 From: BuildTools Date: Sat, 4 Nov 2023 13:00:07 -0500 Subject: [PATCH 12/16] Splitting Documents. --- api_v2/views/__init__.py | 7 +++++- api_v2/views/document.py | 48 ++++++++++++++++++++++++++++++++++++++++ api_v2/views/views.py | 39 -------------------------------- 3 files changed, 54 insertions(+), 40 deletions(-) create mode 100644 api_v2/views/document.py diff --git a/api_v2/views/__init__.py b/api_v2/views/__init__.py index d04e5dea..47a0f8d3 100644 --- a/api_v2/views/__init__.py +++ b/api_v2/views/__init__.py @@ -5,4 +5,9 @@ from .creature import CreatureFilterSet, CreatureViewSet from .creature import CreatureTypeViewSet -from .background import BackgroundFilterSet, BackgroundViewSet \ No newline at end of file +from .background import BackgroundFilterSet, BackgroundViewSet + +from .document import DocumentViewSet +from .document import RulesetViewSet +from .document import PublisherViewSet +from .document import LicenseViewSet \ No newline at end of file diff --git a/api_v2/views/document.py b/api_v2/views/document.py new file mode 100644 index 00000000..37419fc9 --- /dev/null +++ b/api_v2/views/document.py @@ -0,0 +1,48 @@ +"""Viewsets for the Document, Ruleset, Publisher, and License Serializers.""" +from rest_framework import viewsets + +from django_filters import FilterSet + +from api_v2 import models +from api_v2 import serializers + + + +class RulesetViewSet(viewsets.ReadOnlyModelViewSet): + """" + list: API Endpoint for returning a set of rulesets. + + retrieve: API endpoint for return a particular ruleset. + """ + queryset = models.Ruleset.objects.all().order_by('pk') + serializer_class = serializers.RulesetSerializer + + +class DocumentViewSet(viewsets.ReadOnlyModelViewSet): + """ + list: API endpoint for returning a list of documents. + retrieve: API endpoint for returning a particular document. + """ + queryset = models.Document.objects.all().order_by('pk') + serializer_class = serializers.DocumentSerializer + filterset_fields = '__all__' + + +class PublisherViewSet(viewsets.ReadOnlyModelViewSet): + """ + list: API endpoint for returning a list of publishers. + retrieve: API endpoint for returning a particular publisher. + """ + queryset = models.Publisher.objects.all().order_by('pk') + serializer_class = serializers.PublisherSerializer + filterset_fields = '__all__' + + +class LicenseViewSet(viewsets.ReadOnlyModelViewSet): + """ + list: API endpoint for returning a list of licenses. + retrieve: API endpoint for returning a particular license. + """ + queryset = models.License.objects.all().order_by('pk') + serializer_class = serializers.LicenseSerializer + filterset_fields = '__all__' diff --git a/api_v2/views/views.py b/api_v2/views/views.py index 728a611b..a102fc11 100644 --- a/api_v2/views/views.py +++ b/api_v2/views/views.py @@ -60,45 +60,6 @@ class ItemSetViewSet(viewsets.ReadOnlyModelViewSet): filterset_class = ItemSetFilterSet -class RulesetViewSet(viewsets.ReadOnlyModelViewSet): - """" - list: API Endpoint for returning a set of rulesets. - - retrieve: API endpoint for return a particular ruleset. - """ - queryset = models.Ruleset.objects.all().order_by('pk') - serializer_class = serializers.RulesetSerializer - - -class DocumentViewSet(viewsets.ReadOnlyModelViewSet): - """ - list: API endpoint for returning a list of documents. - retrieve: API endpoint for returning a particular document. - """ - queryset = models.Document.objects.all().order_by('pk') - serializer_class = serializers.DocumentSerializer - filterset_fields = '__all__' - - -class PublisherViewSet(viewsets.ReadOnlyModelViewSet): - """ - list: API endpoint for returning a list of publishers. - retrieve: API endpoint for returning a particular publisher. - """ - queryset = models.Publisher.objects.all().order_by('pk') - serializer_class = serializers.PublisherSerializer - filterset_fields = '__all__' - - -class LicenseViewSet(viewsets.ReadOnlyModelViewSet): - """ - list: API endpoint for returning a list of licenses. - retrieve: API endpoint for returning a particular license. - """ - queryset = models.License.objects.all().order_by('pk') - serializer_class = serializers.LicenseSerializer - filterset_fields = '__all__' - class WeaponFilterSet(FilterSet): From 1f3fa97ac131990266edb13e91d5b6f857afdece Mon Sep 17 00:00:00 2001 From: BuildTools Date: Sat, 4 Nov 2023 13:03:04 -0500 Subject: [PATCH 13/16] Getting items back online. --- api_v2/views/__init__.py | 11 +++- api_v2/views/item.py | 123 +++++++++++++++++++++++++++++++++++++++ api_v2/views/views.py | 117 ------------------------------------- 3 files changed, 131 insertions(+), 120 deletions(-) create mode 100644 api_v2/views/item.py diff --git a/api_v2/views/__init__.py b/api_v2/views/__init__.py index 47a0f8d3..73dacbf9 100644 --- a/api_v2/views/__init__.py +++ b/api_v2/views/__init__.py @@ -2,12 +2,17 @@ from .views import * +from .background import BackgroundFilterSet, BackgroundViewSet + from .creature import CreatureFilterSet, CreatureViewSet from .creature import CreatureTypeViewSet -from .background import BackgroundFilterSet, BackgroundViewSet - from .document import DocumentViewSet from .document import RulesetViewSet from .document import PublisherViewSet -from .document import LicenseViewSet \ No newline at end of file +from .document import LicenseViewSet + +from .item import ItemFilterSet, ItemViewSet +from .item import ItemSetFilterSet, ItemSetViewSet +from .item import ArmorFilterSet, ArmorViewSet +from .item import WeaponFilterSet, WeaponViewSet \ No newline at end of file diff --git a/api_v2/views/item.py b/api_v2/views/item.py new file mode 100644 index 00000000..dc51458f --- /dev/null +++ b/api_v2/views/item.py @@ -0,0 +1,123 @@ +from rest_framework import viewsets + +from django_filters import FilterSet +from django_filters import BooleanFilter + + +from api_v2 import models +from api_v2 import serializers + +class ItemFilterSet(FilterSet): + is_magic_item = BooleanFilter(field_name='rarity', lookup_expr='isnull', exclude=True) + + class Meta: + model = models.Item + fields = { + 'key': ['in', 'iexact', 'exact' ], + 'name': ['iexact', 'exact'], + 'desc': ['icontains'], + 'cost': ['exact', 'range', 'gt', 'gte', 'lt', 'lte'], + 'weight': ['exact', 'range', 'gt', 'gte', 'lt', 'lte'], + 'rarity': ['exact', 'in', ], + 'requires_attunement': ['exact'], + 'category': ['in', 'iexact', 'exact'], + 'document__key': ['in','iexact','exact'] + } + + +class ItemViewSet(viewsets.ReadOnlyModelViewSet): + """ + list: API endpoint for returning a list of items. + + retrieve: API endpoint for returning a particular item. + """ + queryset = models.Item.objects.all().order_by('pk') + serializer_class = serializers.ItemSerializer + filterset_class = ItemFilterSet + + +class ItemSetFilterSet(FilterSet): + + class Meta: + model = models.ItemSet + fields = { + 'key': ['in', 'iexact', 'exact' ], + 'name': ['iexact', 'exact'], + 'document__key': ['in','iexact','exact'] + } + + +class ItemSetViewSet(viewsets.ReadOnlyModelViewSet): + """" + list: API Endpoint for returning a set of itemsets. + + retrieve: API endpoint for return a particular itemset. + """ + queryset = models.ItemSet.objects.all().order_by('pk') + serializer_class = serializers.ItemSetSerializer + filterset_class = ItemSetFilterSet + + +class WeaponFilterSet(FilterSet): + + class Meta: + model = models.Weapon + fields = { + 'key': ['in', 'iexact', 'exact' ], + 'name': ['iexact', 'exact'], + 'document__key': ['in','iexact','exact'], + 'damage_type': ['in','iexact','exact'], + 'damage_dice': ['in','iexact','exact'], + 'versatile_dice': ['in','iexact','exact'], + 'range_reach': ['exact','lt','lte','gt','gte'], + 'range_normal': ['exact','lt','lte','gt','gte'], + 'range_long': ['exact','lt','lte','gt','gte'], + 'is_finesse': ['exact'], + 'is_thrown': ['exact'], + 'is_two_handed': ['exact'], + 'requires_ammunition': ['exact'], + 'requires_loading': ['exact'], + 'is_heavy': ['exact'], + 'is_light': ['exact'], + 'is_lance': ['exact'], + 'is_net': ['exact'], + 'is_simple': ['exact'], + 'is_improvised': ['exact'] + } + + +class WeaponViewSet(viewsets.ReadOnlyModelViewSet): + """ + list: API endpoint for returning a list of weapons. + retrieve: API endpoint for returning a particular weapon. + """ + queryset = models.Weapon.objects.all().order_by('pk') + serializer_class = serializers.WeaponSerializer + filterset_class = WeaponFilterSet + + +class ArmorFilterSet(FilterSet): + + class Meta: + model = models.Armor + fields = { + 'key': ['in', 'iexact', 'exact' ], + 'name': ['iexact', 'exact'], + 'document__key': ['in','iexact','exact'], + 'grants_stealth_disadvantage': ['exact'], + 'strength_score_required': ['exact','lt','lte','gt','gte'], + 'ac_base': ['exact','lt','lte','gt','gte'], + 'ac_add_dexmod': ['exact'], + 'ac_cap_dexmod': ['exact'], + + } + + +class ArmorViewSet(viewsets.ReadOnlyModelViewSet): + """ + list: API endpoint for returning a list of armor. + retrieve: API endpoint for returning a particular armor. + """ + queryset = models.Armor.objects.all().order_by('pk') + serializer_class = serializers.ArmorSerializer + filterset_class = ArmorFilterSet diff --git a/api_v2/views/views.py b/api_v2/views/views.py index a102fc11..84b32707 100644 --- a/api_v2/views/views.py +++ b/api_v2/views/views.py @@ -1,5 +1,4 @@ from django_filters import FilterSet -from django_filters import BooleanFilter from django_filters.rest_framework import DjangoFilterBackend import django_filters from rest_framework import viewsets @@ -9,122 +8,6 @@ from api.schema_generator import CustomSchema -class ItemFilterSet(FilterSet): - is_magic_item = BooleanFilter(field_name='rarity', lookup_expr='isnull', exclude=True) - - class Meta: - model = models.Item - fields = { - 'key': ['in', 'iexact', 'exact' ], - 'name': ['iexact', 'exact'], - 'desc': ['icontains'], - 'cost': ['exact', 'range', 'gt', 'gte', 'lt', 'lte'], - 'weight': ['exact', 'range', 'gt', 'gte', 'lt', 'lte'], - 'rarity': ['exact', 'in', ], - 'requires_attunement': ['exact'], - 'category': ['in', 'iexact', 'exact'], - 'document__key': ['in','iexact','exact'] - } - - -class ItemViewSet(viewsets.ReadOnlyModelViewSet): - """ - list: API endpoint for returning a list of items. - - retrieve: API endpoint for returning a particular item. - """ - queryset = models.Item.objects.all().order_by('pk') - serializer_class = serializers.ItemSerializer - filterset_class = ItemFilterSet - - -class ItemSetFilterSet(FilterSet): - - class Meta: - model = models.ItemSet - fields = { - 'key': ['in', 'iexact', 'exact' ], - 'name': ['iexact', 'exact'], - 'document__key': ['in','iexact','exact'] - } - - -class ItemSetViewSet(viewsets.ReadOnlyModelViewSet): - """" - list: API Endpoint for returning a set of itemsets. - - retrieve: API endpoint for return a particular itemset. - """ - queryset = models.ItemSet.objects.all().order_by('pk') - serializer_class = serializers.ItemSetSerializer - filterset_class = ItemSetFilterSet - - - -class WeaponFilterSet(FilterSet): - - class Meta: - model = models.Weapon - fields = { - 'key': ['in', 'iexact', 'exact' ], - 'name': ['iexact', 'exact'], - 'document__key': ['in','iexact','exact'], - 'damage_type': ['in','iexact','exact'], - 'damage_dice': ['in','iexact','exact'], - 'versatile_dice': ['in','iexact','exact'], - 'range_reach': ['exact','lt','lte','gt','gte'], - 'range_normal': ['exact','lt','lte','gt','gte'], - 'range_long': ['exact','lt','lte','gt','gte'], - 'is_finesse': ['exact'], - 'is_thrown': ['exact'], - 'is_two_handed': ['exact'], - 'requires_ammunition': ['exact'], - 'requires_loading': ['exact'], - 'is_heavy': ['exact'], - 'is_light': ['exact'], - 'is_lance': ['exact'], - 'is_net': ['exact'], - 'is_simple': ['exact'], - 'is_improvised': ['exact'] - } - - -class WeaponViewSet(viewsets.ReadOnlyModelViewSet): - """ - list: API endpoint for returning a list of weapons. - retrieve: API endpoint for returning a particular weapon. - """ - queryset = models.Weapon.objects.all().order_by('pk') - serializer_class = serializers.WeaponSerializer - filterset_class = WeaponFilterSet - - -class ArmorFilterSet(FilterSet): - - class Meta: - model = models.Armor - fields = { - 'key': ['in', 'iexact', 'exact' ], - 'name': ['iexact', 'exact'], - 'document__key': ['in','iexact','exact'], - 'grants_stealth_disadvantage': ['exact'], - 'strength_score_required': ['exact','lt','lte','gt','gte'], - 'ac_base': ['exact','lt','lte','gt','gte'], - 'ac_add_dexmod': ['exact'], - 'ac_cap_dexmod': ['exact'], - - } - - -class ArmorViewSet(viewsets.ReadOnlyModelViewSet): - """ - list: API endpoint for returning a list of armor. - retrieve: API endpoint for returning a particular armor. - """ - queryset = models.Armor.objects.all().order_by('pk') - serializer_class = serializers.ArmorSerializer - filterset_class = ArmorFilterSet - class FeatFilterSet(FilterSet): class Meta: From e61394010cb2a0d80ec0e4bb74d302affd3f66c2 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Sat, 4 Nov 2023 13:04:46 -0500 Subject: [PATCH 14/16] Races and Feats. --- api_v2/views/__init__.py | 7 ++++++- api_v2/views/feat.py | 29 ++++++++++++++++++++++++++++ api_v2/views/race.py | 27 ++++++++++++++++++++++++++ api_v2/views/views.py | 41 ---------------------------------------- 4 files changed, 62 insertions(+), 42 deletions(-) create mode 100644 api_v2/views/feat.py create mode 100644 api_v2/views/race.py diff --git a/api_v2/views/__init__.py b/api_v2/views/__init__.py index 73dacbf9..cce9b9ae 100644 --- a/api_v2/views/__init__.py +++ b/api_v2/views/__init__.py @@ -12,7 +12,12 @@ from .document import PublisherViewSet from .document import LicenseViewSet +from .feat import FeatFilterSet, FeatViewSet + +from .race import RaceFilterSet, RaceViewSet + from .item import ItemFilterSet, ItemViewSet from .item import ItemSetFilterSet, ItemSetViewSet from .item import ArmorFilterSet, ArmorViewSet -from .item import WeaponFilterSet, WeaponViewSet \ No newline at end of file +from .item import WeaponFilterSet, WeaponViewSet + diff --git a/api_v2/views/feat.py b/api_v2/views/feat.py new file mode 100644 index 00000000..7368e55a --- /dev/null +++ b/api_v2/views/feat.py @@ -0,0 +1,29 @@ +from rest_framework import viewsets + +from django_filters import FilterSet + +from api_v2 import models +from api_v2 import serializers + + +class FeatFilterSet(FilterSet): + class Meta: + model = models.Feat + fields = { + 'key': ['in', 'iexact', 'exact' ], + 'name': ['iexact', 'exact'], + 'document__key': ['in','iexact','exact'], + } + + +class FeatViewSet(viewsets.ReadOnlyModelViewSet): + """ + list: API endpoint for returning a list of feats. + retrieve: API endpoint for returning a particular feat. + """ + queryset = models.Feat.objects.all().order_by('pk') + serializer_class = serializers.FeatSerializer + filterset_class = FeatFilterSet + + + diff --git a/api_v2/views/race.py b/api_v2/views/race.py new file mode 100644 index 00000000..d9db9149 --- /dev/null +++ b/api_v2/views/race.py @@ -0,0 +1,27 @@ +from rest_framework import viewsets + +from django_filters import FilterSet + +from api_v2 import models +from api_v2 import serializers + + +class RaceFilterSet(FilterSet): + class Meta: + model = models.Race + fields = { + 'key': ['in', 'iexact', 'exact'], + 'name': ['iexact', 'exact'], + 'document__key': ['in', 'iexact', 'exact'], + } + + +class RaceViewSet(viewsets.ReadOnlyModelViewSet): + """ + list: API endpoint for returning a list of races. + retrieve: API endpoint for returning a particular race. + """ + queryset = models.Race.objects.all().order_by('pk') + serializer_class = serializers.RaceSerializer + filterset_class = RaceFilterSet + diff --git a/api_v2/views/views.py b/api_v2/views/views.py index 84b32707..edb19110 100644 --- a/api_v2/views/views.py +++ b/api_v2/views/views.py @@ -8,44 +8,3 @@ from api.schema_generator import CustomSchema - -class FeatFilterSet(FilterSet): - class Meta: - model = models.Feat - fields = { - 'key': ['in', 'iexact', 'exact' ], - 'name': ['iexact', 'exact'], - 'document__key': ['in','iexact','exact'], - } - - -class FeatViewSet(viewsets.ReadOnlyModelViewSet): - """ - list: API endpoint for returning a list of feats. - retrieve: API endpoint for returning a particular feat. - """ - queryset = models.Feat.objects.all().order_by('pk') - serializer_class = serializers.FeatSerializer - filterset_class = FeatFilterSet - - -class RaceFilterSet(FilterSet): - class Meta: - model = models.Race - fields = { - 'key': ['in', 'iexact', 'exact'], - 'name': ['iexact', 'exact'], - 'document__key': ['in', 'iexact', 'exact'], - } - - -class RaceViewSet(viewsets.ReadOnlyModelViewSet): - """ - list: API endpoint for returning a list of races. - retrieve: API endpoint for returning a particular race. - """ - queryset = models.Race.objects.all().order_by('pk') - serializer_class = serializers.RaceSerializer - filterset_class = RaceFilterSet - - From 91d3211f511b8aff517c39af69cc7365569dae84 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Sat, 4 Nov 2023 13:05:25 -0500 Subject: [PATCH 15/16] Removing single views. --- api_v2/views/__init__.py | 4 +--- api_v2/views/views.py | 10 ---------- 2 files changed, 1 insertion(+), 13 deletions(-) delete mode 100644 api_v2/views/views.py diff --git a/api_v2/views/__init__.py b/api_v2/views/__init__.py index cce9b9ae..614a5fbf 100644 --- a/api_v2/views/__init__.py +++ b/api_v2/views/__init__.py @@ -1,8 +1,6 @@ """The initialization for views for open5e's api v2.""" -from .views import * - -from .background import BackgroundFilterSet, BackgroundViewSet + from .background import BackgroundFilterSet, BackgroundViewSet from .creature import CreatureFilterSet, CreatureViewSet from .creature import CreatureTypeViewSet diff --git a/api_v2/views/views.py b/api_v2/views/views.py deleted file mode 100644 index edb19110..00000000 --- a/api_v2/views/views.py +++ /dev/null @@ -1,10 +0,0 @@ -from django_filters import FilterSet -from django_filters.rest_framework import DjangoFilterBackend -import django_filters -from rest_framework import viewsets - -from api_v2 import models -from api_v2 import serializers -from api.schema_generator import CustomSchema - - From d98983227ef1ab6e193b355833029426b9f0b8be Mon Sep 17 00:00:00 2001 From: BuildTools Date: Sat, 4 Nov 2023 13:05:41 -0500 Subject: [PATCH 16/16] Whitespace issue. --- api_v2/views/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api_v2/views/__init__.py b/api_v2/views/__init__.py index 614a5fbf..67d2b037 100644 --- a/api_v2/views/__init__.py +++ b/api_v2/views/__init__.py @@ -1,6 +1,6 @@ """The initialization for views for open5e's api v2.""" - from .background import BackgroundFilterSet, BackgroundViewSet +from .background import BackgroundFilterSet, BackgroundViewSet from .creature import CreatureFilterSet, CreatureViewSet from .creature import CreatureTypeViewSet