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 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 .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 Meta:
model = User

View File

@ -184,6 +184,9 @@
<a href="{% url 'api:api-root' %}"
class="dropdown-item"
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 %}
<a href="{% url 'admin:index' %}"
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'^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(),
name='user-password'),
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.auth import update_session_auth_hash
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.urls import reverse
from django.urls import reverse, reverse_lazy
from django.views.generic import View
from django.views.generic.base import TemplateView, RedirectView
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from .forms import UserForm, UserPasswordForm, UserSettingsForm
from core.models import Child
from django_filters.views import FilterView
from babybuddy import forms
from core import models
class RootRouter(LoginRequiredMixin, RedirectView):
@ -22,22 +27,62 @@ class RootRouter(LoginRequiredMixin, RedirectView):
more than one child is in the database.
"""
def get_redirect_url(self, *args, **kwargs):
children = Child.objects.count()
children = models.Child.objects.count()
if children == 0:
self.url = reverse('babybuddy:welcome')
elif children == 1:
self.url = reverse(
'dashboard:dashboard-child', args={Child.objects.first().slug})
'dashboard:dashboard-child',
args={models.Child.objects.first().slug}
)
else:
self.url = reverse('dashboard:dashboard')
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):
"""
Handles user password changes.
"""
form_class = UserPasswordForm
form_class = forms.UserPasswordForm
template_name = 'babybuddy/user_password_form.html'
def get(self, request):
@ -69,8 +114,8 @@ class UserSettings(LoginRequiredMixin, View):
Handles both the User and Settings models.
Based on this SO answer: https://stackoverflow.com/a/45056835.
"""
form_user_class = UserForm
form_settings_class = UserSettingsForm
form_user_class = forms.UserForm
form_settings_class = forms.UserSettingsForm
template_name = 'babybuddy/user_settings_form.html'
def get(self, request):