feat(people): Add view to create Person

User profile nav directs to create new Person for user
if there is not one currently associated

resolves issue #4
This commit is contained in:
James Graham
2020-02-19 08:17:39 +00:00
parent e530ddc8ec
commit d57c4769ae
8 changed files with 140 additions and 6 deletions

View File

@@ -60,6 +60,10 @@
<div class="navbar-collapse collapse" id="navbarCollapse"> <div class="navbar-collapse collapse" id="navbarCollapse">
<ul class="navbar-nav mt-2 mt-lg-0"> <ul class="navbar-nav mt-2 mt-lg-0">
<li class="nav-item">
<a href="{% url 'people:person.list' %}" class="nav-link">People</a>
</li>
{% if request.user.is_superuser %} {% if request.user.is_superuser %}
<li class="nav-item"> <li class="nav-item">
<a href="{% url 'admin:index' %}" class="nav-link">Admin</a> <a href="{% url 'admin:index' %}" class="nav-link">Admin</a>
@@ -71,19 +75,20 @@
{% if request.user.is_authenticated %} {% if request.user.is_authenticated %}
<li class="nav-item"> <li class="nav-item">
{% if request.user.person %} {% if request.user.person %}
<a href="{{ request.user.get_absolute_url }}" class="nav-link"> <a href="{% url 'people:person.profile' %}" class="nav-link">
<i class="fas fa-user-circle"></i> <i class="fas fa-user-circle"></i>
{{ request.user }} {{ request.user }}
</a> </a>
{% else %} {% else %}
<span class="navbar-text"> <a href="{% url 'people:person.create' %}?user" class="nav-link">
<i class="fas fa-user-circle"></i> <i class="fas fa-user-circle"></i>
{{ request.user }} {{ request.user }}
</span> </a>
{% endif %} {% endif %}
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="{% url 'logout' %}" class="nav-link"> <a href="{% url 'logout' %}" class="nav-link">
<i class="fas fa-sign-out-alt"></i> <i class="fas fa-sign-out-alt"></i>

19
people/forms.py Normal file
View File

@@ -0,0 +1,19 @@
"""
Forms for creating / updating models belonging to the 'people' app.
"""
from django import forms
from . import models
class PersonForm(forms.ModelForm):
"""
Form for creating / updating an instance of :class:`Person`.
"""
class Meta:
model = models.Person
fields = [
'name',
'core_member',
]

View File

@@ -0,0 +1,20 @@
# Generated by Django 2.2.10 on 2020-02-18 15:44
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('people', '0003_fix_people_plural'),
]
operations = [
migrations.AddField(
model_name='person',
name='user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='person', to=settings.AUTH_USER_MODEL),
),
]

View File

@@ -0,0 +1,20 @@
# Generated by Django 2.2.10 on 2020-02-19 08:09
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('people', '0004_person_user'),
]
operations = [
migrations.AlterField(
model_name='person',
name='user',
field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='person', to=settings.AUTH_USER_MODEL),
),
]

View File

@@ -1,5 +1,7 @@
from django.conf import settings
from django.contrib.auth.models import AbstractUser from django.contrib.auth.models import AbstractUser
from django.db import models from django.db import models
from django.urls import reverse
class User(AbstractUser): class User(AbstractUser):
@@ -12,9 +14,14 @@ class Person(models.Model):
""" """
A person may be a member of the BRECcIA core team or an external stakeholder. A person may be a member of the BRECcIA core team or an external stakeholder.
""" """
class Meta: class Meta:
verbose_name_plural = 'people' verbose_name_plural = 'people'
#: User account belonging to this person
user = models.OneToOneField(settings.AUTH_USER_MODEL,
related_name='person',
on_delete=models.CASCADE,
blank=True, null=True)
#: Name of the person #: Name of the person
name = models.CharField(max_length=255, name = models.CharField(max_length=255,
@@ -35,6 +42,9 @@ class Person(models.Model):
return self.relationships_as_source.all().union( return self.relationships_as_source.all().union(
self.relationships_as_target.all() self.relationships_as_target.all()
) )
def get_absolute_url(self):
return reverse('people:person.detail', kwargs={'pk': self.pk})
def __str__(self) -> str: def __str__(self) -> str:
return self.name return self.name

View File

@@ -0,0 +1,27 @@
{% extends 'base.html' %}
{% block content %}
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="{% url 'people:person.list' %}">People</a>
</li>
<li class="breadcrumb-item active" aria-current="page">Create</li>
</ol>
</nav>
<hr>
<form class="form"
method="POST">
{% csrf_token %}
{% load bootstrap4 %}
{% bootstrap_form form %}
{% buttons %}
<button class="btn btn-success" type="submit">Submit</button>
{% endbuttons %}
</form>
{% endblock %}

View File

@@ -10,6 +10,10 @@ urlpatterns = [
views.ProfileView.as_view(), views.ProfileView.as_view(),
name='person.profile'), name='person.profile'),
path('people/create',
views.PersonCreateView.as_view(),
name='person.create'),
path('people', path('people',
views.PersonListView.as_view(), views.PersonListView.as_view(),
name='person.list'), name='person.list'),

View File

@@ -2,9 +2,26 @@
Views for displaying or manipulating models in the 'people' app. Views for displaying or manipulating models in the 'people' app.
""" """
from django.views.generic import DetailView, ListView from django.views.generic import CreateView, DetailView, ListView
from . import models from . import forms, models
class PersonCreateView(CreateView):
"""
View to create a new instance of :class:`Person`.
If 'user' is passed as a URL parameter - link the new person to the current user.
"""
model = models.Person
template_name = 'people/person/create.html'
form_class = forms.PersonForm
def form_valid(self, form):
if 'user' in self.request.GET:
form.instance.user = self.request.user
return super().form_valid(form)
class PersonListView(ListView): class PersonListView(ListView):
@@ -22,6 +39,18 @@ class ProfileView(DetailView):
model = models.Person model = models.Person
template_name = 'people/person/detail.html' template_name = 'people/person/detail.html'
def get_object(self, queryset=None) -> models.Person:
"""
Get the :class:`Person` object to be represented by this page.
If not determined from url get current user.
"""
try:
return super().get_object(queryset)
except AttributeError:
return self.request.user.person
class RelationshipDetailView(DetailView): class RelationshipDetailView(DetailView):
""" """