Merge pull request #533 from SchrodingersGat/key-value-settings

Key value settings
This commit is contained in:
Oliver 2019-09-15 23:28:37 +10:00 committed by GitHub
commit 180df8f110
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 176 additions and 1 deletions

View File

@ -61,6 +61,7 @@ settings_urls = [
url(r'^user/?', SettingsView.as_view(template_name='InvenTree/settings/user.html'), name='settings-user'), url(r'^user/?', SettingsView.as_view(template_name='InvenTree/settings/user.html'), name='settings-user'),
url(r'^currency/?', SettingsView.as_view(template_name='InvenTree/settings/currency.html'), name='settings-currency'), url(r'^currency/?', SettingsView.as_view(template_name='InvenTree/settings/currency.html'), name='settings-currency'),
url(r'^part/?', SettingsView.as_view(template_name='InvenTree/settings/part.html'), name='settings-part'), url(r'^part/?', SettingsView.as_view(template_name='InvenTree/settings/part.html'), name='settings-part'),
url(r'^other/?', SettingsView.as_view(template_name='InvenTree/settings/other.html'), name='settings-other'),
# Catch any other urls # Catch any other urls
url(r'^.*$', SettingsView.as_view(template_name='InvenTree/settings/user.html'), name='settings'), url(r'^.*$', SettingsView.as_view(template_name='InvenTree/settings/user.html'), name='settings'),

View File

@ -16,6 +16,7 @@ from django.views.generic import UpdateView, CreateView
from django.views.generic.base import TemplateView from django.views.generic.base import TemplateView
from part.models import Part from part.models import Part
from common.models import InvenTreeSetting
from .forms import DeleteForm, EditUserForm, SetPasswordForm from .forms import DeleteForm, EditUserForm, SetPasswordForm
from .helpers import str2bool from .helpers import str2bool
@ -511,3 +512,11 @@ class SettingsView(TemplateView):
""" """
template_name = "InvenTree/settings.html" template_name = "InvenTree/settings.html"
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs).copy()
ctx['settings'] = InvenTreeSetting.objects.all().order_by('key')
return ctx

View File

@ -5,11 +5,17 @@ from django.contrib import admin
from import_export.admin import ImportExportModelAdmin from import_export.admin import ImportExportModelAdmin
from .models import Currency from .models import Currency, InvenTreeSetting
class CurrencyAdmin(ImportExportModelAdmin): class CurrencyAdmin(ImportExportModelAdmin):
list_display = ('symbol', 'suffix', 'description', 'value', 'base') list_display = ('symbol', 'suffix', 'description', 'value', 'base')
class SettingsAdmin(ImportExportModelAdmin):
list_display = ('key', 'value', 'description')
admin.site.register(Currency, CurrencyAdmin) admin.site.register(Currency, CurrencyAdmin)
admin.site.register(InvenTreeSetting, SettingsAdmin)

View File

@ -0,0 +1,21 @@
# Generated by Django 2.2.5 on 2019-09-15 12:44
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('common', '0003_auto_20190902_2310'),
]
operations = [
migrations.CreateModel(
name='InvenTreeSetting',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('key', models.CharField(help_text='Settings key', max_length=50, unique=True)),
('value', models.CharField(blank=True, help_text='Settings value', max_length=200)),
],
),
]

View File

@ -0,0 +1,23 @@
# Generated by Django 2.2.5 on 2019-09-15 12:56
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('common', '0004_inventreesetting'),
]
operations = [
migrations.AddField(
model_name='inventreesetting',
name='description',
field=models.CharField(blank=True, help_text='Settings description', max_length=200),
),
migrations.AlterField(
model_name='inventreesetting',
name='key',
field=models.CharField(help_text='Settings key (must be unique - case insensitive', max_length=50, unique=True),
),
]

View File

@ -9,6 +9,79 @@ from __future__ import unicode_literals
from django.db import models from django.db import models
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.core.validators import MinValueValidator, MaxValueValidator from django.core.validators import MinValueValidator, MaxValueValidator
from django.core.exceptions import ValidationError
class InvenTreeSetting(models.Model):
"""
An InvenTreeSetting object is a key:value pair used for storing
single values (e.g. one-off settings values).
The class provides a way of retrieving the value for a particular key,
even if that key does not exist.
"""
@classmethod
def get_setting(cls, key, backup_value=None):
"""
Get the value of a particular setting.
If it does not exist, return the backup value (default = None)
"""
try:
setting = InvenTreeSetting.objects.get(key__iexact=key)
return setting.value
except InvenTreeSetting.DoesNotExist:
return backup_value
@classmethod
def set_setting(cls, key, value, user, create=True):
"""
Set the value of a particular setting.
If it does not exist, option to create it.
Args:
key: settings key
value: New value
user: User object (must be staff member to update a core setting)
create: If True, create a new setting if the specified key does not exist.
"""
if not user.is_staff:
return
try:
setting = InvenTreeSetting.objects.get(key__iexact=key)
except InvenTreeSetting.DoesNotExist:
if create:
setting = InvenTreeSetting(key=key)
else:
return
setting.value = value
setting.save()
key = models.CharField(max_length=50, blank=False, unique=True, help_text=_('Settings key (must be unique - case insensitive'))
value = models.CharField(max_length=200, blank=True, unique=False, help_text=_('Settings value'))
description = models.CharField(max_length=200, blank=True, unique=False, help_text=_('Settings description'))
def validate_unique(self, exclude=None):
""" Ensure that the key:value pair is unique.
In addition to the base validators, this ensures that the 'key'
is unique, using a case-insensitive comparison.
"""
super().validate_unique(exclude)
try:
setting = InvenTreeSetting.objects.exclude(id=self.id).filter(key__iexact=self.key)
if setting.exists():
raise ValidationError({'key': _('Key string must be unique')})
except InvenTreeSetting.DoesNotExist:
pass
class Currency(models.Model): class Currency(models.Model):

View File

@ -0,0 +1,37 @@
{% extends "InvenTree/settings/settings.html" %}
{% block tabs %}
{% include "InvenTree/settings/tabs.html" with tab='other' %}
{% endblock %}
{% block settings %}
<h4>InvenTree Settings</h4>
<table class='table table-striped table-condensed' id='other-table'>
<thead>
<tr>
<th>Setting</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
{% for setting in settings %}
<tr>
<td>{{ setting.key }}</td>
<td>{{ setting.value }}</td>
<td>{{ setting.description }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
{% block js_ready %}
{{ block.super }}
$("#other-table").bootstrapTable();
{% endblock %}

View File

@ -8,4 +8,9 @@
<li{% ifequal tab 'part' %} class='active'{% endifequal %}> <li{% ifequal tab 'part' %} class='active'{% endifequal %}>
<a href="{% url 'settings-part' %}"><span class='glyphicon glyphicon-briefcase'></span> Part</a> <a href="{% url 'settings-part' %}"><span class='glyphicon glyphicon-briefcase'></span> Part</a>
</li> </li>
{% if user.is_staff %}
<li{% ifequal tab 'other' %} class='active'{% endifequal %}>
<a href="{% url 'settings-other' %}"><span class='glyphicon glyphicon-cog'></span>Other</a>
</li>
{% endif %}
</ul> </ul>