From a61e7eec34e9c7e37a6506c9ca1c3e380754c1f2 Mon Sep 17 00:00:00 2001 From: BIT074 Date: Tue, 30 Jun 2026 17:19:53 +0800 Subject: [PATCH 1/2] Link form changes to respective methods --- data/v2/build.py | 15 ++ data/v2/csv/items.csv | 47 +++- data/v2/csv/pokemon_form_conditions.csv | 224 ++++++++++++++++++ data/v2/csv/pokemon_form_methods.csv | 7 + ..._pokemonformmethod_pokemonformcondition.py | 37 +++ .../0030_pokemonformcondition_move.py | 19 ++ pokemon_v2/models.py | 11 + pokemon_v2/serializers.py | 57 +++++ pokemon_v2/tests.py | 20 ++ 9 files changed, 436 insertions(+), 1 deletion(-) create mode 100644 data/v2/csv/pokemon_form_conditions.csv create mode 100644 data/v2/csv/pokemon_form_methods.csv create mode 100644 pokemon_v2/migrations/0029_pokemonformmethod_pokemonformcondition.py create mode 100644 pokemon_v2/migrations/0030_pokemonformcondition_move.py diff --git a/data/v2/build.py b/data/v2/build.py index 87a6a3291..2c7b86c49 100644 --- a/data/v2/build.py +++ b/data/v2/build.py @@ -2212,6 +2212,21 @@ def csv_record_to_objects(info): build_generic((PokemonFormType,), "pokemon_form_types.csv", csv_record_to_objects) + def csv_record_to_objects(info): + yield PokemonFormMethod(id=int(info[0]), name=info[1]) + + build_generic((PokemonFormMethod,), "pokemon_form_methods.csv", csv_record_to_objects) + + def csv_record_to_objects(info): + yield PokemonFormCondition( + pokemon_form_id=int(info[0]), + form_method_id=int(info[1]), + item_id=int(info[2]) if info[2] != "" else None, + ability_id=int(info[3]) if info[3] != "" else None, + move_id=int(info[4]) if info[4] != "" else None, + ) + build_generic((PokemonFormCondition,), "pokemon_form_conditions.csv", csv_record_to_objects) + def csv_record_to_objects(info): yield PokemonGameIndex( pokemon_id=int(info[0]), version_id=int(info[1]), game_index=int(info[2]) diff --git a/data/v2/csv/items.csv b/data/v2/csv/items.csv index da4160b70..0eb2862b0 100644 --- a/data/v2/csv/items.csv +++ b/data/v2/csv/items.csv @@ -2174,4 +2174,49 @@ id,identifier,category_id,cost,fling_power,fling_effect_id 2229,laorigin-ball,34,0,, 2230,black-augurite,10,0,, 2231,peat-block,10,0,, -2232,metal-alloy,10,0,, \ No newline at end of file +2232,metal-alloy,10,0,, +2559,clefablite,44,0,80, +2560,victreebelite,44,0,80, +2561,starminite,44,0,80, +2562,dragoninite,44,0,80, +2563,meganiumite,44,0,80, +2564,feraligite,44,0,80, +2565,skarmorite,44,0,80, +2566,froslassite,44,0,80, +2567,heatranite,44,0,80, +2568,darkranite,44,0,80, +2569,emboarite,44,0,80, +2570,excadrite,44,0,80, +2571,scolipite,44,0,80, +2572,scraftinite,44,0,80, +2573,eelektrossite,44,0,80, +2574,chandelurite,44,0,80, +2575,chesnaughtite,44,0,80, +2576,delphoxite,44,0,80, +2577,greninjite,44,0,80, +2578,pyroarite,44,0,80, +2579,floettite,44,0,80, +2580,malamarite,44,0,80, +2581,barbaracite,44,0,80, +2582,dragalgite,44,0,80, +2583,hawluchanite,44,0,80, +2584,zygardite,44,0,80, +2585,drampanite,44,0,80, +2586,zeraorite,44,0,80, +2587,falinksite,44,0,80, +2635,raichunite-x,44,0,80, +2636,raichunite-y,44,0,80, +2637,chimechite,44,0,80, +2638,absolite-z,44,0,80, +2639,staraptite,44,0,80, +2640,garchompite-z,44,0,80, +2641,lucarionite-z,44,0,80, +2642,golurkite,44,0,80, +2643,meowsticite,44,0,80, +2644,crabominite,44,0,80, +2645,golisopite,44,0,80, +2646,magearnite,44,0,80, +2647,scovillainite,44,0,80, +2648,baxcalibrite,44,0,80, +2649,tatsugirinite,44,0,80, +2650,glimmoranite,44,0,80, diff --git a/data/v2/csv/pokemon_form_conditions.csv b/data/v2/csv/pokemon_form_conditions.csv new file mode 100644 index 000000000..8df92859a --- /dev/null +++ b/data/v2/csv/pokemon_form_conditions.csv @@ -0,0 +1,224 @@ +pokemon_form_id,form_method_id,item_id,ability_id,move_id +493,1,1662,, +681,4,,176, +718,1,884,, +741,2,889,, +1017,1,2102,, +10028,4,,59, +10029,4,,59, +10030,4,,59, +10038,4,,122, +10041,1,285,, +10042,1,289,, +10043,1,288,, +10044,1,277,, +10045,1,280,, +10046,1,275,, +10047,1,283,, +10048,1,287,, +10049,1,278,, +10050,1,282,, +10051,1,279,, +10052,1,281,, +10053,1,284,, +10054,1,286,, +10055,1,290,, +10056,1,276,, +10063,1,442,, +10063,1,1661,, +10064,3,444,, +10067,4,,161, +10074,6,,,547 +10075,1,563,, +10076,1,564,, +10077,1,565,, +10078,1,566,, +10079,3,681,, +10080,3,681,, +10081,3,681,, +10084,6,,,548 +10085,1,684,, +10125,4,,176, +10133,1,698,, +10134,1,699,, +10135,1,717,, +10136,1,700,, +10137,1,718,, +10138,1,695,, +10139,1,714,, +10140,1,710,, +10141,1,715,, +10142,1,711,, +10143,1,701,, +10144,1,702,, +10145,1,697,, +10146,1,709,, +10147,1,719,, +10148,1,705,, +10149,1,708,, +10150,1,703,, +10151,1,696,, +10152,1,720,, +10153,1,706,, +10154,1,704,, +10155,1,721,, +10156,1,707,, +10157,1,716,, +10158,1,722,, +10159,1,712,, +10160,1,713,, +10164,1,760,, +10165,1,761,, +10166,1,793,, +10167,1,794,, +10168,1,795,, +10169,1,796,, +10170,1,797,, +10171,1,798,, +10172,1,800,, +10173,1,801,, +10174,1,802,, +10175,1,803,, +10176,1,804,, +10177,1,805,, +10178,1,799,, +10179,1,468,, +10180,1,467,, +10188,3,806,, +10189,1,808,, +10190,1,809,, +10191,1,810,, +10192,1,811,, +10219,4,,210, +10220,1,884,, +10221,1,884,, +10222,4,,211, +10225,2,890,, +10226,2,891,, +10227,2,892,, +10229,4,,208, +10232,1,902,, +10233,1,903,, +10234,1,904,, +10235,1,905,, +10236,1,906,, +10237,1,907,, +10238,1,908,, +10239,1,909,, +10240,1,910,, +10241,1,911,, +10242,1,912,, +10243,1,913,, +10244,1,914,, +10245,1,915,, +10246,1,916,, +10247,1,917,, +10248,1,918,, +10255,4,,197, +10256,4,,197, +10257,4,,197, +10258,4,,197, +10259,4,,197, +10260,4,,197, +10261,4,,197, +10262,4,,209, +10264,4,,209, +10337,4,,161, +10340,1,884,, +10341,4,,241, +10342,4,,241, +10354,4,,248, +10356,4,,258, +10357,1,1161,, +10358,1,1162,, +10364,5,,, +10365,5,,, +10366,5,,, +10367,5,,, +10368,5,,, +10369,5,,, +10370,5,,, +10371,5,,, +10372,5,,, +10373,5,,, +10374,5,,, +10375,5,,, +10376,5,,, +10377,5,,, +10378,5,,, +10379,5,,, +10380,5,,, +10381,5,,, +10382,5,,, +10383,5,,, +10384,5,,, +10385,5,,, +10386,5,,, +10387,5,,, +10388,5,,, +10389,5,,, +10390,5,,, +10391,5,,, +10392,5,,, +10393,5,,, +10394,5,,, +10395,5,,, +10396,5,,, +10397,5,,, +10414,1,1659,, +10415,1,1660,, +10425,4,,278, +10442,1,2106,, +10443,1,2107,, +10444,1,2108,, +10445,4,,304, +10446,3,1669,, +10503,1,2559,, +10504,1,2560,, +10505,1,2561,, +10506,1,2562,, +10507,1,2563,, +10508,1,2564,, +10509,1,2565,, +10510,1,2566,, +10511,1,2569,, +10512,1,2570,, +10513,1,2571,, +10514,1,2572,, +10515,1,2573,, +10516,1,2574,, +10517,1,2575,, +10518,1,2576,, +10519,1,2577,, +10520,1,2578,, +10521,1,2579,, +10522,1,2580,, +10523,1,2581,, +10524,1,2582,, +10525,1,2583,, +10526,1,2584,, +10527,1,2585,, +10528,1,2587,, +10529,1,2635,, +10530,1,2636,, +10531,1,2637,, +10532,1,2638,, +10533,1,2639,, +10534,1,2640,, +10535,1,2641,, +10536,1,2567,, +10537,1,2568,, +10538,1,2642,, +10539,1,2643,, +10540,1,2644,, +10541,1,2645,, +10542,1,2646,, +10543,1,2646,, +10544,1,2586,, +10545,1,2647,, +10546,1,2650,, +10547,1,2649,, +10548,1,2649,, +10549,1,2649,, +10550,1,2648,, +10554,1,2643,, diff --git a/data/v2/csv/pokemon_form_methods.csv b/data/v2/csv/pokemon_form_methods.csv new file mode 100644 index 000000000..6cc4d9488 --- /dev/null +++ b/data/v2/csv/pokemon_form_methods.csv @@ -0,0 +1,7 @@ +id,identifier +1,held-item +2,consumed-item +3,key-item +4,ability +5,gigantamax-factor +6,move diff --git a/pokemon_v2/migrations/0029_pokemonformmethod_pokemonformcondition.py b/pokemon_v2/migrations/0029_pokemonformmethod_pokemonformcondition.py new file mode 100644 index 000000000..1bf808287 --- /dev/null +++ b/pokemon_v2/migrations/0029_pokemonformmethod_pokemonformcondition.py @@ -0,0 +1,37 @@ +# Generated by Django 5.2.10 on 2026-06-29 04:01 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('pokemon_v2', '0028_pokemonevolution_evolved_form_and_more'), + ] + + operations = [ + migrations.CreateModel( + name='PokemonFormMethod', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(db_index=True, max_length=200)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='PokemonFormCondition', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('ability', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='pokemon_v2.ability')), + ('item', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='pokemon_v2.item')), + ('pokemon_form', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s', to='pokemon_v2.pokemonform')), + ('form_method', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='pokemon_v2.pokemonformmethod')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/pokemon_v2/migrations/0030_pokemonformcondition_move.py b/pokemon_v2/migrations/0030_pokemonformcondition_move.py new file mode 100644 index 000000000..51e8397a6 --- /dev/null +++ b/pokemon_v2/migrations/0030_pokemonformcondition_move.py @@ -0,0 +1,19 @@ +# Generated by Django 5.2.10 on 2026-06-30 08:04 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('pokemon_v2', '0029_pokemonformmethod_pokemonformcondition'), + ] + + operations = [ + migrations.AddField( + model_name='pokemonformcondition', + name='move', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='pokemon_v2.move'), + ), + ] diff --git a/pokemon_v2/models.py b/pokemon_v2/models.py index a18f2a8c8..688b8167a 100644 --- a/pokemon_v2/models.py +++ b/pokemon_v2/models.py @@ -1774,6 +1774,17 @@ class PokemonFormSprites(HasPokemonForm): sprites = models.JSONField() +class PokemonFormMethod(HasName): + pass + + +class PokemonFormCondition(HasPokemonForm): + form_method = models.ForeignKey(PokemonFormMethod, on_delete=models.CASCADE) + item = models.ForeignKey(Item, blank=True, null=True, on_delete=models.CASCADE) + ability = models.ForeignKey(Ability, blank=True, null=True, on_delete=models.CASCADE) + move = models.ForeignKey(Move, blank=True, null=True, on_delete=models.CASCADE) + + class PokemonGameIndex(HasPokemon, HasGameIndex, HasVersion): pass diff --git a/pokemon_v2/serializers.py b/pokemon_v2/serializers.py index 3e87a5661..506456509 100644 --- a/pokemon_v2/serializers.py +++ b/pokemon_v2/serializers.py @@ -3892,6 +3892,15 @@ class Meta: model = PokemonFormName fields = ("name", "pokemon_name", "language") +class PokemonFormTriggerSerializer(serializers.ModelSerializer): + method = serializers.CharField(source="form_method.name", read_only=True) + item = ItemSummarySerializer() + ability = AbilitySummarySerializer() + move = MoveSummarySerializer() + + class Meta: + model = PokemonFormCondition + fields = ("method", "item", "ability", "move") class PokemonFormDetailSerializer(serializers.ModelSerializer): pokemon = PokemonSummarySerializer() @@ -3900,6 +3909,7 @@ class PokemonFormDetailSerializer(serializers.ModelSerializer): form_names = serializers.SerializerMethodField("get_pokemon_form_names") names = serializers.SerializerMethodField("get_pokemon_form_pokemon_names") types = serializers.SerializerMethodField("get_pokemon_form_types") + trigger_conditions = serializers.SerializerMethodField("get_pokemon_form_triggers") class Meta: model = PokemonForm @@ -3918,6 +3928,7 @@ class Meta: "form_names", "names", "types", + "trigger_conditions", ) @extend_schema_field( @@ -4083,6 +4094,52 @@ def get_pokemon_form_types(self, obj): return form_types + @extend_schema_field( + field={ + "type": "array", + "items": { + "type": "object", + "required": ["method", "name", "url"], + "properties": { + "method": { + "type": "string", + "examples": ["held-item"], + }, + "name": { + "type": "string", + "examples": ["venusaurite"], + }, + "url": { + "type": "string", + "format": "uri", + "examples": ["https://pokeapi.co/api/v2/item/698/"], + }, + }, + }, + } + ) + def get_pokemon_form_triggers(self, obj): + conditions = PokemonFormCondition.objects.filter( + pokemon_form=obj + ) + conditions_data = PokemonFormTriggerSerializer( + conditions, many=True, context=self.context + ).data + + triggers = [] + for condition in conditions_data: + method = condition.pop("method", None) + if not method: + continue + trigger = {"method": method} + for value in condition.values(): + if value: + trigger.update(value) + break + triggers.append(trigger) + return triggers + + ################################# # POKEMON HABITAT SERIALIZERS # diff --git a/pokemon_v2/tests.py b/pokemon_v2/tests.py index 57086e188..bb97abb03 100644 --- a/pokemon_v2/tests.py +++ b/pokemon_v2/tests.py @@ -1619,6 +1619,21 @@ def setup_pokemon_form_data( return pokemon_form + @classmethod + def setup_pokemon_form_method_data(cls, name="frm mthd for pkmn frm"): + pokemon_form_method = PokemonFormMethod(name=name) + pokemon_form_method.save() + return pokemon_form_method + + @classmethod + def setup_pokemon_form_condition_data(cls, pokemon_form, form_method=None, item=None, ability=None, move=None): + form_method = form_method or cls.setup_pokemon_form_method_data(name="frm mthd for pkmn frm") + item = item or cls.setup_item_data(name="itm for pkmn frm") + + pokemon_form_condition = PokemonFormCondition(pokemon_form=pokemon_form, form_method=form_method, item=item, ability=ability, move=move) + pokemon_form_condition.save() + return pokemon_form_condition + @classmethod def setup_pokemon_ability_data(cls, pokemon, ability=None, is_hidden=False, slot=1): ability = ability or cls.setup_ability_data(name="ablty for pkmn") @@ -5265,6 +5280,7 @@ def test_pokemon_form_api(self): ) pokemon_form_sprites = self.setup_pokemon_form_sprites_data(pokemon_form) pokemon_form_type = self.setup_pokemon_form_type_data(pokemon_form) + pokemon_form_condition = self.setup_pokemon_form_condition_data(pokemon_form) response = self.client.get( "{}/pokemon-form/{}/".format(API_V2, pokemon_form.pk), @@ -5317,6 +5333,10 @@ def test_pokemon_form_api(self): "{}{}/type/{}/".format(TEST_HOST, API_V2, pokemon_form_type.type.pk), ) + self.assertEqual(response.data["trigger_conditions"][0]["method"], pokemon_form_condition.form_method.name) + self.assertEqual(response.data["trigger_conditions"][0]["name"], pokemon_form_condition.item.name) + self.assertEqual(response.data["trigger_conditions"][0]["url"], "{}{}/item/{}/".format(TEST_HOST, API_V2, pokemon_form_condition.item.pk)) + # Evolution test def test_evolution_trigger_api(self): evolution_trigger = self.setup_evolution_trigger_data(name="base evltn trgr") From fb5f63e5777d400cfe5ddb2f70dda677b21f8032 Mon Sep 17 00:00:00 2001 From: BIT074 Date: Thu, 2 Jul 2026 11:44:20 +0800 Subject: [PATCH 2/2] fix id, naming, code format issues --- data/v2/build.py | 13 ++- data/v2/csv/items.csv | 90 ++++++++-------- data/v2/csv/pokemon_form_conditions.csv | 100 +++++++++--------- data/v2/csv/pokemon_form_trigger_prose.csv | 7 ++ ..._methods.csv => pokemon_form_triggers.csv} | 0 ..._pokemonformmethod_pokemonformcondition.py | 37 ------- ...pokemonformtrigger_pokemonformcondition.py | 93 ++++++++++++++++ .../0030_pokemonformcondition_move.py | 19 ---- pokemon_v2/models.py | 8 +- pokemon_v2/serializers.py | 31 +++--- pokemon_v2/tests.py | 39 +++++-- 11 files changed, 254 insertions(+), 183 deletions(-) create mode 100644 data/v2/csv/pokemon_form_trigger_prose.csv rename data/v2/csv/{pokemon_form_methods.csv => pokemon_form_triggers.csv} (100%) delete mode 100644 pokemon_v2/migrations/0029_pokemonformmethod_pokemonformcondition.py create mode 100644 pokemon_v2/migrations/0029_pokemonformtrigger_pokemonformcondition.py delete mode 100644 pokemon_v2/migrations/0030_pokemonformcondition_move.py diff --git a/data/v2/build.py b/data/v2/build.py index 2c7b86c49..e9a3a5896 100644 --- a/data/v2/build.py +++ b/data/v2/build.py @@ -2213,19 +2213,24 @@ def csv_record_to_objects(info): build_generic((PokemonFormType,), "pokemon_form_types.csv", csv_record_to_objects) def csv_record_to_objects(info): - yield PokemonFormMethod(id=int(info[0]), name=info[1]) + yield PokemonFormTrigger(id=int(info[0]), name=info[1]) - build_generic((PokemonFormMethod,), "pokemon_form_methods.csv", csv_record_to_objects) + build_generic( + (PokemonFormTrigger,), "pokemon_form_triggers.csv", csv_record_to_objects + ) def csv_record_to_objects(info): yield PokemonFormCondition( pokemon_form_id=int(info[0]), - form_method_id=int(info[1]), + form_trigger_id=int(info[1]), item_id=int(info[2]) if info[2] != "" else None, ability_id=int(info[3]) if info[3] != "" else None, move_id=int(info[4]) if info[4] != "" else None, ) - build_generic((PokemonFormCondition,), "pokemon_form_conditions.csv", csv_record_to_objects) + + build_generic( + (PokemonFormCondition,), "pokemon_form_conditions.csv", csv_record_to_objects + ) def csv_record_to_objects(info): yield PokemonGameIndex( diff --git a/data/v2/csv/items.csv b/data/v2/csv/items.csv index 0eb2862b0..139a73620 100644 --- a/data/v2/csv/items.csv +++ b/data/v2/csv/items.csv @@ -2175,48 +2175,48 @@ id,identifier,category_id,cost,fling_power,fling_effect_id 2230,black-augurite,10,0,, 2231,peat-block,10,0,, 2232,metal-alloy,10,0,, -2559,clefablite,44,0,80, -2560,victreebelite,44,0,80, -2561,starminite,44,0,80, -2562,dragoninite,44,0,80, -2563,meganiumite,44,0,80, -2564,feraligite,44,0,80, -2565,skarmorite,44,0,80, -2566,froslassite,44,0,80, -2567,heatranite,44,0,80, -2568,darkranite,44,0,80, -2569,emboarite,44,0,80, -2570,excadrite,44,0,80, -2571,scolipite,44,0,80, -2572,scraftinite,44,0,80, -2573,eelektrossite,44,0,80, -2574,chandelurite,44,0,80, -2575,chesnaughtite,44,0,80, -2576,delphoxite,44,0,80, -2577,greninjite,44,0,80, -2578,pyroarite,44,0,80, -2579,floettite,44,0,80, -2580,malamarite,44,0,80, -2581,barbaracite,44,0,80, -2582,dragalgite,44,0,80, -2583,hawluchanite,44,0,80, -2584,zygardite,44,0,80, -2585,drampanite,44,0,80, -2586,zeraorite,44,0,80, -2587,falinksite,44,0,80, -2635,raichunite-x,44,0,80, -2636,raichunite-y,44,0,80, -2637,chimechite,44,0,80, -2638,absolite-z,44,0,80, -2639,staraptite,44,0,80, -2640,garchompite-z,44,0,80, -2641,lucarionite-z,44,0,80, -2642,golurkite,44,0,80, -2643,meowsticite,44,0,80, -2644,crabominite,44,0,80, -2645,golisopite,44,0,80, -2646,magearnite,44,0,80, -2647,scovillainite,44,0,80, -2648,baxcalibrite,44,0,80, -2649,tatsugirinite,44,0,80, -2650,glimmoranite,44,0,80, +2233,clefablite,44,0,80, +2234,victreebelite,44,0,80, +2235,starminite,44,0,80, +2236,dragoninite,44,0,80, +2237,meganiumite,44,0,80, +2238,feraligite,44,0,80, +2239,skarmorite,44,0,80, +2240,froslassite,44,0,80, +2241,heatranite,44,0,80, +2242,darkranite,44,0,80, +2243,emboarite,44,0,80, +2244,excadrite,44,0,80, +2245,scolipite,44,0,80, +2246,scraftinite,44,0,80, +2247,eelektrossite,44,0,80, +2248,chandelurite,44,0,80, +2249,chesnaughtite,44,0,80, +2250,delphoxite,44,0,80, +2251,greninjite,44,0,80, +2252,pyroarite,44,0,80, +2253,floettite,44,0,80, +2254,malamarite,44,0,80, +2255,barbaracite,44,0,80, +2256,dragalgite,44,0,80, +2257,hawluchanite,44,0,80, +2258,zygardite,44,0,80, +2259,drampanite,44,0,80, +2260,zeraorite,44,0,80, +2261,falinksite,44,0,80, +2262,raichunite-x,44,0,80, +2263,raichunite-y,44,0,80, +2264,chimechite,44,0,80, +2265,absolite-z,44,0,80, +2266,staraptite,44,0,80, +2267,garchompite-z,44,0,80, +2268,lucarionite-z,44,0,80, +2269,golurkite,44,0,80, +2270,meowsticite,44,0,80, +2271,crabominite,44,0,80, +2272,golisopite,44,0,80, +2273,magearnite,44,0,80, +2274,scovillainite,44,0,80, +2275,baxcalibrite,44,0,80, +2276,tatsugirinite,44,0,80, +2277,glimmoranite,44,0,80, diff --git a/data/v2/csv/pokemon_form_conditions.csv b/data/v2/csv/pokemon_form_conditions.csv index 8df92859a..61302109e 100644 --- a/data/v2/csv/pokemon_form_conditions.csv +++ b/data/v2/csv/pokemon_form_conditions.csv @@ -1,4 +1,4 @@ -pokemon_form_id,form_method_id,item_id,ability_id,move_id +pokemon_form_id,form_trigger_id,trigger_item_id,trigger_ability_id,trigger_move_id 493,1,1662,, 681,4,,176, 718,1,884,, @@ -173,52 +173,52 @@ pokemon_form_id,form_method_id,item_id,ability_id,move_id 10444,1,2108,, 10445,4,,304, 10446,3,1669,, -10503,1,2559,, -10504,1,2560,, -10505,1,2561,, -10506,1,2562,, -10507,1,2563,, -10508,1,2564,, -10509,1,2565,, -10510,1,2566,, -10511,1,2569,, -10512,1,2570,, -10513,1,2571,, -10514,1,2572,, -10515,1,2573,, -10516,1,2574,, -10517,1,2575,, -10518,1,2576,, -10519,1,2577,, -10520,1,2578,, -10521,1,2579,, -10522,1,2580,, -10523,1,2581,, -10524,1,2582,, -10525,1,2583,, -10526,1,2584,, -10527,1,2585,, -10528,1,2587,, -10529,1,2635,, -10530,1,2636,, -10531,1,2637,, -10532,1,2638,, -10533,1,2639,, -10534,1,2640,, -10535,1,2641,, -10536,1,2567,, -10537,1,2568,, -10538,1,2642,, -10539,1,2643,, -10540,1,2644,, -10541,1,2645,, -10542,1,2646,, -10543,1,2646,, -10544,1,2586,, -10545,1,2647,, -10546,1,2650,, -10547,1,2649,, -10548,1,2649,, -10549,1,2649,, -10550,1,2648,, -10554,1,2643,, +10503,1,2233,, +10504,1,2234,, +10505,1,2235,, +10506,1,2236,, +10507,1,2237,, +10508,1,2238,, +10509,1,2239,, +10510,1,2240,, +10511,1,2243,, +10512,1,2244,, +10513,1,2245,, +10514,1,2246,, +10515,1,2247,, +10516,1,2248,, +10517,1,2249,, +10518,1,2250,, +10519,1,2251,, +10520,1,2252,, +10521,1,2253,, +10522,1,2254,, +10523,1,2255,, +10524,1,2256,, +10525,1,2257,, +10526,1,2258,, +10527,1,2259,, +10528,1,2261,, +10529,1,2262,, +10530,1,2263,, +10531,1,2264,, +10532,1,2265,, +10533,1,2266,, +10534,1,2267,, +10535,1,2268,, +10536,1,2241,, +10537,1,2242,, +10538,1,2269,, +10539,1,2270,, +10540,1,2271,, +10541,1,2272,, +10542,1,2273,, +10543,1,2273,, +10544,1,2260,, +10545,1,2274,, +10546,1,2277,, +10547,1,2276,, +10548,1,2276,, +10549,1,2276,, +10550,1,2275,, +10554,1,2270,, diff --git a/data/v2/csv/pokemon_form_trigger_prose.csv b/data/v2/csv/pokemon_form_trigger_prose.csv new file mode 100644 index 000000000..8cf955230 --- /dev/null +++ b/data/v2/csv/pokemon_form_trigger_prose.csv @@ -0,0 +1,7 @@ +pokemon_form_trigger_id,local_language_id,name +1,9,Held item +2,9,Consumed item +3,9,Key item +4,9,Ability +5,9,Gigantamax factor +6,9,Move diff --git a/data/v2/csv/pokemon_form_methods.csv b/data/v2/csv/pokemon_form_triggers.csv similarity index 100% rename from data/v2/csv/pokemon_form_methods.csv rename to data/v2/csv/pokemon_form_triggers.csv diff --git a/pokemon_v2/migrations/0029_pokemonformmethod_pokemonformcondition.py b/pokemon_v2/migrations/0029_pokemonformmethod_pokemonformcondition.py deleted file mode 100644 index 1bf808287..000000000 --- a/pokemon_v2/migrations/0029_pokemonformmethod_pokemonformcondition.py +++ /dev/null @@ -1,37 +0,0 @@ -# Generated by Django 5.2.10 on 2026-06-29 04:01 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('pokemon_v2', '0028_pokemonevolution_evolved_form_and_more'), - ] - - operations = [ - migrations.CreateModel( - name='PokemonFormMethod', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(db_index=True, max_length=200)), - ], - options={ - 'abstract': False, - }, - ), - migrations.CreateModel( - name='PokemonFormCondition', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('ability', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='pokemon_v2.ability')), - ('item', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='pokemon_v2.item')), - ('pokemon_form', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s', to='pokemon_v2.pokemonform')), - ('form_method', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='pokemon_v2.pokemonformmethod')), - ], - options={ - 'abstract': False, - }, - ), - ] diff --git a/pokemon_v2/migrations/0029_pokemonformtrigger_pokemonformcondition.py b/pokemon_v2/migrations/0029_pokemonformtrigger_pokemonformcondition.py new file mode 100644 index 000000000..8f13f6af3 --- /dev/null +++ b/pokemon_v2/migrations/0029_pokemonformtrigger_pokemonformcondition.py @@ -0,0 +1,93 @@ +# Generated by Django 5.2.10 on 2026-07-01 16:03 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("pokemon_v2", "0028_pokemonevolution_evolved_form_and_more"), + ] + + operations = [ + migrations.CreateModel( + name="PokemonFormTrigger", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(db_index=True, max_length=200)), + ], + options={ + "abstract": False, + }, + ), + migrations.CreateModel( + name="PokemonFormCondition", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "ability", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + to="pokemon_v2.ability", + ), + ), + ( + "item", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + to="pokemon_v2.item", + ), + ), + ( + "move", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + to="pokemon_v2.move", + ), + ), + ( + "pokemon_form", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="%(class)s", + to="pokemon_v2.pokemonform", + ), + ), + ( + "form_trigger", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="pokemon_v2.pokemonformtrigger", + ), + ), + ], + options={ + "abstract": False, + }, + ), + ] diff --git a/pokemon_v2/migrations/0030_pokemonformcondition_move.py b/pokemon_v2/migrations/0030_pokemonformcondition_move.py deleted file mode 100644 index 51e8397a6..000000000 --- a/pokemon_v2/migrations/0030_pokemonformcondition_move.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 5.2.10 on 2026-06-30 08:04 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('pokemon_v2', '0029_pokemonformmethod_pokemonformcondition'), - ] - - operations = [ - migrations.AddField( - model_name='pokemonformcondition', - name='move', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='pokemon_v2.move'), - ), - ] diff --git a/pokemon_v2/models.py b/pokemon_v2/models.py index 688b8167a..e8311991c 100644 --- a/pokemon_v2/models.py +++ b/pokemon_v2/models.py @@ -1774,14 +1774,16 @@ class PokemonFormSprites(HasPokemonForm): sprites = models.JSONField() -class PokemonFormMethod(HasName): +class PokemonFormTrigger(HasName): pass class PokemonFormCondition(HasPokemonForm): - form_method = models.ForeignKey(PokemonFormMethod, on_delete=models.CASCADE) + form_trigger = models.ForeignKey(PokemonFormTrigger, on_delete=models.CASCADE) item = models.ForeignKey(Item, blank=True, null=True, on_delete=models.CASCADE) - ability = models.ForeignKey(Ability, blank=True, null=True, on_delete=models.CASCADE) + ability = models.ForeignKey( + Ability, blank=True, null=True, on_delete=models.CASCADE + ) move = models.ForeignKey(Move, blank=True, null=True, on_delete=models.CASCADE) diff --git a/pokemon_v2/serializers.py b/pokemon_v2/serializers.py index 506456509..7460dc49b 100644 --- a/pokemon_v2/serializers.py +++ b/pokemon_v2/serializers.py @@ -3892,15 +3892,17 @@ class Meta: model = PokemonFormName fields = ("name", "pokemon_name", "language") -class PokemonFormTriggerSerializer(serializers.ModelSerializer): - method = serializers.CharField(source="form_method.name", read_only=True) + +class PokemonFormConditionSerializer(serializers.ModelSerializer): + trigger = serializers.CharField(source="form_trigger.name", read_only=True) item = ItemSummarySerializer() ability = AbilitySummarySerializer() move = MoveSummarySerializer() class Meta: model = PokemonFormCondition - fields = ("method", "item", "ability", "move") + fields = ("trigger", "item", "ability", "move") + class PokemonFormDetailSerializer(serializers.ModelSerializer): pokemon = PokemonSummarySerializer() @@ -3909,7 +3911,9 @@ class PokemonFormDetailSerializer(serializers.ModelSerializer): form_names = serializers.SerializerMethodField("get_pokemon_form_names") names = serializers.SerializerMethodField("get_pokemon_form_pokemon_names") types = serializers.SerializerMethodField("get_pokemon_form_types") - trigger_conditions = serializers.SerializerMethodField("get_pokemon_form_triggers") + trigger_conditions = serializers.SerializerMethodField( + "get_pokemon_form_triggers_conditions" + ) class Meta: model = PokemonForm @@ -4099,9 +4103,9 @@ def get_pokemon_form_types(self, obj): "type": "array", "items": { "type": "object", - "required": ["method", "name", "url"], + "required": ["trigger", "name", "url"], "properties": { - "method": { + "trigger": { "type": "string", "examples": ["held-item"], }, @@ -4118,27 +4122,24 @@ def get_pokemon_form_types(self, obj): }, } ) - def get_pokemon_form_triggers(self, obj): - conditions = PokemonFormCondition.objects.filter( - pokemon_form=obj - ) - conditions_data = PokemonFormTriggerSerializer( + def get_pokemon_form_triggers_conditions(self, obj): + conditions = PokemonFormCondition.objects.filter(pokemon_form=obj) + conditions_data = PokemonFormConditionSerializer( conditions, many=True, context=self.context ).data triggers = [] for condition in conditions_data: - method = condition.pop("method", None) - if not method: + trigger_value = condition.pop("trigger", None) + if not trigger_value: continue - trigger = {"method": method} + trigger = {"trigger": trigger_value} for value in condition.values(): if value: trigger.update(value) break triggers.append(trigger) return triggers - ################################# diff --git a/pokemon_v2/tests.py b/pokemon_v2/tests.py index bb97abb03..b49c99e4a 100644 --- a/pokemon_v2/tests.py +++ b/pokemon_v2/tests.py @@ -1620,17 +1620,27 @@ def setup_pokemon_form_data( return pokemon_form @classmethod - def setup_pokemon_form_method_data(cls, name="frm mthd for pkmn frm"): - pokemon_form_method = PokemonFormMethod(name=name) - pokemon_form_method.save() - return pokemon_form_method + def setup_pokemon_form_trigger_data(cls, name="frm trgr for pkmn frm"): + pokemon_form_trigger = PokemonFormTrigger(name=name) + pokemon_form_trigger.save() + return pokemon_form_trigger @classmethod - def setup_pokemon_form_condition_data(cls, pokemon_form, form_method=None, item=None, ability=None, move=None): - form_method = form_method or cls.setup_pokemon_form_method_data(name="frm mthd for pkmn frm") + def setup_pokemon_form_condition_data( + cls, pokemon_form, form_trigger=None, item=None, ability=None, move=None + ): + form_trigger = form_trigger or cls.setup_pokemon_form_trigger_data( + name="frm trgr for pkmn frm" + ) item = item or cls.setup_item_data(name="itm for pkmn frm") - pokemon_form_condition = PokemonFormCondition(pokemon_form=pokemon_form, form_method=form_method, item=item, ability=ability, move=move) + pokemon_form_condition = PokemonFormCondition( + pokemon_form=pokemon_form, + form_trigger=form_trigger, + item=item, + ability=ability, + move=move, + ) pokemon_form_condition.save() return pokemon_form_condition @@ -5333,9 +5343,18 @@ def test_pokemon_form_api(self): "{}{}/type/{}/".format(TEST_HOST, API_V2, pokemon_form_type.type.pk), ) - self.assertEqual(response.data["trigger_conditions"][0]["method"], pokemon_form_condition.form_method.name) - self.assertEqual(response.data["trigger_conditions"][0]["name"], pokemon_form_condition.item.name) - self.assertEqual(response.data["trigger_conditions"][0]["url"], "{}{}/item/{}/".format(TEST_HOST, API_V2, pokemon_form_condition.item.pk)) + self.assertEqual( + response.data["trigger_conditions"][0]["trigger"], + pokemon_form_condition.form_trigger.name, + ) + self.assertEqual( + response.data["trigger_conditions"][0]["name"], + pokemon_form_condition.item.name, + ) + self.assertEqual( + response.data["trigger_conditions"][0]["url"], + "{}{}/item/{}/".format(TEST_HOST, API_V2, pokemon_form_condition.item.pk), + ) # Evolution test def test_evolution_trigger_api(self):