Add basic user management forms and views.

This commit is contained in:
Christopher Charbonneau Wells 2017-12-10 21:36:25 -05:00
parent 2659063e40
commit e234c1cfd2
7 changed files with 190 additions and 11 deletions

View File

@ -2,12 +2,24 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from django import forms from django import forms
from django.contrib.auth.forms import PasswordChangeForm from django.contrib.auth.forms import PasswordChangeForm, UserCreationForm
from django.contrib.auth.models import User from django.contrib.auth.models import User
from .models import Settings from .models import Settings
class UserAddForm(UserCreationForm):
class Meta:
model = User
fields = ['username', 'first_name', 'last_name', 'email']
class UserUpdateForm(forms.ModelForm):
class Meta:
model = User
fields = ['username', 'first_name', 'last_name', 'email']
class UserForm(forms.ModelForm): class UserForm(forms.ModelForm):
class Meta: class Meta:
model = User model = User

View File

@ -184,6 +184,9 @@
<a href="{% url 'api:api-root' %}" <a href="{% url 'api:api-root' %}"
class="dropdown-item" class="dropdown-item"
target="_blank">API Browser</a> target="_blank">API Browser</a>
{% if perms.admin.add_user %}
<a href="{% url 'babybuddy:user-list' %}" class="dropdown-item">Users</a>
{% endif %}
{% if request.user.is_staff %} {% if request.user.is_staff %}
<a href="{% url 'admin:index' %}" <a href="{% url 'admin:index' %}"
class="dropdown-item" class="dropdown-item"

View File

@ -0,0 +1,19 @@
{% extends 'babybuddy/page.html' %}
{% load widget_tweaks %}
{% block title %}Delete User{% endblock %}
{% block breadcrumbs %}
<li class="breadcrumb-item"><a href="{% url 'babybuddy:user-list' %}">Users</a></li>
<li class="breadcrumb-item">{{ object }}</li>
<li class="breadcrumb-item active" aria-current="page">Delete</li>
{% endblock %}
{% block content %}
<form role="form" method="post">
{% csrf_token %}
<h1>Are you sure you want to delete <span class="text-info">{{ object }}</span>?</h1>
<input type="submit" value="Delete" class="btn btn-danger" />
<a href="{% url 'babybuddy:user-list' %}" class="btn btn-default">Cancel</a>
</form>
{% endblock %}

View File

@ -0,0 +1,28 @@
{% extends 'babybuddy/page.html' %}
{% block title %}
{% if object %}
{{ object }}
{% else %}
Create User
{% endif %}
{% endblock %}
{% block breadcrumbs %}
<li class="breadcrumb-item"><a href="{% url 'babybuddy:user-list' %}">Users</a></li>
{% if object %}
<li class="breadcrumb-item font-weight-bold">{{ object }}</li>
<li class="breadcrumb-item active" aria-current="page">Update</li>
{% else %}
<li class="breadcrumb-item active" aria-current="page">Create User</li>
{% endif %}
{% endblock %}
{% block content %}
{% if object %}
<h1>Update <span class="text-info">{{ object }}</span></h1>
{% else %}
<h1>Create User</h1>
{% endif %}
{% include 'babybuddy/form.html' %}
{% endblock %}

View File

@ -0,0 +1,65 @@
{% extends 'babybuddy/page.html' %}
{% load widget_tweaks static thumbnail %}
{% block title %}Users{% endblock %}
{% block breadcrumbs %}
<li class="breadcrumb-item active" aria-current="page">Users</li>
{% endblock %}
{% block content %}
<h1>Users</h1>
{% include 'babybuddy/filter.html' %}
<div class="table-responsive">
<table class="table table-striped table-hover user-list">
<thead class="thead-inverse">
<tr>
<th>User</th>
<th>First Name</th>
<th>Last Name</th>
<th>Email</th>
<th class="text-center">Actions</th>
</tr>
</thead>
<tbody>
{% for object in object_list %}
<tr>
<th scope="row">{{ object.username }}</th>
<td>{{ object.first_name }}</td>
<td>{{ object.last_name }}</td>
<td>{{ object.email }}</td>
<td class="text-center">
<div class="btn-group btn-group-sm" role="group" aria-label="Actions">
{% if perms.admin.change_user %}
<a href="{% url 'babybuddy:user-update' object.id %}" class="btn btn-warning">
<i class="icon icon-update" aria-hidden="true"></i>
</a>
{% endif %}
{% if perms.admin.delete_user %}
<a href="{% url 'babybuddy:user-delete' object.id %}" class="btn btn-danger">
<i class="icon icon-delete" aria-hidden="true"></i>
</a>
{% endif %}
</div>
</td>
</tr>
{% empty %}
<tr>
<th colspan="4">No users found.</th>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% include 'babybuddy/paginator.html' %}
{% if perms.admin.add_user %}
<a href="{% url 'babybuddy:user-add' %}" class="btn btn-sm btn-success">
<i class="icon icon-add" aria-hidden="true"></i> Create User
</a>
{% endif %}
{% endblock %}

View File

@ -18,6 +18,13 @@ app_patterns = [
url(r'^$', views.RootRouter.as_view(), name='root-router'), url(r'^$', views.RootRouter.as_view(), name='root-router'),
url(r'^welcome/$', views.Welcome.as_view(), name='welcome'), url(r'^welcome/$', views.Welcome.as_view(), name='welcome'),
url(r'^user/list/$', views.UserList.as_view(), name='user-list'),
url(r'^user/add/$', views.UserAdd.as_view(), name='user-add'),
url(r'^user/(?P<pk>[0-9]+)/$', views.UserUpdate.as_view(),
name='user-update'),
url(r'^user/(?P<pk>[0-9]+)/delete/$', views.UserDelete.as_view(),
name='user-delete'),
url(r'^user/password/$', views.UserPassword.as_view(), url(r'^user/password/$', views.UserPassword.as_view(),
name='user-password'), name='user-password'),
url(r'^user/reset-api-key/$', views.UserResetAPIKey.as_view(), url(r'^user/reset-api-key/$', views.UserResetAPIKey.as_view(),

View File

@ -4,15 +4,20 @@ from __future__ import unicode_literals
from django.contrib import messages from django.contrib import messages
from django.contrib.auth import update_session_auth_hash from django.contrib.auth import update_session_auth_hash
from django.contrib.auth.forms import PasswordChangeForm from django.contrib.auth.forms import PasswordChangeForm
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import (LoginRequiredMixin,
PermissionRequiredMixin)
from django.contrib.auth.models import User
from django.contrib.messages.views import SuccessMessageMixin
from django.shortcuts import redirect, render from django.shortcuts import redirect, render
from django.urls import reverse from django.urls import reverse, reverse_lazy
from django.views.generic import View from django.views.generic import View
from django.views.generic.base import TemplateView, RedirectView from django.views.generic.base import TemplateView, RedirectView
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from .forms import UserForm, UserPasswordForm, UserSettingsForm from django_filters.views import FilterView
from core.models import Child
from babybuddy import forms
from core import models
class RootRouter(LoginRequiredMixin, RedirectView): class RootRouter(LoginRequiredMixin, RedirectView):
@ -22,22 +27,62 @@ class RootRouter(LoginRequiredMixin, RedirectView):
more than one child is in the database. more than one child is in the database.
""" """
def get_redirect_url(self, *args, **kwargs): def get_redirect_url(self, *args, **kwargs):
children = Child.objects.count() children = models.Child.objects.count()
if children == 0: if children == 0:
self.url = reverse('babybuddy:welcome') self.url = reverse('babybuddy:welcome')
elif children == 1: elif children == 1:
self.url = reverse( self.url = reverse(
'dashboard:dashboard-child', args={Child.objects.first().slug}) 'dashboard:dashboard-child',
args={models.Child.objects.first().slug}
)
else: else:
self.url = reverse('dashboard:dashboard') self.url = reverse('dashboard:dashboard')
return super(RootRouter, self).get_redirect_url(self, *args, **kwargs) return super(RootRouter, self).get_redirect_url(self, *args, **kwargs)
class UserList(PermissionRequiredMixin, FilterView):
model = User
template_name = 'babybuddy/user_list.html'
permission_required = ('admin.add_user',)
paginate_by = 10
filter_fields = ('username', 'first_name', 'last_name', 'email')
class UserAdd(PermissionRequiredMixin, SuccessMessageMixin, CreateView):
model = User
template_name = 'babybuddy/user_form.html'
permission_required = ('admin.add_user',)
form_class = forms.UserAddForm
success_url = reverse_lazy('babybuddy:user-list')
success_message = 'User %(username)s added!'
class UserUpdate(PermissionRequiredMixin, SuccessMessageMixin, UpdateView):
model = User
template_name = 'babybuddy/user_form.html'
permission_required = ('admin.change_user',)
form_class = forms.UserUpdateForm
success_url = reverse_lazy('babybuddy:user-list')
success_message = 'User %(username)s updated.'
class UserDelete(PermissionRequiredMixin, DeleteView):
model = User
template_name = 'babybuddy/user_confirm_delete.html'
permission_required = ('admin.delete_user',)
success_url = reverse_lazy('babybuddy:user-list')
def delete(self, request, *args, **kwargs):
success_message = 'User {} deleted.'.format(self.get_object())
messages.success(request, success_message)
return super(UserDelete, self).delete(request, *args, **kwargs)
class UserPassword(LoginRequiredMixin, View): class UserPassword(LoginRequiredMixin, View):
""" """
Handles user password changes. Handles user password changes.
""" """
form_class = UserPasswordForm form_class = forms.UserPasswordForm
template_name = 'babybuddy/user_password_form.html' template_name = 'babybuddy/user_password_form.html'
def get(self, request): def get(self, request):
@ -69,8 +114,8 @@ class UserSettings(LoginRequiredMixin, View):
Handles both the User and Settings models. Handles both the User and Settings models.
Based on this SO answer: https://stackoverflow.com/a/45056835. Based on this SO answer: https://stackoverflow.com/a/45056835.
""" """
form_user_class = UserForm form_user_class = forms.UserForm
form_settings_class = UserSettingsForm form_settings_class = forms.UserSettingsForm
template_name = 'babybuddy/user_settings_form.html' template_name = 'babybuddy/user_settings_form.html'
def get(self, request): def get(self, request):