Skip to content

Commit 400d200

Browse files
676 add monster illustrations as a field to creature objects (open5e#767)
* Implementing HasIllustration * Bit of cleanup for whitespace/comments. * PEP8 and adding HasIllustration to Creature. * Adding illustration to database. * merging a couple of conflicts. * Adding open5e custom image objects. * Adding illustration field to data. * Ordering fields. * Adding illustration fields to creature documents. * Adding in pks * Exposing the field. * Fixing creature illustrations. --------- Co-authored-by: calum <[email protected]>
1 parent 5ef5a67 commit 400d200

22 files changed

+3761
-10
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Generated by Django 5.2.1 on 2025-06-08 12:24
2+
3+
import django.db.models.deletion
4+
from django.db import migrations, models
5+
6+
7+
class Migration(migrations.Migration):
8+
9+
dependencies = [
10+
('api_v2', '0049_add_document_display_name'),
11+
]
12+
13+
operations = [
14+
migrations.AddField(
15+
model_name='creature',
16+
name='illustration',
17+
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='api_v2.image'),
18+
),
19+
]
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Generated by Django 5.2.1 on 2025-06-15 21:21
2+
3+
from django.db import migrations
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('api_v2', '0050_creature_illustration'),
10+
('api_v2', '0051_merge_20250615_2056'),
11+
]
12+
13+
operations = [
14+
]

api_v2/models/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,6 @@
6060

6161
from .rule import Rule, RuleSet
6262

63-
from .image import Image
63+
from .image import Image, HasIcon, HasIllustration
6464

6565
from .service import Service

api_v2/models/creature.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
"""The model for a creature."""
2+
import decimal
3+
24
from fractions import Fraction
35

46
from django.db import models
@@ -9,21 +11,21 @@
911
from .abstracts import damage_die_count_field, damage_die_type_field
1012
from .abstracts import damage_bonus_field, key_field
1113
from .abstracts import distance_field, distance_unit_field
14+
from .image import HasIllustration
1215
from .object import Object
1316
from .condition import Condition
1417
from .damagetype import DamageType
1518
from .document import FromDocument
1619
from .environment import Environment
1720
from .speed import HasSpeed
1821
from .enums import CREATURE_ATTACK_TYPES, CREATURE_USES_TYPES, ACTION_TYPES
19-
import decimal
2022

2123

2224
class CreatureType(HasName, HasDescription, FromDocument):
2325
"""The Type of creature, such as Aberration."""
2426

2527

26-
class Creature(Object, HasAbilities, HasSenses, HasLanguage, HasSpeed, FromDocument):
28+
class Creature(Object, HasAbilities, HasSenses, HasLanguage, HasSpeed, HasIllustration, FromDocument):
2729
"""
2830
This is the model for a Creature, per the 5e gamesystem.
2931
@@ -151,7 +153,7 @@ def search_result_extra_fields(self):
151153
"type": self.type.name,
152154
"size": self.size.name,
153155
}
154-
156+
155157
@property
156158
def challenge_rating_text(self):
157159
'''Challenge rating as text string representation of a fraction or integer. '''
@@ -204,6 +206,7 @@ def experience_points(self):
204206
except:
205207
return None
206208

209+
207210
class CreatureAction(HasName, HasDescription):
208211
"""Describes an action available to a creature."""
209212
key = key_field()
@@ -266,6 +269,7 @@ def as_text(self):
266269

267270
return text
268271

272+
269273
class CreatureActionAttack(HasName):
270274
"""Describes an attack action used by a creature."""
271275
key = key_field()
@@ -337,7 +341,7 @@ class CreatureTrait(Modification):
337341
"""
338342
key = key_field()
339343
parent = models.ForeignKey(Creature, on_delete=models.CASCADE, related_name="traits")
340-
344+
341345

342346
class CreatureSet(HasName, FromDocument):
343347
"""Set that the creature belongs to."""

api_v2/models/image.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
"""The model for an image with metadata."""
1+
"""The model for an image with metadata. Includes abstracts."""
22

33

44
from django.db import models
@@ -32,19 +32,31 @@ class Image(HasName, FromDocument):
3232
)
3333

3434
def __str__(self):
35-
return (self.document.name + " - " + self.name)
35+
return self.document.name + " - " + self.name
3636

3737
@property
3838
def file_url(self)->str:
39+
"""Returns a relative path to the related file."""
3940
return static(self.file_path)
40-
41+
4142
class Meta:
4243
ordering = ['key']
4344

4445

4546
class HasIcon(models.Model):
4647
"""The model inherited for defining an icon for another object type."""
47-
icon = models.ForeignKey(Image,
48+
icon = models.ForeignKey(Image,
49+
blank=True,
50+
null=True,
51+
on_delete=models.CASCADE)
52+
53+
class Meta:
54+
abstract = True
55+
56+
57+
class HasIllustration(models.Model):
58+
"""The model inherited for defining an illustration for another object type."""
59+
illustration = models.ForeignKey(Image,
4860
blank=True,
4961
null=True,
5062
on_delete=models.CASCADE)

api_v2/serializers/creature.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from .language import LanguageSummarySerializer
1414
from .environment import EnvironmentSummarySerializer
1515
from .size import SizeSummarySerializer
16+
from .image import ImageSummarySerializer
1617
from drf_spectacular.utils import extend_schema_field, inline_serializer
1718
from drf_spectacular.types import OpenApiTypes
1819

@@ -157,6 +158,8 @@ class CreatureSerializer(GameContentSerializer):
157158
languages = CreatureLanguageSerializer(source='*')
158159
environments = EnvironmentSummarySerializer(many=True)
159160
initiative_bonus = serializers.SerializerMethodField()
161+
illustration = ImageSummarySerializer()
162+
160163

161164
class Meta:
162165
'''Serializer meta options.'''
@@ -199,7 +202,8 @@ class Meta:
199202
'actions',
200203
'traits',
201204
'creaturesets',
202-
'environments'
205+
'environments',
206+
'illustration'
203207
]
204208

205209
@extend_schema_field(inline_serializer(

api_v2/tests/responses/TestObjects.test_creature_ancient_example.approved.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@
212212
"experience_points": 62000,
213213
"hit_dice": "28d20+252",
214214
"hit_points": 546,
215+
"illustration": null,
215216
"initiative_bonus": 0,
216217
"key": "srd_ancient-red-dragon",
217218
"languages": {

api_v2/tests/responses/TestObjects.test_creature_goblin_example.approved.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@
170170
"experience_points": 50,
171171
"hit_dice": "2d6",
172172
"hit_points": 7,
173+
"illustration": null,
173174
"initiative_bonus": 2,
174175
"key": "srd_goblin",
175176
"languages": {

api_v2/tests/responses/TestObjects.test_creature_guard_example.approved.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@
129129
"experience_points": 25,
130130
"hit_dice": "2d8+2",
131131
"hit_points": 11,
132+
"illustration": null,
132133
"initiative_bonus": 1,
133134
"key": "srd_guard",
134135
"languages": {

api_v2/tests/responses/TestObjects.test_creatureset_example.approved.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@
8686
"experience_points": 25,
8787
"hit_dice": "2d10+4",
8888
"hit_points": 15,
89+
"illustration": null,
8990
"initiative_bonus": -1,
9091
"key": "srd_camel",
9192
"languages": {
@@ -241,6 +242,7 @@
241242
"experience_points": 0,
242243
"hit_dice": null,
243244
"hit_points": 11,
245+
"illustration": null,
244246
"initiative_bonus": 0,
245247
"key": "srd_donkey",
246248
"languages": {
@@ -436,6 +438,7 @@
436438
"experience_points": 50,
437439
"hit_dice": "3d10+3",
438440
"hit_points": 19,
441+
"illustration": null,
439442
"initiative_bonus": 0,
440443
"key": "srd_draft-horse",
441444
"languages": {
@@ -674,6 +677,7 @@
674677
"experience_points": 1100,
675678
"hit_dice": "8d12+24",
676679
"hit_points": 76,
680+
"illustration": null,
677681
"initiative_bonus": -1,
678682
"key": "srd_elephant",
679683
"languages": {
@@ -884,6 +888,7 @@
884888
"experience_points": 25,
885889
"hit_dice": "1d8+1",
886890
"hit_points": 5,
891+
"illustration": null,
887892
"initiative_bonus": 2,
888893
"key": "srd_mastiff",
889894
"languages": {
@@ -1094,6 +1099,7 @@
10941099
"experience_points": 25,
10951100
"hit_dice": "2d8+2",
10961101
"hit_points": 11,
1102+
"illustration": null,
10971103
"initiative_bonus": 0,
10981104
"key": "srd_mule",
10991105
"languages": {
@@ -1303,6 +1309,7 @@
13031309
"experience_points": 25,
13041310
"hit_dice": "2d8+2",
13051311
"hit_points": 11,
1312+
"illustration": null,
13061313
"initiative_bonus": 0,
13071314
"key": "srd_pony",
13081315
"languages": {
@@ -1503,6 +1510,7 @@
15031510
"experience_points": 50,
15041511
"hit_dice": "2d10+2",
15051512
"hit_points": 13,
1513+
"illustration": null,
15061514
"initiative_bonus": 0,
15071515
"key": "srd_riding-horse",
15081516
"languages": {
@@ -1698,6 +1706,7 @@
16981706
"experience_points": 100,
16991707
"hit_dice": "3d10+3",
17001708
"hit_points": 19,
1709+
"illustration": null,
17011710
"initiative_bonus": 1,
17021711
"key": "srd_warhorse",
17031712
"languages": {

0 commit comments

Comments
 (0)