added migration status to system page

This commit is contained in:
vabene1111 2023-12-16 14:03:32 +01:00
parent dd3e91e10d
commit 0fed6b9fb3
5 changed files with 127 additions and 55 deletions

View File

@ -3,6 +3,7 @@
<words> <words>
<w>pinia</w> <w>pinia</w>
<w>selfhosted</w> <w>selfhosted</w>
<w>unapplied</w>
</words> </words>
</dictionary> </dictionary>
</component> </component>

View File

@ -1,5 +1,6 @@
<component name="InspectionProjectProfileManager"> <component name="InspectionProjectProfileManager">
<settings> <settings>
<option name="PROJECT_PROFILE" value="Default" />
<option name="USE_PROJECT_PROFILE" value="false" /> <option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" /> <version value="1.0" />
</settings> </settings>

View File

@ -83,51 +83,94 @@
{% trans 'Everything is fine!' %} {% trans 'Everything is fine!' %}
{% endif %} {% endif %}
<h4 class="mt-3">{% trans 'Database' %} <h4 class="mt-3">{% trans 'Database' %}
<span class="badge badge-{{postgres_status}}"> <span class="badge badge-{{ postgres_status }}">
{% if postgres_status == 'warning' %} {% if postgres_status == 'warning' %}
{% trans 'Info' %} {% trans 'Info' %}
{% elif postgres_status == 'danger'%} {% elif postgres_status == 'danger' %}
{% trans 'Warning' %} {% trans 'Warning' %}
{% else %} {% else %}
{% trans 'Ok' %} {% trans 'Ok' %}
{% endif %} {% endif %}
</span> </span>
</h4> </h4>
{{postgres_message}} {{ postgres_message }}
{# <h4 class="mt-3">#} <h4 class="mt-3">{% trans 'Migrations' %}
{# {% trans 'Orphaned Files' %}#} <span
{##} class="badge badge-{% if missing_migration %}danger{% else %}success{% endif %}">{% if missing_migration %}
{# <span class="badge badge-{% if orphans|length == 0 %}success{% elif orphans|length <= 25 %}warning{% else %}danger{% endif %}">#} {% trans 'Warning' %}{% else %}{% trans 'Ok' %}{% endif %}</span></h4>
{# {% if orphans|length == 0 %}{% trans 'Success' %}#}
{# {% elif orphans|length <= 25 %}{% trans 'Warning' %}#}
{# {% else %}{% trans 'Danger' %}#}
{# {% endif %}#}
{# </span>#}
{# </h4>#}
{% if orphans|length == 0 %} <p>
{% trans 'Everything is fine!' %} {% blocktrans %}
{% else %} Migrations should never fail!
{% blocktrans with orphan_count=orphans|length %} Failed migrations will likely cause major parts of the app to not function correctly.
There are currently {{ orphan_count }} orphaned files. If a migration fails make sure you are on the latest version and if so please post the migration log and the overview below in a GitHub issue.
{% endblocktrans %} {% endblocktrans %}
<br> </p>
<button id="toggle-button" class="btn btn-info btn-sm" onclick="toggleOrphans()">{% trans 'Show' %}</button>
<button class="btn btn-info btn-sm" onclick="deleteOrphans()">{% trans 'Delete' %}</button> <table class="table mt-3">
{% endif %} <thead>
<textarea id="orphans-list" style="display:none;" class="form-control" rows="20"> <tr>
{% for orphan in orphans %}{{ orphan }} <th>App</th>
{% endfor %} <th class="text-right">{% trans 'Migrations' %}</th>
</textarea> </tr>
</thead>
{% for key,value in migration_info.items %}
<tr>
<td>{{ value.app }}</td>
<td class="text-right">
<span class="badge badge-{% if value.unapplied_migrations|length > 0 %}danger{% else %}success{% endif %}">
{{ value.applied_migrations|length }} / {{ value.total }}
</span>
</td>
</tr>
{% for u in value.unapplied_migrations %}
<tr>
<td>
{{ u }}
</td>
<td></td>
</tr>
{% endfor %}
{% endfor %}
</table>
{# <h4 class="mt-3">#}
{# {% trans 'Orphaned Files' %}#}
{##}
{# <span class="badge badge-{% if orphans|length == 0 %}success{% elif orphans|length <= 25 %}warning{% else %}danger{% endif %}">#}
{# {% if orphans|length == 0 %}{% trans 'Success' %}#}
{# {% elif orphans|length <= 25 %}{% trans 'Warning' %}#}
{# {% else %}{% trans 'Danger' %}#}
{# {% endif %}#}
{# </span>#}
{# </h4>#}
{# {% if orphans|length == 0 %}#}
{# {% trans 'Everything is fine!' %}#}
{# {% else %}#}
{# {% blocktrans with orphan_count=orphans|length %}#}
{# There are currently {{ orphan_count }} orphaned files.#}
{# {% endblocktrans %}#}
{# <br>#}
{# <button id="toggle-button" class="btn btn-info btn-sm" onclick="toggleOrphans()">{% trans 'Show' %}</button>#}
{# <button class="btn btn-info btn-sm" onclick="deleteOrphans()">{% trans 'Delete' %}</button>#}
{# {% endif %}#}
{# <textarea id="orphans-list" style="display:none;" class="form-control" rows="20">#}
{#{% for orphan in orphans %}{{ orphan }}#}
{#{% endfor %}#}
{# </textarea>#}
<h4 class="mt-3">Debug</h4> <h4 class="mt-3">Debug</h4>
<textarea class="form-control" rows="20"> <textarea class="form-control" rows="20">
Gunicorn Media: {{ gunicorn_media }} Gunicorn Media: {{ gunicorn_media }}
Sqlite: {% if postgres %} {% trans 'False' %} {% else %} {% trans 'True' %} {% endif %} Sqlite: {% if postgres %} {% trans 'False' %} {% else %} {% trans 'True' %} {% endif %}
{% if postgres %}PostgreSQL: {{postgres_version}} {% endif %} {% if postgres %}PostgreSQL: {{ postgres_version }} {% endif %}
Debug: {{ debug }} Debug: {{ debug }}
{% for key,value in request.META.items %}{% if key in 'SERVER_PORT,REMOTE_HOST,REMOTE_ADDR,SERVER_PROTOCOL' %}{{ key }}:{{ value }} {% for key,value in request.META.items %}{% if key in 'SERVER_PORT,REMOTE_HOST,REMOTE_ADDR,SERVER_PROTOCOL' %}{{ key }}:{{ value }}
{% endif %}{% endfor %} {% endif %}{% endfor %}
@ -142,26 +185,27 @@ Debug: {{ debug }}
{% csrf_token %} {% csrf_token %}
<input type="hidden" name="delete_orphans" value="false"> <input type="hidden" name="delete_orphans" value="false">
</form> </form>
{% block script %} {% block script %}
<script> <script>
function toggleOrphans() { function toggleOrphans() {
var orphansList = document.getElementById('orphans-list'); var orphansList = document.getElementById('orphans-list');
var button = document.getElementById('toggle-button'); var button = document.getElementById('toggle-button');
if (orphansList.style.display === 'none') { if (orphansList.style.display === 'none') {
orphansList.style.display = 'block'; orphansList.style.display = 'block';
button.innerText = "{% trans 'Hide' %}"; button.innerText = "{% trans 'Hide' %}";
} else { } else {
orphansList.style.display = 'none'; orphansList.style.display = 'none';
button.innerText = "{% trans 'Show' %}"; button.innerText = "{% trans 'Show' %}";
} }
} }
function deleteOrphans() {
document.getElementById('delete-form').delete_orphans.value = 'true'; function deleteOrphans() {
document.getElementById('delete-form').submit(); document.getElementById('delete-form').delete_orphans.value = 'true';
} document.getElementById('delete-form').submit();
</script> }
{% endblock script %} </script>
{% endblock script %}
{% endblock %} {% endblock %}

View File

@ -1,7 +1,9 @@
import os import os
import re import re
from datetime import datetime from datetime import datetime
from io import StringIO
from uuid import UUID from uuid import UUID
import subprocess
from django.apps import apps from django.apps import apps
from django.conf import settings from django.conf import settings
@ -10,6 +12,7 @@ from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import Group from django.contrib.auth.models import Group
from django.contrib.auth.password_validation import validate_password from django.contrib.auth.password_validation import validate_password
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.core.management import call_command
from django.db import models from django.db import models
from django.http import HttpResponseRedirect from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404, redirect, render from django.shortcuts import get_object_or_404, redirect, render
@ -27,7 +30,7 @@ from cookbook.models import (Comment, CookLog, InviteLink, SearchFields, SearchP
ShareLink, Space, UserSpace, ViewLog) ShareLink, Space, UserSpace, ViewLog)
from cookbook.tables import CookLogTable, ViewLogTable from cookbook.tables import CookLogTable, ViewLogTable
from cookbook.version_info import VERSION_INFO from cookbook.version_info import VERSION_INFO
from recipes.settings import PLUGINS from recipes.settings import PLUGINS, BASE_DIR
def index(request): def index(request):
@ -228,10 +231,10 @@ def shopping_settings(request):
if not sp: if not sp:
sp = SearchPreferenceForm(user=request.user) sp = SearchPreferenceForm(user=request.user)
fields_searched = ( fields_searched = (
len(search_form.cleaned_data['icontains']) len(search_form.cleaned_data['icontains'])
+ len(search_form.cleaned_data['istartswith']) + len(search_form.cleaned_data['istartswith'])
+ len(search_form.cleaned_data['trigram']) + len(search_form.cleaned_data['trigram'])
+ len(search_form.cleaned_data['fulltext']) + len(search_form.cleaned_data['fulltext'])
) )
if search_form.cleaned_data['preset'] == 'fuzzy': if search_form.cleaned_data['preset'] == 'fuzzy':
sp.search = SearchPreference.SIMPLE sp.search = SearchPreference.SIMPLE
@ -348,6 +351,26 @@ def system(request):
else: else:
orphans = get_orphan_files() orphans = get_orphan_files()
out = StringIO()
call_command('showmigrations', stdout=out)
missing_migration = False
migration_info = {}
current_app = None
for row in out.getvalue().splitlines():
if '[ ]' in row and current_app:
migration_info[current_app]['unapplied_migrations'].append(row.replace('[ ]', ''))
missing_migration = True
elif '[X]' in row and current_app:
migration_info[current_app]['applied_migrations'].append(row.replace('[x]', ''))
elif '(no migrations)' in row and current_app:
pass
else:
current_app = row
migration_info[current_app] = {'app': current_app, 'unapplied_migrations': [], 'applied_migrations': [], 'total': 0}
for key in migration_info.keys():
migration_info[key]['total'] = len(migration_info[key]['unapplied_migrations']) + len(migration_info[key]['applied_migrations'])
return render(request, 'system.html', { return render(request, 'system.html', {
'gunicorn_media': settings.GUNICORN_MEDIA, 'gunicorn_media': settings.GUNICORN_MEDIA,
'debug': settings.DEBUG, 'debug': settings.DEBUG,
@ -358,7 +381,9 @@ def system(request):
'version_info': VERSION_INFO, 'version_info': VERSION_INFO,
'plugins': PLUGINS, 'plugins': PLUGINS,
'secret_key': secret_key, 'secret_key': secret_key,
'orphans': orphans 'orphans': orphans,
'migration_info': migration_info,
'missing_migration': missing_migration,
}) })
@ -514,6 +539,7 @@ def get_orphan_files(delete_orphans=False):
# Check each image file against model image fields # Check each image file against model image fields
return [img for img in image_files if img[0] not in image_paths] return [img for img in image_files if img[0] not in image_paths]
orphans = find_orphans() orphans = find_orphans()
if delete_orphans: if delete_orphans:
for f in [img[1] for img in orphans]: for f in [img[1] for img in orphans]:

View File

@ -9,7 +9,7 @@ django-tables2==2.5.3
djangorestframework==3.14.0 djangorestframework==3.14.0
drf-writable-nested==0.7.0 drf-writable-nested==0.7.0
django-oauth-toolkit==2.3.0 django-oauth-toolkit==2.3.0
django-debug-toolbar==3.8.1 django-debug-toolbar==4.2.0
bleach==6.0.0 bleach==6.0.0
gunicorn==20.1.0 gunicorn==20.1.0
lxml==4.9.3 lxml==4.9.3