NPCs
This commit is contained in:
parent
11292774f2
commit
a9648c12b8
|
@ -1,5 +1,6 @@
|
|||
from typing import Any
|
||||
from django import forms
|
||||
from guild.models import PlaySession, Character, Reward
|
||||
from guild.models import NPC, PlaySession, Character, Reward
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
|
||||
|
@ -11,14 +12,22 @@ class PlaySessionCharacterForm(forms.ModelMultipleChoiceField):
|
|||
return character.name
|
||||
|
||||
|
||||
class PlaySessionNPCForm(forms.ModelMultipleChoiceField):
|
||||
def label_from_instance(self, npc):
|
||||
return npc.name
|
||||
|
||||
|
||||
class PlaySessionForm(forms.ModelForm):
|
||||
characters = PlaySessionCharacterForm(
|
||||
queryset=Character.objects.all(), widget=forms.CheckboxSelectMultiple
|
||||
)
|
||||
npcs = PlaySessionNPCForm(
|
||||
queryset=NPC.objects.all(), widget=forms.CheckboxSelectMultiple, required=False
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = PlaySession
|
||||
fields = ["date", "characters", "summary"]
|
||||
fields = ["date", "characters", "summary", "npcs"]
|
||||
# set date wideget to type="date"
|
||||
widgets = {
|
||||
"date": forms.DateInput(attrs={"type": "date"}),
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
# Generated by Django 4.2.1 on 2023-08-25 18:41
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("guild", "0012_alter_character_options_alter_character_picture"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="NPC",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("name", models.CharField(max_length=255)),
|
||||
("description", models.TextField()),
|
||||
(
|
||||
"picture",
|
||||
models.ImageField(
|
||||
blank=True,
|
||||
null=True,
|
||||
upload_to="uploads/",
|
||||
verbose_name="NPC Picture",
|
||||
),
|
||||
),
|
||||
(
|
||||
"created_at",
|
||||
models.DateTimeField(auto_now_add=True, verbose_name="created at"),
|
||||
),
|
||||
(
|
||||
"updated_at",
|
||||
models.DateTimeField(auto_now=True, verbose_name="updated at"),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "npc",
|
||||
"verbose_name_plural": "npcs",
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="playsession",
|
||||
name="npcs",
|
||||
field=models.ManyToManyField(to="guild.npc", verbose_name="npcs"),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,19 @@
|
|||
# Generated by Django 4.2.1 on 2023-08-25 18:52
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("guild", "0013_npc_playsession_npcs"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="playsession",
|
||||
name="npcs",
|
||||
field=models.ManyToManyField(
|
||||
blank=True, to="guild.npc", verbose_name="npcs"
|
||||
),
|
||||
),
|
||||
]
|
|
@ -116,6 +116,7 @@ class PlaySession(models.Model):
|
|||
"Adventure", verbose_name=_("adventure"), on_delete=models.CASCADE
|
||||
)
|
||||
characters = models.ManyToManyField("Character", verbose_name=_("characters"))
|
||||
npcs = models.ManyToManyField("NPC", verbose_name=_("npcs"), blank=True)
|
||||
|
||||
summary = models.TextField()
|
||||
|
||||
|
@ -199,3 +200,25 @@ class Reward(models.Model):
|
|||
|
||||
def get_absolute_url(self):
|
||||
return reverse("guild:reward_detail", kwargs={"pk": self.pk})
|
||||
|
||||
|
||||
class NPC(models.Model):
|
||||
name = models.CharField(max_length=255)
|
||||
description = models.TextField()
|
||||
|
||||
picture = models.ImageField(
|
||||
_("NPC Picture"), null=True, blank=True, upload_to="uploads/"
|
||||
)
|
||||
|
||||
created_at = models.DateTimeField(_("created at"), auto_now_add=True)
|
||||
updated_at = models.DateTimeField(_("updated at"), auto_now=True)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("npc")
|
||||
verbose_name_plural = _("npcs")
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse("guild:npc_detail", kwargs={"pk": self.pk})
|
||||
|
|
|
@ -8,11 +8,13 @@
|
|||
<div class="column column-75">
|
||||
<hrgroup>
|
||||
<h1>Adventure: {{ adventure.name }}</h1>
|
||||
<h4>Mastered by:
|
||||
<a href="{% url 'guild:player_detail' adventure.master.id %}">
|
||||
{{ adventure.master }}
|
||||
</a>
|
||||
</h4>
|
||||
{% if adventure.master %}
|
||||
<h4>Mastered by:
|
||||
<a href="{% url 'guild:player_detail' adventure.master.id %}">
|
||||
{{ adventure.master }}
|
||||
</a>
|
||||
</h4>
|
||||
{% endif %}
|
||||
</hrgroup>
|
||||
</div>
|
||||
<div class="column">
|
||||
|
|
|
@ -55,6 +55,25 @@
|
|||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
<div class="row">
|
||||
<div class="column column-75">
|
||||
<h2>NPCs</h2>
|
||||
</div>
|
||||
<div class="column column-25">
|
||||
<a class="button button-outline" href="{% url 'guild:create_npc' %}">Create New NPC</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ul>
|
||||
{% for npc in npcs %}
|
||||
<li>
|
||||
<a href="{% url 'guild:npc_detail' npc.id %}">
|
||||
{{ npc.name }}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
<div class="row">
|
||||
<div class="column column-75">
|
||||
<h2>Players</h2>
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h1>Session Delete</h1>
|
||||
|
||||
<p>Are you sure you want to delete <strong>{{ character.name}}</strong>?</p>
|
||||
|
||||
<form action="" method="post">
|
||||
{% csrf_token %}
|
||||
{{ form.as_p }}
|
||||
<input type="submit" value="Delete Character">
|
||||
</form>
|
||||
{% endblock content %}
|
|
@ -0,0 +1,52 @@
|
|||
{% extends 'base.html' %}
|
||||
|
||||
{% load guild_extras %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="row">
|
||||
<div class="column column-75">
|
||||
<hrgroup>
|
||||
<h1>NPCs: {{ npc.name }}</h1>
|
||||
<h4>
|
||||
{{ npc.get_status_display }}
|
||||
</h4>
|
||||
</hrgroup>
|
||||
</div>
|
||||
<div class="column">
|
||||
<a class="button button-outline" href="{% url 'guild:npc_update' npc.id %}">Edit</a>
|
||||
</div>
|
||||
<div class="column">
|
||||
<a class="button button-clear" href="{% url 'guild:npc_delete' npc.id %}">Delete</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
</div>
|
||||
{% if npc.picture %}
|
||||
<a href="{{npc.picture.url}}" style="float:left;margin-right:10px;margin-bottom:10px;">
|
||||
<img src="{{npc.picture.url}}" width="300"/>
|
||||
</a>
|
||||
{% endif %}
|
||||
<p>{{npc.description|md|safe}}</p>
|
||||
<div class="column">
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
<h2>Session History</h2>
|
||||
|
||||
{% if not npc.playsession_set.count %}
|
||||
<p>No appearance yet.</p>
|
||||
{% else %}
|
||||
<ul>
|
||||
{% for session in npc.playsession_set.all %}
|
||||
<li>
|
||||
<a href="{% url 'guild:adventure_detail' session.adventure.id %}">
|
||||
{{session.date}} - {{ session.adventure.name }}
|
||||
</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
{% endblock content %}
|
|
@ -0,0 +1,13 @@
|
|||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<form action="" method="post" enctype="multipart/form-data" >
|
||||
{% csrf_token %}
|
||||
{{ form.as_p }}
|
||||
{% if object %}
|
||||
<input type="submit" value="Update NPC">
|
||||
{% else %}
|
||||
<input type="submit" value="Create NPC">
|
||||
{% endif %}
|
||||
</form>
|
||||
{% endblock content %}
|
|
@ -74,4 +74,14 @@
|
|||
|
||||
<p>{{playsession.summary|md|safe}}</p>
|
||||
|
||||
|
||||
<h3>NPC Appearances</h3>
|
||||
|
||||
<ul>
|
||||
{% for npc in playsession.npcs.all %}
|
||||
<li><a href="{% url 'guild:npc_detail' npc.id %}">{{ npc.name }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
|
||||
{% endblock content %}
|
|
@ -2,6 +2,7 @@ from django.urls import path
|
|||
import guild.views as views
|
||||
import guild.views.player as player_views
|
||||
import guild.views.character as character_views
|
||||
import guild.views.npc as npc_views
|
||||
import guild.views.adventure as adventure_views
|
||||
import guild.views.playsession as playsession_views
|
||||
import guild.views.settings as settings_views
|
||||
|
@ -137,4 +138,24 @@ urlpatterns = [
|
|||
resource_views.ResourceUpdateView.as_view(),
|
||||
name="resource_update",
|
||||
),
|
||||
path(
|
||||
"npcs/create/",
|
||||
npc_views.CreateNPCView.as_view(),
|
||||
name="create_npc",
|
||||
),
|
||||
path(
|
||||
"npcs/<int:pk>/",
|
||||
npc_views.NPCDetailView.as_view(),
|
||||
name="npc_detail",
|
||||
),
|
||||
path(
|
||||
"npcs/<int:pk>/update/",
|
||||
npc_views.NPCUpdateView.as_view(),
|
||||
name="npc_update",
|
||||
),
|
||||
path(
|
||||
"npcs/<int:pk>/delete/",
|
||||
npc_views.NPCDeleteView.as_view(),
|
||||
name="npc_delete",
|
||||
),
|
||||
]
|
||||
|
|
|
@ -5,7 +5,7 @@ from django.views.generic.edit import CreateView
|
|||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.auth.forms import UserCreationForm
|
||||
from guild.models import Adventure, Character, Player, Reward
|
||||
from guild.models import NPC, Adventure, Character, Player, Reward
|
||||
|
||||
|
||||
# Create your views here.
|
||||
|
@ -23,6 +23,7 @@ class HomeView(LoginRequiredMixin, TemplateView):
|
|||
context["adventures"] = advs
|
||||
context["players"] = Player.objects.all()
|
||||
context["characters"] = Character.objects.all()
|
||||
context["npcs"] = NPC.objects.all()
|
||||
|
||||
context["rewards"] = Reward.objects.filter(character=None).order_by(
|
||||
"-playsession__date"
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
from django.views.generic import TemplateView, ListView, DetailView
|
||||
from django.views.generic.edit import CreateView, UpdateView, DeleteView
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from guild.models import NPC
|
||||
|
||||
|
||||
class NPCListView(LoginRequiredMixin, ListView):
|
||||
model = NPC
|
||||
context_object_name = "NPCs"
|
||||
|
||||
|
||||
class CreateNPCView(LoginRequiredMixin, CreateView):
|
||||
model = NPC
|
||||
fields = ["name", "picture", "description"]
|
||||
|
||||
|
||||
class NPCDetailView(LoginRequiredMixin, DetailView):
|
||||
model = NPC
|
||||
|
||||
|
||||
class NPCUpdateView(LoginRequiredMixin, UpdateView):
|
||||
model = NPC
|
||||
fields = ["name", "picture", "description"]
|
||||
|
||||
|
||||
class NPCDeleteView(LoginRequiredMixin, DeleteView):
|
||||
model = NPC
|
||||
success_url = "/"
|
Loading…
Reference in New Issue