Added the user list in the Mia core application.

This commit is contained in:
依瑪貓 2020-08-09 20:22:37 +08:00
parent 062e3f5c93
commit 2a6d3ff4cb
6 changed files with 195 additions and 33 deletions

35
mia_core/converters.py Normal file
View File

@ -0,0 +1,35 @@
# The core application of the Mia project.
# by imacat <imacat@mail.imacat.idv.tw>, 2020/8/9
# Copyright (c) 2020 imacat.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""The URL converters.
"""
from .models import User
class UserConverter:
"""The path converter for the user accounts."""
regex = ".*"
def to_python(self, value):
try:
return User.objects.get(login_id=value)
except User.DoesNotExist:
raise ValueError
def to_url(self, value):
return value.login_id

View File

@ -7,8 +7,8 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: mia 1.0\n" "Project-Id-Version: mia 1.0\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-08-09 19:13+0800\n" "POT-Creation-Date: 2020-08-09 20:20+0800\n"
"PO-Revision-Date: 2020-08-07 00:01+0800\n" "PO-Revision-Date: 2020-08-09 20:21+0800\n"
"Last-Translator: imacat <imacat@mail.imacat.idv.tw>\n" "Last-Translator: imacat <imacat@mail.imacat.idv.tw>\n"
"Language-Team: Traditional Chinese <imacat@mail.imacat.idv.tw>\n" "Language-Team: Traditional Chinese <imacat@mail.imacat.idv.tw>\n"
"Language: Traditional Chinese\n" "Language: Traditional Chinese\n"
@ -115,36 +115,42 @@ msgstr "從:"
msgid "To:" msgid "To:"
msgstr "到:" msgstr "到:"
#: mia_core/templates/mia_core/user_list.html:29 #: mia_core/templates/mia_core/user_list.html:28
#: mia_core/templates/mia_core/user_list.html:42 msgid "Account Management"
msgctxt "Accounting" msgstr "帳號管理"
msgid "Accounts"
msgstr ""
#: mia_core/templates/mia_core/user_list.html:40 #: mia_core/templates/mia_core/user_list.html:36
msgid "New" msgid "New"
msgstr "" msgstr "新增"
#: mia_core/templates/mia_core/user_list.html:52 #: mia_core/templates/mia_core/user_list.html:44
msgid "Code" msgid "Login ID"
msgstr "" msgstr "帳號"
#: mia_core/templates/mia_core/user_list.html:53 #: mia_core/templates/mia_core/user_list.html:45
msgid "Title" msgid "Name"
msgstr "" msgstr "姓名"
#: mia_core/templates/mia_core/user_list.html:54 #: mia_core/templates/mia_core/user_list.html:46
#: mia_core/templates/mia_core/user_list.html:72 #: mia_core/templates/mia_core/user_list.html:68
msgid "View" msgid "View"
msgstr "" msgstr "查閱"
#: mia_core/templates/mia_core/user_list.html:65 #: mia_core/templates/mia_core/user_list.html:56
msgid "Parent Account In Use" msgid "Disabled"
msgstr "" msgstr "停用"
#: mia_core/templates/mia_core/user_list.html:80 #: mia_core/templates/mia_core/user_list.html:59
msgid "Deleted"
msgstr "已刪"
#: mia_core/templates/mia_core/user_list.html:62
msgid "Not In Use"
msgstr "未使用"
#: mia_core/templates/mia_core/user_list.html:76
msgid "There is currently no data." msgid "There is currently no data."
msgstr "" msgstr "目前沒有資料。"
#: mia_core/utils.py:343 #: mia_core/utils.py:343
msgctxt "Pagination|" msgctxt "Pagination|"

View File

@ -19,7 +19,7 @@
""" """
from dirtyfields import DirtyFieldsMixin from dirtyfields import DirtyFieldsMixin
from django.db import models from django.db import models, connection, OperationalError
from mia_core.utils import get_multi_lingual_attr, set_multi_lingual_attr from mia_core.utils import get_multi_lingual_attr, set_multi_lingual_attr
@ -116,3 +116,37 @@ class User(DirtyFieldsMixin, models.Model):
class Meta: class Meta:
db_table = "users" db_table = "users"
app_label = "mia_core" app_label = "mia_core"
def is_in_use(self):
"""Returns whether this user is in use.
Returns:
bool: True if this user is in use, or False otherwise.
"""
for table in connection.introspection.table_names():
if self._is_in_use_with(F"SELECT * FROM {table}"
" WHERE createdby=%s OR updatedby=%s"):
return True
if self._is_in_use_with(
F"SELECT * FROM {table}"
" WHERE created_by_id=%s OR updated_by_id=%s"):
return True
return False
def _is_in_use_with(self, sql):
"""Returns whether this user is in use with a specific SQL statement.
Args:
sql (str): The SQL query statement
Returns:
bool: True if this user is in use, or False otherwise.
"""
with connection.cursor() as cursor:
try:
cursor.execute(sql, [self.pk, self.pk])
except OperationalError:
return False
if cursor.fetchone() is None:
return False
return True

View File

@ -0,0 +1,79 @@
{% extends "base.html" %}
{% comment %}
The Mia Core Application
user_list.html: The template for the user list
Copyright (c) 2020 imacat.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Author: imacat@mail.imacat.idv.tw (imacat)
First written: 2020/8/9
{% endcomment %}
{% load static %}
{% load i18n %}
{% load mia_core %}
{% block settings %}
{% setvar "title" _("Account Management") %}
{% endblock %}
{% block content %}
<div class="btn-group btn-actions">
<a class="btn btn-primary" role="button" href="{% url "mia_core:users.create" %}">
<i class="fas fa-user-plus"></i>
{{ _("New")|force_escape }}
</a>
</div>
{% if user_list %}
<table id="users" class="table table-striped table-hover">
<thead>
<tr>
<th scope="col">{{ _("Login ID")|force_escape }}</th>
<th scope="col">{{ _("Name")|force_escape }}</th>
<th class="actions" scope="col">{{ _("View")|force_escape }}</th>
</tr>
</thead>
<tbody>
{% for user in user_list %}
<tr>
<td>{{ user.login_id }}</td>
<td>
{{ user.name }}
{% if user.is_disabled %}
<span class="badge badge-pill badge-secondary">{{ _("Disabled")|force_escape }}</span>
{% endif %}
{% if user.is_deleted %}
<span class="badge badge-pill badge-dark">{{ _("Deleted")|force_escape }}</span>
{% endif %}
{% if not user.is_in_use %}
<span class="badge badge-pill badge-info">{{ _("Not In Use")|force_escape }}</span>
{% endif %}
</td>
<td class="actions">
<a href="{% url "mia_core:users.detail" user %}" class="btn btn-info" role="button">
<i class="fas fa-eye"></i>
<span class="d-none d-sm-inline">{{ _("View")|force_escape }}</span>
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p>{{ _("There is currently no data.")|force_escape }}</p>
{% endif %}
{% endblock %}

View File

@ -18,26 +18,28 @@
"""The route settings of the Mia core application. """The route settings of the Mia core application.
""" """
from django.urls import path from django.urls import path, register_converter
from . import views from . import views, converters
register_converter(converters.UserConverter, "user")
app_name = "mia_core" app_name = "mia_core"
urlpatterns = [ urlpatterns = [
# TODO: To be done. # TODO: To be done.
path("users", views.todo, name="users"), path("users", views.UserListView.as_view(), name="users"),
# TODO: To be done. # TODO: To be done.
path("users/create", views.todo, name="users.create"), path("users/create", views.todo, name="users.create"),
# TODO: To be done. # TODO: To be done.
path("users/store", views.todo, name="users.store"), path("users/store", views.todo, name="users.store"),
# TODO: To be done. # TODO: To be done.
path("users/<str:login_id>", views.todo, name="users.detail"), path("users/<user:user>", views.todo, name="users.detail"),
# TODO: To be done. # TODO: To be done.
path("users/<str:login_id>/edit", views.todo, name="users.edit"), path("users/<user:user>/edit", views.todo, name="users.edit"),
# TODO: To be done. # TODO: To be done.
path("users/<str:login_id>/update", views.todo, name="users.update"), path("users/<user:user>/update", views.todo, name="users.update"),
# TODO: To be done. # TODO: To be done.
path("users/<str:login_id>/delete", views.todo, name="users.delete"), path("users/<user:user>/delete", views.todo, name="users.delete"),
# TODO: To be done. # TODO: To be done.
path("api/users/<str:login_id>/exists", views.todo, path("api/users/<str:login_id>/exists", views.todo,
name="api.users.exists"), name="api.users.exists"),

View File

@ -23,9 +23,10 @@ from django.contrib.auth import logout as logout_user
from django.contrib.messages.views import SuccessMessageMixin from django.contrib.messages.views import SuccessMessageMixin
from django.http import HttpResponse from django.http import HttpResponse
from django.shortcuts import redirect from django.shortcuts import redirect
from django.urls import reverse
from django.views.decorators.http import require_POST from django.views.decorators.http import require_POST
from django.views.generic import DeleteView as CoreDeleteView from django.views.generic import DeleteView as CoreDeleteView, ListView
from mia_core.models import User
class DeleteView(SuccessMessageMixin, CoreDeleteView): class DeleteView(SuccessMessageMixin, CoreDeleteView):
@ -54,6 +55,11 @@ def logout(request):
return redirect("home") return redirect("home")
class UserListView(ListView):
"""The view to list the users."""
queryset = User.objects.order_by("login_id")
# TODO: To be removed. # TODO: To be removed.
def todo(request, **kwargs): def todo(request, **kwargs):
"""A dummy placeholder view for the URL settings that are not """A dummy placeholder view for the URL settings that are not