Как я могу поместить список целых чисел (выбор битов) в базу данных в django
Я пытаюсь получить список вариантов дней недели в PositiveSmallIntegerField
в Django.
Я нашел очень похожий вопрос от 2011 года, Представление поля multi-select для дней недели в модели Django
Я попробовал подход с классом BitChoices, и сам класс вроде бы работает. Однако я не могу поместить список, возвращаемый классом, в базу данных, поскольку он каким-то образом должен быть суммой этого списка. Но как мне этого добиться? Что я упускаю?
Вот что я имею на данный момент (оговорка: возможно, несколько строк являются лишними для этого примера, я пытался сократить их до минимума):
models.py
from django.db import models
from django.conf import settings
from django.contrib.auth.models import User
from django.utils.translation import gettext_lazy as _
from datetime import date
class BitChoices(object):
def __init__(self, choices):
self._choices = []
self._lookup = {}
for index, (key, val) in enumerate(choices):
index = 2**index
self._choices.append((index, val))
self._lookup[key] = index
def __iter__(self):
return iter(self._choices)
def __len__(self):
return len(self._choices)
def __getattr__(self, attr):
try:
return self._lookup[attr]
except KeyError:
raise AttributeError(attr)
def get_selected_keys(self, selection):
""" Return a list of keys for the given selection """
return [ k for k,b in self._lookup.items() if b & selection]
def get_selected_values(self, selection):
""" Return a list of values for the given selection """
return [ v for b,v in self._choices if b & selection]
weekday_options = BitChoices(
(('nev', _('never')),
('mon', _('Monday')),
('tue', _('Tuesday')),
('wed', _('Wednesday')),
('thu', _('Thursday')),
('fri', _('Friday')),
('sat', _('Saturday')),
('sun', _('Sunday')),
('onh', _('on holidays')),
('bfh', _('before a holiday')))
)
class Directive(models.Model):
weekdays = models.PositiveSmallIntegerField(choices=weekday_options, default='')
def __str__(self):
return f'Eintrag {self.title}'
def save(self):
super().save()
forms.py
from django import forms
from django_select2 import forms as s2forms
from django.db import models
from . import models
from django.utils.translation import gettext_lazy as _
class DirectiveForm(forms.ModelForm):
class Meta:
model = models.Directive
fields = [
'weekdays'
]
labels = {
'weekdays': _('Weekdays')
}
widgets = {
'weekdays': s2forms.Select2MultipleWidget(),
}
views.py
from django.views import generic
from django.shortcuts import render, redirect
from django.contrib import messages
from .forms import DirectiveForm
from . import forms, models
def new_directive(request):
if request.method == 'POST':
d_form = DirectiveForm(request.POST)
if d_form.is_valid():
d_form.save()
entryTitle = d_form.cleaned_data.get('title')
messages.success(request, f'Neuer Eintrag mit Titel {entryTitle} wurde generiert.')
return redirect('blog-home')
else:
d_form = DirectiveForm()
return render(request, 'itinerary/new.html', {'d_form': d_form})
template:
{% load crispy_forms_tags %}
{% load i18n %}
{% load bootstrap4 %} {# import bootstrap4/bootstrap3 #}
{% bootstrap_css %} {# Embed Bootstrap CSS #}
{% bootstrap_javascript jquery='full' %} {# Embed Bootstrap JS+jQuery #}
{% block content %}
<div class="content-section">
<form method="POST" >
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">{% translate 'New Entry' %}</legend>
{{ d_form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info type="submit">{% translate 'submit' %}</button>
</div>
</form>
{{ d_form.media }}
</div>
{% endblock content %}
Теперь, например, если я отправляю форму с вариантами среда и пятница, я получаю ошибку (вольный перевод с немецкого):
Please make a valid selection. ['8', '32'] is invalid.
Я бы ожидал сохранить значение 40
в базу данных. Но как - или, скорее: где подвести итог? И очевидный последующий вопрос: так же ли прост обратный процесс?
Для контекста: общая картина такова: я хочу создать приложение, которое будет обрабатывать ежедневные дела на работе. Некоторые из них должны выполняться ежедневно, другие - только в отдельные дни недели.