Add parties

This commit is contained in:
Gabriel Augendre 2022-11-02 23:10:48 +01:00
parent a8f7d04bdf
commit 596dd59780
12 changed files with 242 additions and 29 deletions

View file

@ -105,6 +105,11 @@ class CharacterAdminForm(ModelForm):
].queryset = models.RacialCapability.objects.select_related("race") ].queryset = models.RacialCapability.objects.select_related("race")
class PartyInline(admin.TabularInline):
model = models.Character.parties.through
extra = 0
@admin.register(models.Character) @admin.register(models.Character)
class CharacterAdmin(admin.ModelAdmin): class CharacterAdmin(admin.ModelAdmin):
list_display = ["name", "player", "race", "profile", "level"] list_display = ["name", "player", "race", "profile", "level"]
@ -185,6 +190,7 @@ class CharacterAdmin(admin.ModelAdmin):
"weapons", "weapons",
"states", "states",
] ]
inlines = [PartyInline]
form = CharacterAdminForm form = CharacterAdminForm
@ -204,3 +210,9 @@ class WeaponAdmin(admin.ModelAdmin):
class HarmfulStateAdmin(admin.ModelAdmin): class HarmfulStateAdmin(admin.ModelAdmin):
list_display = ["name", "description"] list_display = ["name", "description"]
search_fields = ["name"] search_fields = ["name"]
@admin.register(models.Party)
class PartyAdmin(admin.ModelAdmin):
list_display = ["name", "game_master"]
search_fields = ["name"]

View file

@ -0,0 +1,68 @@
# Generated by Django 4.1.2 on 2022-11-02 22:07
import django.db.models.deletion
import django_extensions.db.fields
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
("character", "0032_weapon_url"),
]
operations = [
migrations.CreateModel(
name="Party",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"name",
models.CharField(max_length=100, unique=True, verbose_name="nom"),
),
(
"created",
django_extensions.db.fields.CreationDateTimeField(
auto_now_add=True, verbose_name="created"
),
),
(
"modified",
django_extensions.db.fields.ModificationDateTimeField(
auto_now=True, verbose_name="modified"
),
),
(
"characters",
models.ManyToManyField(
blank=True,
related_name="parties",
to="character.character",
verbose_name="personnages",
),
),
(
"game_master",
models.ForeignKey(
on_delete=django.db.models.deletion.PROTECT,
related_name="parties",
to=settings.AUTH_USER_MODEL,
verbose_name="meneur de jeu",
),
),
],
options={
"abstract": False,
},
),
]

View file

@ -0,0 +1,17 @@
# Generated by Django 4.1.2 on 2022-11-02 22:07
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("character", "0033_party"),
]
operations = [
migrations.AlterModelOptions(
name="party",
options={"ordering": ["name"]},
),
]

View file

@ -0,0 +1,83 @@
# Generated by Django 4.1.2 on 2022-11-02 22:10
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("character", "0034_alter_party_options"),
]
operations = [
migrations.AlterModelOptions(
name="capability",
options={
"get_latest_by": "modified",
"verbose_name": "Capacité",
"verbose_name_plural": "Capacités",
},
),
migrations.AlterModelOptions(
name="harmfulstate",
options={
"get_latest_by": "modified",
"ordering": ["name"],
"verbose_name": "État préjudiciable",
"verbose_name_plural": "États préjudiciables",
},
),
migrations.AlterModelOptions(
name="party",
options={
"get_latest_by": "modified",
"ordering": ["name"],
"verbose_name": "Groupe",
"verbose_name_plural": "Groupes",
},
),
migrations.AlterModelOptions(
name="path",
options={
"get_latest_by": "modified",
"ordering": ["name"],
"verbose_name": "Voie",
"verbose_name_plural": "Voies",
},
),
migrations.AlterModelOptions(
name="profile",
options={
"get_latest_by": "modified",
"ordering": ["name"],
"verbose_name": "Profil",
"verbose_name_plural": "Profils",
},
),
migrations.AlterModelOptions(
name="race",
options={
"get_latest_by": "modified",
"ordering": ["name"],
"verbose_name": "Race",
"verbose_name_plural": "Races",
},
),
migrations.AlterModelOptions(
name="racialcapability",
options={
"get_latest_by": "modified",
"verbose_name": "Capacité raciale",
"verbose_name_plural": "Capacités raciales",
},
),
migrations.AlterModelOptions(
name="weapon",
options={
"get_latest_by": "modified",
"ordering": ["name"],
"verbose_name": "Arme",
"verbose_name_plural": "Armes",
},
),
]

View file

@ -1 +1 @@
0032_weapon_url 0035_alter_capability_options_alter_harmfulstate_options_and_more

View file

@ -1,6 +1,7 @@
from .capabilities import Capability, Path, RacialCapability from .capabilities import Capability, Path, RacialCapability
from .character import Character, HarmfulState, Profile, Race from .character import Character, HarmfulState, Profile, Race
from .equipment import Weapon from .equipment import Weapon
from .party import Party
__all__ = [ __all__ = [
"Capability", "Capability",
@ -11,4 +12,5 @@ __all__ = [
"Profile", "Profile",
"Race", "Race",
"Weapon", "Weapon",
"Party",
] ]

View file

@ -36,7 +36,7 @@ class Path(DocumentedModel, UniquelyNamedModel, TimeStampedModel, models.Model):
) )
notes = models.TextField(blank=True, verbose_name="notes") notes = models.TextField(blank=True, verbose_name="notes")
class Meta: class Meta(UniquelyNamedModel.Meta, TimeStampedModel.Meta):
verbose_name = "Voie" verbose_name = "Voie"
verbose_name_plural = "Voies" verbose_name_plural = "Voies"
@ -105,7 +105,7 @@ class Capability(DocumentedModel, TimeStampedModel, models.Model):
objects = CapabilityManager() objects = CapabilityManager()
class Meta: class Meta(TimeStampedModel.Meta):
constraints = [models.UniqueConstraint("path", "rank", name="unique_path_rank")] constraints = [models.UniqueConstraint("path", "rank", name="unique_path_rank")]
verbose_name = "Capacité" verbose_name = "Capacité"
verbose_name_plural = "Capacités" verbose_name_plural = "Capacités"
@ -134,7 +134,7 @@ class RacialCapability(DocumentedModel, TimeStampedModel, models.Model):
objects = RacialCapabilityManager() objects = RacialCapabilityManager()
class Meta: class Meta(TimeStampedModel.Meta):
verbose_name = "Capacité raciale" verbose_name = "Capacité raciale"
verbose_name_plural = "Capacités raciales" verbose_name_plural = "Capacités raciales"
constraints = [models.UniqueConstraint("name", "race", name="unique_name_race")] constraints = [models.UniqueConstraint("name", "race", name="unique_name_race")]

View file

@ -39,13 +39,13 @@ class Profile(DocumentedModel, UniquelyNamedModel, TimeStampedModel, models.Mode
) )
notes = models.TextField(blank=True, verbose_name="notes") notes = models.TextField(blank=True, verbose_name="notes")
class Meta: class Meta(UniquelyNamedModel.Meta, TimeStampedModel.Meta):
verbose_name = "Profil" verbose_name = "Profil"
verbose_name_plural = "Profils" verbose_name_plural = "Profils"
class Race(DocumentedModel, UniquelyNamedModel, TimeStampedModel, models.Model): class Race(DocumentedModel, UniquelyNamedModel, TimeStampedModel, models.Model):
class Meta: class Meta(UniquelyNamedModel.Meta, TimeStampedModel.Meta):
verbose_name = "Race" verbose_name = "Race"
verbose_name_plural = "Races" verbose_name_plural = "Races"
@ -54,10 +54,9 @@ class HarmfulState(DocumentedModel, UniquelyNamedModel, TimeStampedModel, models
description = models.TextField() description = models.TextField()
icon_url = models.URLField() icon_url = models.URLField()
class Meta: class Meta(UniquelyNamedModel.Meta, TimeStampedModel.Meta):
verbose_name = "État préjudiciable" verbose_name = "État préjudiciable"
verbose_name_plural = "États préjudiciables" verbose_name_plural = "États préjudiciables"
ordering = ["name"]
def modifier(value: int) -> int: def modifier(value: int) -> int:
@ -74,6 +73,14 @@ class CharacterManager(models.Manager):
return self.get(name=name, player_id=player_id) return self.get(name=name, player_id=player_id)
class CharacterQuerySet(models.QuerySet):
def managed_by(self, user):
return self.filter(player=user)
def owned_by(self, user):
return self.filter(player=user)
DEFAULT_NOTES = """ DEFAULT_NOTES = """
#### Traits personnalisés #### Traits personnalisés
@ -190,7 +197,7 @@ class Character(models.Model):
states = models.ManyToManyField(HarmfulState, blank=True, related_name="characters") states = models.ManyToManyField(HarmfulState, blank=True, related_name="characters")
objects = CharacterManager() objects = CharacterManager.from_queryset(CharacterQuerySet)()
class Meta: class Meta:
verbose_name = "Personnage" verbose_name = "Personnage"

View file

@ -16,6 +16,6 @@ class Weapon(UniquelyNamedModel, DocumentedModel, TimeStampedModel, models.Model
max_length=3, choices=Category.choices, default=Category.NONE max_length=3, choices=Category.choices, default=Category.NONE
) )
class Meta: class Meta(UniquelyNamedModel.Meta, TimeStampedModel.Meta):
verbose_name = "Arme" verbose_name = "Arme"
verbose_name_plural = "Armes" verbose_name_plural = "Armes"

View file

@ -0,0 +1,23 @@
from django.db import models
from django_extensions.db.models import TimeStampedModel
from common.models import UniquelyNamedModel
class Party(UniquelyNamedModel, TimeStampedModel, models.Model):
game_master = models.ForeignKey(
"common.User",
on_delete=models.PROTECT,
related_name="parties",
verbose_name="meneur de jeu",
)
characters = models.ManyToManyField(
"character.Character",
blank=True,
related_name="parties",
verbose_name="personnages",
)
class Meta(UniquelyNamedModel.Meta, TimeStampedModel.Meta):
verbose_name = "Groupe"
verbose_name_plural = "Groupes"

View file

@ -11,7 +11,7 @@ from character.templatetags.character_extras import modifier
@login_required @login_required
def characters_list(request): def characters_list(request):
context = { context = {
"characters": Character.objects.filter(player=request.user).select_related( "characters": Character.objects.owned_by(request.user).select_related(
"race", "profile" "race", "profile"
) )
} }
@ -26,7 +26,7 @@ def character_create(request):
@login_required @login_required
def character_view(request, pk: int): def character_view(request, pk: int):
character = get_object_or_404( character = get_object_or_404(
Character.objects.filter(player=request.user) Character.objects.managed_by(request.user)
.select_related("player", "racial_capability", "profile", "race") .select_related("player", "racial_capability", "profile", "race")
.prefetch_related("capabilities__path", "weapons"), .prefetch_related("capabilities__path", "weapons"),
pk=pk, pk=pk,
@ -42,7 +42,7 @@ def character_view(request, pk: int):
@login_required @login_required
def add_path(request, pk: int): def add_path(request, pk: int):
character = get_object_or_404(Character.objects.filter(player=request.user), pk=pk) character = get_object_or_404(Character.objects.managed_by(request.user), pk=pk)
form = AddPathForm(character, request.POST) form = AddPathForm(character, request.POST)
context = {"character": character} context = {"character": character}
if form.is_valid(): if form.is_valid():
@ -64,7 +64,7 @@ def add_path(request, pk: int):
@login_required @login_required
def character_health_change(request, pk: int): def character_health_change(request, pk: int):
character = get_object_or_404( character = get_object_or_404(
Character.objects.filter(player=request.user).only( Character.objects.managed_by(request.user).only(
"health_max", "health_remaining" "health_max", "health_remaining"
), ),
pk=pk, pk=pk,
@ -78,7 +78,7 @@ def character_health_change(request, pk: int):
@login_required @login_required
def character_mana_change(request, pk: int): def character_mana_change(request, pk: int):
character = get_object_or_404( character = get_object_or_404(
Character.objects.filter(player=request.user) Character.objects.managed_by(request.user)
.only("mana_remaining", "level", "value_intelligence", "profile") .only("mana_remaining", "level", "value_intelligence", "profile")
.select_related("profile"), .select_related("profile"),
pk=pk, pk=pk,
@ -92,7 +92,7 @@ def character_mana_change(request, pk: int):
@login_required @login_required
def character_recovery_points_change(request, pk: int): def character_recovery_points_change(request, pk: int):
character = get_object_or_404( character = get_object_or_404(
Character.objects.filter(player=request.user).only("recovery_points_remaining"), Character.objects.managed_by(request.user).only("recovery_points_remaining"),
pk=pk, pk=pk,
) )
value = get_updated_value( value = get_updated_value(
@ -106,7 +106,7 @@ def character_recovery_points_change(request, pk: int):
@login_required @login_required
def character_defense_misc_change(request, pk: int): def character_defense_misc_change(request, pk: int):
character = get_object_or_404( character = get_object_or_404(
Character.objects.filter(player=request.user).only("defense_misc"), pk=pk Character.objects.managed_by(request.user).only("defense_misc"), pk=pk
) )
value = get_updated_value(request, character.defense_misc, float("inf")) value = get_updated_value(request, character.defense_misc, float("inf"))
character.defense_misc = value character.defense_misc = value
@ -118,7 +118,7 @@ def character_defense_misc_change(request, pk: int):
@login_required @login_required
def character_shield_change(request, pk: int): def character_shield_change(request, pk: int):
character = get_object_or_404( character = get_object_or_404(
Character.objects.filter(player=request.user).only("shield"), pk=pk Character.objects.managed_by(request.user).only("shield"), pk=pk
) )
value = get_updated_value(request, character.shield, float("inf")) value = get_updated_value(request, character.shield, float("inf"))
character.shield = value character.shield = value
@ -130,7 +130,7 @@ def character_shield_change(request, pk: int):
@login_required @login_required
def character_armor_change(request, pk: int): def character_armor_change(request, pk: int):
character = get_object_or_404( character = get_object_or_404(
Character.objects.filter(player=request.user).only("armor"), pk=pk Character.objects.managed_by(request.user).only("armor"), pk=pk
) )
value = get_updated_value(request, character.armor, float("inf")) value = get_updated_value(request, character.armor, float("inf"))
character.armor = value character.armor = value
@ -142,7 +142,7 @@ def character_armor_change(request, pk: int):
@login_required @login_required
def character_initiative_misc_change(request, pk: int): def character_initiative_misc_change(request, pk: int):
character = get_object_or_404( character = get_object_or_404(
Character.objects.filter(player=request.user).only("initiative_misc"), pk=pk Character.objects.managed_by(request.user).only("initiative_misc"), pk=pk
) )
value = get_updated_value(request, character.initiative_misc, float("inf")) value = get_updated_value(request, character.initiative_misc, float("inf"))
character.initiative_misc = value character.initiative_misc = value
@ -154,7 +154,7 @@ def character_initiative_misc_change(request, pk: int):
@login_required @login_required
def character_luck_points_change(request, pk: int): def character_luck_points_change(request, pk: int):
character = get_object_or_404( character = get_object_or_404(
Character.objects.filter(player=request.user).only( Character.objects.managed_by(request.user).only(
"luck_points_remaining", "value_charisma" "luck_points_remaining", "value_charisma"
), ),
pk=pk, pk=pk,
@ -184,7 +184,7 @@ def get_updated_value(request, remaining_value: int, max_value: int | float) ->
@login_required @login_required
def character_get_defense(request, pk: int): def character_get_defense(request, pk: int):
character = get_object_or_404( character = get_object_or_404(
Character.objects.filter(player=request.user).only( Character.objects.managed_by(request.user).only(
"defense_misc", "armor", "shield", "value_dexterity" "defense_misc", "armor", "shield", "value_dexterity"
), ),
pk=pk, pk=pk,
@ -195,7 +195,7 @@ def character_get_defense(request, pk: int):
@login_required @login_required
def character_get_initiative(request, pk: int): def character_get_initiative(request, pk: int):
character = get_object_or_404( character = get_object_or_404(
Character.objects.filter(player=request.user).only( Character.objects.managed_by(request.user).only(
"initiative_misc", "value_dexterity" "initiative_misc", "value_dexterity"
), ),
pk=pk, pk=pk,
@ -212,7 +212,7 @@ def character_notes_change(request, pk: int):
def character_equipment_change(request, pk: int): def character_equipment_change(request, pk: int):
field = "equipment" field = "equipment"
character = get_object_or_404( character = get_object_or_404(
Character.objects.filter(player=request.user).only(field), pk=pk Character.objects.managed_by(request.user).only(field), pk=pk
) )
context = {"character": character} context = {"character": character}
if request.method == "GET": if request.method == "GET":
@ -245,7 +245,7 @@ def character_damage_reduction_change(request, pk: int):
def update_text_field(request, pk, field): def update_text_field(request, pk, field):
character = get_object_or_404( character = get_object_or_404(
Character.objects.filter(player=request.user).only(field), pk=pk Character.objects.managed_by(request.user).only(field), pk=pk
) )
context = {"character": character} context = {"character": character}
if request.method == "GET": if request.method == "GET":
@ -264,7 +264,7 @@ def update_text_field(request, pk, field):
@login_required @login_required
def add_next_in_path(request, character_pk: int, path_pk: int): def add_next_in_path(request, character_pk: int, path_pk: int):
character = get_object_or_404( character = get_object_or_404(
Character.objects.filter(player=request.user), pk=character_pk Character.objects.managed_by(request.user), pk=character_pk
) )
path = get_object_or_404(Path, pk=path_pk) path = get_object_or_404(Path, pk=path_pk)
capability = path.get_next_capability(character) capability = path.get_next_capability(character)
@ -283,7 +283,7 @@ def add_next_in_path(request, character_pk: int, path_pk: int):
@login_required @login_required
def remove_last_in_path(request, character_pk: int, path_pk: int): def remove_last_in_path(request, character_pk: int, path_pk: int):
character = get_object_or_404( character = get_object_or_404(
Character.objects.filter(player=request.user), pk=character_pk Character.objects.managed_by(request.user), pk=character_pk
) )
last_rank = max( last_rank = max(
character.capabilities.filter(path_id=path_pk).values_list("rank", flat=True) character.capabilities.filter(path_id=path_pk).values_list("rank", flat=True)
@ -304,7 +304,7 @@ def remove_last_in_path(request, character_pk: int, path_pk: int):
@login_required @login_required
def remove_state(request, pk: int, state_pk: int): def remove_state(request, pk: int, state_pk: int):
character: Character = get_object_or_404( character: Character = get_object_or_404(
Character.objects.filter(player=request.user), pk=pk Character.objects.managed_by(request.user), pk=pk
) )
state = get_object_or_404(HarmfulState, pk=state_pk) state = get_object_or_404(HarmfulState, pk=state_pk)
character.states.remove(state) character.states.remove(state)
@ -318,7 +318,7 @@ def remove_state(request, pk: int, state_pk: int):
@login_required @login_required
def add_state(request, pk: int, state_pk: int): def add_state(request, pk: int, state_pk: int):
character: Character = get_object_or_404( character: Character = get_object_or_404(
Character.objects.filter(player=request.user), pk=pk Character.objects.managed_by(request.user), pk=pk
) )
state = get_object_or_404(HarmfulState, pk=state_pk) state = get_object_or_404(HarmfulState, pk=state_pk)
character.states.add(state) character.states.add(state)

View file

@ -19,6 +19,7 @@ class UniquelyNamedModel(models.Model):
class Meta: class Meta:
abstract = True abstract = True
ordering = ["name"]
def __str__(self): def __str__(self):
return self.name return self.name