Move parties to separate app

This commit is contained in:
Gabriel Augendre 2022-11-02 23:52:28 +01:00
parent 7aeb983f99
commit bb55490a91
23 changed files with 268 additions and 13 deletions

View file

@ -29,6 +29,7 @@
<list>
<option value="$MODULE_DIR$/src/common/templates" />
<option value="$MODULE_DIR$/src/character/templates" />
<option value="$MODULE_DIR$/src/party/templates" />
</list>
</option>
</component>

View file

@ -210,9 +210,3 @@ 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,19 @@
# Generated by Django 4.1.2 on 2022-11-02 22:28
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
(
"character",
"0035_alter_capability_options_alter_harmfulstate_options_and_more",
),
]
operations = [
migrations.DeleteModel(
name="Party",
),
]

View file

@ -1 +1 @@
0035_alter_capability_options_alter_harmfulstate_options_and_more
0036_delete_party

View file

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

View file

@ -75,6 +75,7 @@ CUSTOM_APPS = [
"whitenoise.runserver_nostatic", # should be first
"common",
"character",
"party",
]
INSTALLED_APPS = CUSTOM_APPS + DJANGO_APPS + EXTERNAL_APPS

View file

@ -48,6 +48,7 @@ urlpatterns = [
path("admin/", admin.site.urls),
path("", hello_world, name="hello_world"),
path("character/", include("character.urls", namespace="character")),
path("party/", include("party.urls", namespace="party")),
]
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

View file

@ -7,16 +7,21 @@
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link" aria-current="page" href="{% url "character:list" %}">Mes perso</a>
<a class="nav-link" href="{% url "character:list" %}">Mes perso</a>
</li>
<li class="nav-item">
<a class="nav-link" aria-current="page" href="{% url "character:list" %}">Mes groupes</a>
<a class="nav-link" href="{% url "party:list" %}">Mes groupes</a>
</li>
</ul>
<ul class="navbar-nav">
{% if user.is_staff %}
<li class="nav-item">
<a class="nav-link" href="{% url "admin:index" %}">Admin</a>
</li>
{% endif %}
{% if user.is_authenticated %}
<li class="nav-item">
<a class="nav-link" aria-current="page" href="{% url "logout" %}">Déconnexion</a>
<a class="nav-link" href="{% url "logout" %}">Déconnexion</a>
</li>
{% endif %}
</ul>

0
src/party/__init__.py Normal file
View file

9
src/party/admin.py Normal file
View file

@ -0,0 +1,9 @@
from django.contrib import admin
from party import models
@admin.register(models.Party)
class PartyAdmin(admin.ModelAdmin):
list_display = ["name", "game_master"]
search_fields = ["name"]

6
src/party/apps.py Normal file
View file

@ -0,0 +1,6 @@
from django.apps import AppConfig
class PartyConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "party"

9
src/party/forms.py Normal file
View file

@ -0,0 +1,9 @@
from django import forms
from party.models import Party
class PartyForm(forms.ModelForm):
class Meta:
model = Party
fields = ["name", "characters"]

View file

@ -0,0 +1,74 @@
# Generated by Django 4.1.2 on 2022-11-02 22:28
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):
initial = True
dependencies = [
("character", "0036_delete_party"),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
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={
"verbose_name": "Groupe",
"verbose_name_plural": "Groupes",
"ordering": ["name"],
"get_latest_by": "modified",
"abstract": False,
},
),
]

View file

View file

@ -0,0 +1 @@
0001_initial

View file

@ -1,7 +1,20 @@
from django.db import models
from django_extensions.db.models import TimeStampedModel
from common.models import UniquelyNamedModel
from character.models import Character
from common.models import UniquelyNamedModel, UniquelyNamedModelManager
class PartyQuerySet(models.QuerySet):
def managed_by(self, user):
return self.filter(game_master=user)
def played_by(self, user):
return self.filter(characters__in=Character.objects.filter(player=user))
class PartyManager(UniquelyNamedModelManager):
pass
class Party(UniquelyNamedModel, TimeStampedModel, models.Model):
@ -18,6 +31,8 @@ class Party(UniquelyNamedModel, TimeStampedModel, models.Model):
verbose_name="personnages",
)
objects = PartyManager.from_queryset(PartyQuerySet)()
class Meta(UniquelyNamedModel.Meta, TimeStampedModel.Meta):
verbose_name = "Groupe"
verbose_name_plural = "Groupes"

View file

@ -0,0 +1,27 @@
{% extends "common/base.html" %}
{% load character_extras %}
{% block title %}Groupes{% endblock %}
{% block content %}
<h1>Groupes</h1>
<a href="{% url "party:create" %}" class="btn btn-primary mb-3">
<i class="fa-solid fa-user-plus"></i> Nouveau groupe
</a>
<h2>Groupes que vous gérez</h2>
<div class="row row-cols-1 row-cols-sm-2 row-cols-md-3 row-cols-lg-4 g-4">
{% for party in managed_parties %}
{% include "party/snippets/party_card.html" %}
{% empty %}
<div class="col">Aucun</div>
{% endfor %}
</div>
<h2 class="mt-3">Groupes dont vous êtes membre</h2>
<div class="row row-cols-1 row-cols-sm-2 row-cols-md-3 row-cols-lg-4 g-4">
{% for party in played_parties %}
{% include "party/snippets/party_card.html" %}
{% empty %}
<div class="col">Aucun</div>
{% endfor %}
</div>
{% endblock %}

View file

@ -0,0 +1,14 @@
{% extends "common/base.html" %}
{% load django_bootstrap5 %}
{% load character_extras %}
{% block title %}Créer groupe{% endblock %}
{% block content %}
<h1>Créer un groupe</h1>
<form action="{% url "party:create" %}" method="post">
{% csrf_token %}
{% bootstrap_form form %}
{% bootstrap_button type="submit" content="Créer" %}
</form>
{% endblock %}

View file

@ -0,0 +1,12 @@
<div class="col">
<div class="card">
<div class="card-body">
<h5 class="card-title">
{{ party.name }}
</h5>
<a href="" class="btn btn-sm btn-success">
<i class="fa-solid fa-users"></i> Accéder
</a>
</div>
</div>
</div>

View file

View file

@ -0,0 +1,30 @@
from model_bakery import baker
from character.models import Character
from common.models import User
from party.models import Party
def test_party_managed_by(db):
game_master = User.objects.create_user("game_master")
other_user = User.objects.create_user("other")
expected = Party.objects.create(name="some name", game_master=game_master)
Party.objects.create(name="some other name", game_master=other_user)
related_to = Party.objects.managed_by(game_master)
assert len(related_to) == 1
assert related_to[0] == expected
def test_party_played_by(db):
player = User.objects.create_user("game_master")
player_character = baker.make(Character, player=player)
other_user = User.objects.create_user("other")
other_character = baker.make(Character, player=other_user)
expected = Party.objects.create(name="some name", game_master=other_user)
expected.characters.add(player_character)
other_party = Party.objects.create(name="some other name", game_master=other_user)
other_party.characters.add(other_character)
related_to = Party.objects.played_by(player)
assert len(related_to) == 1
assert related_to[0] == expected

9
src/party/urls.py Normal file
View file

@ -0,0 +1,9 @@
from django.urls import path
from party import views
app_name = "party"
urlpatterns = [
path("", views.parties_list, name="list"),
path("create/", views.party_create, name="create"),
]

30
src/party/views.py Normal file
View file

@ -0,0 +1,30 @@
from django.contrib.auth.decorators import login_required
from django.shortcuts import redirect, render
from party.forms import PartyForm
from party.models import Party
@login_required
def parties_list(request):
context = {
"managed_parties": Party.objects.managed_by(request.user),
"played_parties": Party.objects.played_by(request.user),
}
return render(request, "party/parties_list.html", context)
@login_required
def party_create(request):
if request.method == "GET":
form = PartyForm()
else:
form = PartyForm(request.POST)
if form.is_valid():
party = form.save(commit=False)
party.game_master = request.user
party.save()
form.save_m2m()
return redirect("party:list")
context = {"form": form}
return render(request, "party/party_create.html", context)