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")
class PartyInline(admin.TabularInline):
model = models.Character.parties.through
extra = 0
@admin.register(models.Character)
class CharacterAdmin(admin.ModelAdmin):
list_display = ["name", "player", "race", "profile", "level"]
@ -185,6 +190,7 @@ class CharacterAdmin(admin.ModelAdmin):
"weapons",
"states",
]
inlines = [PartyInline]
form = CharacterAdminForm
@ -204,3 +210,9 @@ class WeaponAdmin(admin.ModelAdmin):
class HarmfulStateAdmin(admin.ModelAdmin):
list_display = ["name", "description"]
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 .character import Character, HarmfulState, Profile, Race
from .equipment import Weapon
from .party import Party
__all__ = [
"Capability",
@ -11,4 +12,5 @@ __all__ = [
"Profile",
"Race",
"Weapon",
"Party",
]

View file

@ -36,7 +36,7 @@ class Path(DocumentedModel, UniquelyNamedModel, TimeStampedModel, models.Model):
)
notes = models.TextField(blank=True, verbose_name="notes")
class Meta:
class Meta(UniquelyNamedModel.Meta, TimeStampedModel.Meta):
verbose_name = "Voie"
verbose_name_plural = "Voies"
@ -105,7 +105,7 @@ class Capability(DocumentedModel, TimeStampedModel, models.Model):
objects = CapabilityManager()
class Meta:
class Meta(TimeStampedModel.Meta):
constraints = [models.UniqueConstraint("path", "rank", name="unique_path_rank")]
verbose_name = "Capacité"
verbose_name_plural = "Capacités"
@ -134,7 +134,7 @@ class RacialCapability(DocumentedModel, TimeStampedModel, models.Model):
objects = RacialCapabilityManager()
class Meta:
class Meta(TimeStampedModel.Meta):
verbose_name = "Capacité raciale"
verbose_name_plural = "Capacités raciales"
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")
class Meta:
class Meta(UniquelyNamedModel.Meta, TimeStampedModel.Meta):
verbose_name = "Profil"
verbose_name_plural = "Profils"
class Race(DocumentedModel, UniquelyNamedModel, TimeStampedModel, models.Model):
class Meta:
class Meta(UniquelyNamedModel.Meta, TimeStampedModel.Meta):
verbose_name = "Race"
verbose_name_plural = "Races"
@ -54,10 +54,9 @@ class HarmfulState(DocumentedModel, UniquelyNamedModel, TimeStampedModel, models
description = models.TextField()
icon_url = models.URLField()
class Meta:
class Meta(UniquelyNamedModel.Meta, TimeStampedModel.Meta):
verbose_name = "État préjudiciable"
verbose_name_plural = "États préjudiciables"
ordering = ["name"]
def modifier(value: int) -> int:
@ -74,6 +73,14 @@ class CharacterManager(models.Manager):
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 = """
#### Traits personnalisés
@ -190,7 +197,7 @@ class Character(models.Model):
states = models.ManyToManyField(HarmfulState, blank=True, related_name="characters")
objects = CharacterManager()
objects = CharacterManager.from_queryset(CharacterQuerySet)()
class Meta:
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
)
class Meta:
class Meta(UniquelyNamedModel.Meta, TimeStampedModel.Meta):
verbose_name = "Arme"
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
def characters_list(request):
context = {
"characters": Character.objects.filter(player=request.user).select_related(
"characters": Character.objects.owned_by(request.user).select_related(
"race", "profile"
)
}
@ -26,7 +26,7 @@ def character_create(request):
@login_required
def character_view(request, pk: int):
character = get_object_or_404(
Character.objects.filter(player=request.user)
Character.objects.managed_by(request.user)
.select_related("player", "racial_capability", "profile", "race")
.prefetch_related("capabilities__path", "weapons"),
pk=pk,
@ -42,7 +42,7 @@ def character_view(request, pk: int):
@login_required
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)
context = {"character": character}
if form.is_valid():
@ -64,7 +64,7 @@ def add_path(request, pk: int):
@login_required
def character_health_change(request, pk: int):
character = get_object_or_404(
Character.objects.filter(player=request.user).only(
Character.objects.managed_by(request.user).only(
"health_max", "health_remaining"
),
pk=pk,
@ -78,7 +78,7 @@ def character_health_change(request, pk: int):
@login_required
def character_mana_change(request, pk: int):
character = get_object_or_404(
Character.objects.filter(player=request.user)
Character.objects.managed_by(request.user)
.only("mana_remaining", "level", "value_intelligence", "profile")
.select_related("profile"),
pk=pk,
@ -92,7 +92,7 @@ def character_mana_change(request, pk: int):
@login_required
def character_recovery_points_change(request, pk: int):
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,
)
value = get_updated_value(
@ -106,7 +106,7 @@ def character_recovery_points_change(request, pk: int):
@login_required
def character_defense_misc_change(request, pk: int):
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"))
character.defense_misc = value
@ -118,7 +118,7 @@ def character_defense_misc_change(request, pk: int):
@login_required
def character_shield_change(request, pk: int):
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"))
character.shield = value
@ -130,7 +130,7 @@ def character_shield_change(request, pk: int):
@login_required
def character_armor_change(request, pk: int):
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"))
character.armor = value
@ -142,7 +142,7 @@ def character_armor_change(request, pk: int):
@login_required
def character_initiative_misc_change(request, pk: int):
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"))
character.initiative_misc = value
@ -154,7 +154,7 @@ def character_initiative_misc_change(request, pk: int):
@login_required
def character_luck_points_change(request, pk: int):
character = get_object_or_404(
Character.objects.filter(player=request.user).only(
Character.objects.managed_by(request.user).only(
"luck_points_remaining", "value_charisma"
),
pk=pk,
@ -184,7 +184,7 @@ def get_updated_value(request, remaining_value: int, max_value: int | float) ->
@login_required
def character_get_defense(request, pk: int):
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"
),
pk=pk,
@ -195,7 +195,7 @@ def character_get_defense(request, pk: int):
@login_required
def character_get_initiative(request, pk: int):
character = get_object_or_404(
Character.objects.filter(player=request.user).only(
Character.objects.managed_by(request.user).only(
"initiative_misc", "value_dexterity"
),
pk=pk,
@ -212,7 +212,7 @@ def character_notes_change(request, pk: int):
def character_equipment_change(request, pk: int):
field = "equipment"
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}
if request.method == "GET":
@ -245,7 +245,7 @@ def character_damage_reduction_change(request, pk: int):
def update_text_field(request, pk, field):
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}
if request.method == "GET":
@ -264,7 +264,7 @@ def update_text_field(request, pk, field):
@login_required
def add_next_in_path(request, character_pk: int, path_pk: int):
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)
capability = path.get_next_capability(character)
@ -283,7 +283,7 @@ def add_next_in_path(request, character_pk: int, path_pk: int):
@login_required
def remove_last_in_path(request, character_pk: int, path_pk: int):
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(
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
def remove_state(request, pk: int, state_pk: int):
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)
character.states.remove(state)
@ -318,7 +318,7 @@ def remove_state(request, pk: int, state_pk: int):
@login_required
def add_state(request, pk: int, state_pk: int):
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)
character.states.add(state)

View file

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