diff --git a/api_v2/admin.py b/api_v2/admin.py index 80e3f967..a8b211a2 100644 --- a/api_v2/admin.py +++ b/api_v2/admin.py @@ -10,7 +10,7 @@ class FromDocumentModelAdmin(admin.ModelAdmin): class ItemModelAdmin(admin.ModelAdmin): - list_display = ['key', 'category', 'name'] + list_display = ['key', 'name'] class TraitInline(admin.TabularInline): @@ -77,6 +77,7 @@ class LanguageAdmin(admin.ModelAdmin): admin.site.register(Weapon, admin_class=FromDocumentModelAdmin) admin.site.register(Armor, admin_class=FromDocumentModelAdmin) +admin.site.register(ItemCategory) admin.site.register(Item, admin_class=ItemModelAdmin) admin.site.register(ItemSet, admin_class=FromDocumentModelAdmin) diff --git a/api_v2/migrations/0023_rename_category_item_category_text.py b/api_v2/migrations/0023_rename_category_item_category_text.py new file mode 100644 index 00000000..d7751f34 --- /dev/null +++ b/api_v2/migrations/0023_rename_category_item_category_text.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.20 on 2023-11-04 23:57 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('api_v2', '0022_condition'), + ] + + operations = [ + migrations.RenameField( + model_name='item', + old_name='category', + new_name='category_text', + ), + ] diff --git a/api_v2/migrations/0024_itemcategory.py b/api_v2/migrations/0024_itemcategory.py new file mode 100644 index 00000000..fbade8c4 --- /dev/null +++ b/api_v2/migrations/0024_itemcategory.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2.20 on 2023-11-05 00:06 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api_v2', '0023_rename_category_item_category_text'), + ] + + operations = [ + migrations.CreateModel( + name='ItemCategory', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(help_text='Name of the item.', max_length=100)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/api_v2/migrations/0025_auto_20231105_0009.py b/api_v2/migrations/0025_auto_20231105_0009.py new file mode 100644 index 00000000..f0dc0caa --- /dev/null +++ b/api_v2/migrations/0025_auto_20231105_0009.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2.20 on 2023-11-05 00:09 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api_v2', '0024_itemcategory'), + ] + + operations = [ + migrations.RemoveField( + model_name='itemcategory', + name='id', + ), + migrations.AddField( + model_name='itemcategory', + name='key', + field=models.CharField(default='key', help_text='Unique key for the ItemCategory.', max_length=100, primary_key=True, serialize=False), + preserve_default=False, + ), + ] diff --git a/api_v2/migrations/0026_auto_20231105_0015.py b/api_v2/migrations/0026_auto_20231105_0015.py new file mode 100644 index 00000000..cafddb57 --- /dev/null +++ b/api_v2/migrations/0026_auto_20231105_0015.py @@ -0,0 +1,25 @@ +# Generated by Django 3.2.20 on 2023-11-05 00:15 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('api_v2', '0025_auto_20231105_0009'), + ] + + operations = [ + migrations.AddField( + model_name='itemcategory', + name='document', + field=models.ForeignKey(default='srd', on_delete=django.db.models.deletion.CASCADE, to='api_v2.document'), + preserve_default=False, + ), + migrations.AlterField( + model_name='itemcategory', + name='key', + field=models.CharField(help_text='Unique key for the Item.', max_length=100, primary_key=True, serialize=False), + ), + ] diff --git a/api_v2/migrations/0027_item_category.py b/api_v2/migrations/0027_item_category.py new file mode 100644 index 00000000..d269d7b6 --- /dev/null +++ b/api_v2/migrations/0027_item_category.py @@ -0,0 +1,19 @@ +# Generated by Django 3.2.20 on 2023-11-05 00:24 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('api_v2', '0026_auto_20231105_0015'), + ] + + operations = [ + migrations.AddField( + model_name='item', + name='category', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='api_v2.itemcategory'), + ), + ] diff --git a/api_v2/migrations/0028_alter_item_category_text.py b/api_v2/migrations/0028_alter_item_category_text.py new file mode 100644 index 00000000..f6a3b8ac --- /dev/null +++ b/api_v2/migrations/0028_alter_item_category_text.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.20 on 2023-11-05 00:28 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api_v2', '0027_item_category'), + ] + + operations = [ + migrations.AlterField( + model_name='item', + name='category_text', + field=models.CharField(choices=[('staff', 'Staff'), ('rod', 'Rod'), ('scroll', 'Scroll'), ('potion', 'Potion'), ('wand', 'Wand'), ('wondrous-item', 'Wondrous item'), ('ring', 'Ring'), ('ammunition', 'Ammunition'), ('weapon', 'Weapon'), ('armor', 'Armor'), ('gem', 'Gem'), ('jewelry', 'Jewelry'), ('art', 'Art'), ('trade-good', 'Trade Good'), ('shield', 'Shield'), ('poison', 'Poison'), ('adventuring-gear', 'Adventuring gear'), ('tools', 'Tools')], help_text='The category of the magic item.', max_length=100, null=True), + ), + ] diff --git a/api_v2/migrations/0029_auto_20231105_0034.py b/api_v2/migrations/0029_auto_20231105_0034.py new file mode 100644 index 00000000..9b395039 --- /dev/null +++ b/api_v2/migrations/0029_auto_20231105_0034.py @@ -0,0 +1,24 @@ +# Generated by Django 3.2.20 on 2023-11-05 00:34 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('api_v2', '0028_alter_item_category_text'), + ] + + operations = [ + migrations.RemoveField( + model_name='item', + name='category_text', + ), + migrations.AlterField( + model_name='item', + name='category', + field=models.ForeignKey(default='pooop', on_delete=django.db.models.deletion.CASCADE, to='api_v2.itemcategory'), + preserve_default=False, + ), + ] diff --git a/api_v2/models/__init__.py b/api_v2/models/__init__.py index 7b8a782c..c3d12196 100644 --- a/api_v2/models/__init__.py +++ b/api_v2/models/__init__.py @@ -2,6 +2,7 @@ from .abilities import Abilities +from .item import ItemCategory from .item import Item from .item import ItemSet diff --git a/api_v2/models/item.py b/api_v2/models/item.py index 6a37373e..40e69f3d 100644 --- a/api_v2/models/item.py +++ b/api_v2/models/item.py @@ -10,6 +10,9 @@ from .abstracts import Object, HasName, HasDescription from .document import FromDocument +class ItemCategory(HasName, FromDocument): + """A class describing categories of items.""" + pass class Item(Object, HasDescription, FromDocument): """ @@ -40,34 +43,11 @@ class Item(Object, HasDescription, FromDocument): blank=True, null=True) - CATEGORY_CHOICES = [ - ('staff', 'Staff'), - ('rod', 'Rod'), - ('scroll', 'Scroll'), - ('potion', 'Potion'), - ('wand', 'Wand'), - ('wondrous-item', 'Wondrous item'), - ('ring', 'Ring'), - ('ammunition', 'Ammunition'), - ('weapon', 'Weapon'), - ('armor', 'Armor'), - ('gem', 'Gem'), - ('jewelry', 'Jewelry'), - ('art', 'Art'), - ('trade-good', 'Trade Good'), - ('shield', 'Shield'), - ('poison', 'Poison'), - ('adventuring-gear', 'Adventuring gear'), - ('tools', 'Tools') - ] - - category = models.CharField( - null=False, - choices=CATEGORY_CHOICES, - max_length=100, - help_text='The category of the magic item.') - # Magic item types that should probably be filterable: - # Staff, Rod, Scroll, Ring, Potion, Ammunition, Wand = category + category = models.ForeignKey( + ItemCategory, + on_delete=models.CASCADE, + null=False + ) requires_attunement = models.BooleanField( null=False, diff --git a/api_v2/serializers/__init__.py b/api_v2/serializers/__init__.py index 63e618ab..36ff1c6f 100644 --- a/api_v2/serializers/__init__.py +++ b/api_v2/serializers/__init__.py @@ -4,6 +4,7 @@ from .item import WeaponSerializer from .item import ItemSerializer from .item import ItemSetSerializer +from .item import ItemCategorySerializer from .background import BackgroundBenefitSerializer from .background import BackgroundSerializer diff --git a/api_v2/serializers/item.py b/api_v2/serializers/item.py index 2d78a220..dbd417c1 100644 --- a/api_v2/serializers/item.py +++ b/api_v2/serializers/item.py @@ -36,7 +36,6 @@ class ItemSerializer(GameContentSerializer): weapon = WeaponSerializer(read_only=True, context={'request': {}}) armor = ArmorSerializer(read_only=True, context={'request': {}}) - class Meta: model = models.Item fields = '__all__' @@ -49,3 +48,12 @@ class ItemSetSerializer(GameContentSerializer): class Meta: model = models.ItemSet fields = '__all__' + + +class ItemCategorySerializer(GameContentSerializer): + key = serializers.ReadOnlyField() + item_set = ItemSerializer(many=True, read_only=True, context={'request':{}}) + + class Meta: + model = models.ItemCategory + fields = "__all__" \ No newline at end of file diff --git a/api_v2/views/__init__.py b/api_v2/views/__init__.py index c924d1be..bdc7be97 100644 --- a/api_v2/views/__init__.py +++ b/api_v2/views/__init__.py @@ -16,6 +16,7 @@ from .item import ItemFilterSet, ItemViewSet from .item import ItemSetFilterSet, ItemSetViewSet +from .item import ItemCategoryViewSet from .item import ArmorFilterSet, ArmorViewSet from .item import WeaponFilterSet, WeaponViewSet diff --git a/api_v2/views/item.py b/api_v2/views/item.py index dc51458f..a96344b8 100644 --- a/api_v2/views/item.py +++ b/api_v2/views/item.py @@ -20,7 +20,7 @@ class Meta: 'weight': ['exact', 'range', 'gt', 'gte', 'lt', 'lte'], 'rarity': ['exact', 'in', ], 'requires_attunement': ['exact'], - 'category': ['in', 'iexact', 'exact'], + #'category': ['in', 'iexact', 'exact'], 'document__key': ['in','iexact','exact'] } @@ -58,6 +58,18 @@ class ItemSetViewSet(viewsets.ReadOnlyModelViewSet): filterset_class = ItemSetFilterSet +class ItemCategoryViewSet(viewsets.ReadOnlyModelViewSet): + """" + list: API Endpoint for returning a set of item categories. + + retrieve: API endpoint for return a particular item categories. + """ + queryset = models.ItemCategory.objects.all().order_by('pk') + serializer_class = serializers.ItemCategorySerializer + + + + class WeaponFilterSet(FilterSet): class Meta: diff --git a/data/v2/wizards-of-the-coast/srd/ItemCategory.json b/data/v2/wizards-of-the-coast/srd/ItemCategory.json new file mode 100644 index 00000000..63fc41e2 --- /dev/null +++ b/data/v2/wizards-of-the-coast/srd/ItemCategory.json @@ -0,0 +1,154 @@ +[ +{ + "model": "api_v2.itemcategory", + "pk": "Ring", + "fields": { + "name": "Ring", + "document": "srd" + } +}, +{ + "model": "api_v2.itemcategory", + "pk": "adventuring-gear", + "fields": { + "name": "Adventuring Gear", + "document": "srd" + } +}, +{ + "model": "api_v2.itemcategory", + "pk": "ammunition", + "fields": { + "name": "Ammunition", + "document": "srd" + } +}, +{ + "model": "api_v2.itemcategory", + "pk": "armor", + "fields": { + "name": "Armor", + "document": "srd" + } +}, +{ + "model": "api_v2.itemcategory", + "pk": "art", + "fields": { + "name": "Art", + "document": "srd" + } +}, +{ + "model": "api_v2.itemcategory", + "pk": "gem", + "fields": { + "name": "Gem", + "document": "srd" + } +}, +{ + "model": "api_v2.itemcategory", + "pk": "jewelry", + "fields": { + "name": "Jewelry", + "document": "srd" + } +}, +{ + "model": "api_v2.itemcategory", + "pk": "poison", + "fields": { + "name": "Poison", + "document": "srd" + } +}, +{ + "model": "api_v2.itemcategory", + "pk": "potion", + "fields": { + "name": "Potion", + "document": "srd" + } +}, +{ + "model": "api_v2.itemcategory", + "pk": "ring", + "fields": { + "name": "Ring", + "document": "srd" + } +}, +{ + "model": "api_v2.itemcategory", + "pk": "rod", + "fields": { + "name": "Rod", + "document": "srd" + } +}, +{ + "model": "api_v2.itemcategory", + "pk": "scroll", + "fields": { + "name": "Scroll", + "document": "srd" + } +}, +{ + "model": "api_v2.itemcategory", + "pk": "shield", + "fields": { + "name": "Shield", + "document": "srd" + } +}, +{ + "model": "api_v2.itemcategory", + "pk": "staff", + "fields": { + "name": "Staff", + "document": "srd" + } +}, +{ + "model": "api_v2.itemcategory", + "pk": "tools", + "fields": { + "name": "Tools", + "document": "srd" + } +}, +{ + "model": "api_v2.itemcategory", + "pk": "trade-good", + "fields": { + "name": "Trade Good", + "document": "srd" + } +}, +{ + "model": "api_v2.itemcategory", + "pk": "wand", + "fields": { + "name": "Wand", + "document": "srd" + } +}, +{ + "model": "api_v2.itemcategory", + "pk": "weapon", + "fields": { + "name": "Weapon", + "document": "srd" + } +}, +{ + "model": "api_v2.itemcategory", + "pk": "wondrous-item", + "fields": { + "name": "Wondrous Item", + "document": "srd" + } +} +] diff --git a/server/urls.py b/server/urls.py index a643319b..259e9714 100644 --- a/server/urls.py +++ b/server/urls.py @@ -54,6 +54,7 @@ if settings.V2_ENABLED: router_v2.register(r'items',views_v2.ItemViewSet) router_v2.register(r'itemsets',views_v2.ItemSetViewSet) + router_v2.register(r'itemcategories',views_v2.ItemCategoryViewSet) router_v2.register(r'documents',views_v2.DocumentViewSet) router_v2.register(r'licenses',views_v2.LicenseViewSet) router_v2.register(r'publishers',views_v2.PublisherViewSet)