Edit forms, views, template to improve/modify view. Edit urls to remove some path. Few changes in models.

This commit is contained in:
quark 2024-08-14 01:32:55 +02:00
parent 196df1e775
commit 6d7076b03e
9 changed files with 179 additions and 48 deletions

View File

@ -11,7 +11,7 @@ from note_kfet.inputs import Autocomplete, DateTimePickerInput
from note_kfet.middlewares import get_current_request from note_kfet.middlewares import get_current_request
from permission.backends import PermissionBackend from permission.backends import PermissionBackend
from .models import BasicFood, QRCode, TransformedFood from .models import BasicFood, QRCode, TransformedFood, Food
class AddIngredientForms(forms.ModelForm): class AddIngredientForms(forms.ModelForm):
@ -20,7 +20,7 @@ class AddIngredientForms(forms.ModelForm):
""" """
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.fields['ingredient'].queryset = self.fields['ingredient'].queryset.filter(is_ready=False) self.fields['ingredient'].queryset = self.fields['ingredient'].queryset.filter(is_ready=False, is_active=True, was_eaten=False)
class Meta: class Meta:
model = TransformedFood model = TransformedFood
@ -45,7 +45,7 @@ class BasicFoodForms(forms.ModelForm):
class Meta: class Meta:
model = BasicFood model = BasicFood
fields = ('name', 'owner', 'date_type', 'expiry_date', 'allergens') fields = ('name', 'owner', 'date_type', 'expiry_date', 'is_active', 'was_eaten', 'allergens',)
widgets = { widgets = {
"owner": Autocomplete( "owner": Autocomplete(
model=Club, model=Club,
@ -80,6 +80,8 @@ class TransformedFoodForms(forms.ModelForm):
self.fields['creation_date'].required = True self.fields['creation_date'].required = True
self.fields['creation_date'].initial = timezone.now self.fields['creation_date'].initial = timezone.now
self.fields['is_active'].initial = True self.fields['is_active'].initial = True
self.fields['is_ready'].initial = False
self.fields['was_eaten'].initial = False
# Some example # Some example
self.fields['name'].widget.attrs.update({"placeholder": _("lasagna")}) self.fields['name'].widget.attrs.update({"placeholder": _("lasagna")})
@ -89,7 +91,7 @@ class TransformedFoodForms(forms.ModelForm):
class Meta: class Meta:
model = TransformedFood model = TransformedFood
fields = ('name', 'creation_date', 'owner', 'is_active', 'shelf_life') fields = ('name', 'creation_date', 'owner', 'is_active', 'is_ready', 'was_eaten', 'shelf_life')
widgets = { widgets = {
"owner": Autocomplete( "owner": Autocomplete(
model=Club, model=Club,
@ -97,3 +99,13 @@ class TransformedFoodForms(forms.ModelForm):
), ),
'creation_date': DateTimePickerInput(), 'creation_date': DateTimePickerInput(),
} }
class FoodForms(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['was_eaten'].initial = True
class Meta:
model = Food
fields = ('was_eaten',)

View File

@ -0,0 +1,28 @@
# Generated by Django 2.2.28 on 2024-08-13 21:58
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('food', '0003_create_14_allergens_mandatory'),
]
operations = [
migrations.RemoveField(
model_name='transformedfood',
name='is_active',
),
migrations.AddField(
model_name='food',
name='is_active',
field=models.BooleanField(default=True, verbose_name='is active'),
),
migrations.AlterField(
model_name='qrcode',
name='food_container',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='QR_code', to='food.Food', verbose_name='food container'),
),
]

View File

@ -19,9 +19,9 @@ class QRCode(models.Model):
unique=True, unique=True,
) )
food_container = models.OneToOneField( food_container = models.ForeignKey(
'Food', 'Food',
on_delete=models.PROTECT, on_delete=models.CASCADE,
related_name='QR_code', related_name='QR_code',
verbose_name=_('food container'), verbose_name=_('food container'),
) )
@ -80,11 +80,21 @@ class Food(PolymorphicModel):
verbose_name=_('was eaten'), verbose_name=_('was eaten'),
) )
# is_ready != is_active : is_ready signifie que la nourriture est prête à être manger,
# is_active signifie que la nourriture n'est pas encore archivé
# il sert dans les cas où il est plus intéressant que de l'open soit conservé (confiture par ex)
is_ready = models.BooleanField( is_ready = models.BooleanField(
default=False, default=False,
verbose_name=_('is ready'), verbose_name=_('is ready'),
) )
is_active = models.BooleanField(
default=True,
verbose_name=_('is active'),
)
def __str__(self): def __str__(self):
return self.name return self.name
@ -160,11 +170,6 @@ class TransformedFood(Food):
verbose_name=_('transformed ingredient'), verbose_name=_('transformed ingredient'),
) )
is_active = models.BooleanField(
default=True,
verbose_name=_('is active'),
)
# Without microbiological analyzes, the storage time is 3 days # Without microbiological analyzes, the storage time is 3 days
shelf_life = models.DurationField( shelf_life = models.DurationField(
verbose_name=_("shelf life"), verbose_name=_("shelf life"),

View File

@ -7,7 +7,6 @@ SPDX-License-Identifier: GPL-3.0-or-later
{% block content %} {% block content %}
<div class="card bg-white mb-3"> <div class="card bg-white mb-3">
<h3 class="card-header text-center"> <h3 class="card-header text-center">
HTML not finished <br>
{{ title }} {{ title }}
</h3> </h3>
<div class="card-body" id="form"> <div class="card-body" id="form">

View File

@ -7,13 +7,12 @@ SPDX-License-Identifier: GPL-3.0-or-later
{% block content %} {% block content %}
<div class="card bg-white mb-3"> <div class="card bg-white mb-3">
<h3 class="card-header text-center"> <h3 class="card-header text-center">
HTML not finished <br>
{{ title }} {{ title }}
</h3> </h3>
<div class="card-body" id="form"> <div class="card-body" id="form">
<form method="post"> <form method="post">
{% csrf_token %} {% csrf_token %}
{{ form|crispy }} {{ form | crispy }}
<button class="btn btn-primary" type="submit">{% trans "Submit"%}</button> <button class="btn btn-primary" type="submit">{% trans "Submit"%}</button>
</form> </form>
</div> </div>

View File

@ -7,18 +7,28 @@ SPDX-License-Identifier: GPL-3.0-or-later
{% block content %} {% block content %}
<div class="card bg-white mb-3"> <div class="card bg-white mb-3">
<h3 class="card-header text-center"> <h3 class="card-header text-center">
HTML not finished <br> HTML finished <br>
{{ title }} {{ title }}
</h3> </h3>
<div class="card-body"> <div class="card-body">
<p>{% trans 'QR-code' %} : {{ qrcode.qr_code_number }}</p> <p>{% trans 'QR-code number' %} : {{ qrcode.qr_code_number }}</p>
<p>{% trans 'Name' %} : {{ qrcode.food_container.name }}</p> <p>{% trans 'Name' %} : {{ qrcode.food_container.name }}</p>
{% if qrcode.food_container.polymorphic_ctype.name == 'Basic food' %} <p>{% trans 'Owner' %} : {{ qrcode.food_container.owner }}</p>
<a href="{% url "food:basic_update" pk=qrcode.food_container.pk %}">{% trans 'Update' %}</a> <p>{% trans 'Expiry date' %} : {{ qrcode.food_container.expiry_date }}</p>
{% else %} {% if qrcode.food_container.polymorphic_ctype.model == 'basicfood' and can_update_basic %}
<a href="{% url "food:transformed_update" pk=qrcode.food_container.pk %}">{% trans 'Update' %}</a> <a class="btn btn-sm btn-warning" href="{% url "food:basic_update" pk=qrcode.food_container.pk %}" data-turbolinks="false">
{% trans 'Update' %}
</a>
{% elif can_update_transformed %}
<a class="btn btn-sm btn-warning" href="{% url "food:transformed_update" pk=qrcode.food_container.pk %}">
{% trans 'Update' %}
</a>
{% endif %} {% endif %}
<a href="{% url "food:add_ingredient" pk=qrcode.food_container.pk %}">{% trans 'Add the ingredient' %}</a> {% if can_add_ingredient %}
</div> <a class="btn btn-sm btn-success" href="{% url "food:add_ingredient" pk=qrcode.food_container.pk %}">
{% trans 'Add the ingredient' %}
</a>
{% endif %}
</div>
</div> </div>
{% endblock %} {% endblock %}

View File

@ -13,12 +13,9 @@ urlpatterns = [
path('detail/<int:pk>', views.FoodView.as_view(), name='food_view'), path('detail/<int:pk>', views.FoodView.as_view(), name='food_view'),
path('<int:slug>/create_qrcode', views.QRCodeCreateView.as_view(), name='qrcode_create'), path('<int:slug>/create_qrcode', views.QRCodeCreateView.as_view(), name='qrcode_create'),
path('create', views.FoodCreateView.as_view(), name='food_create'),
path('<int:slug>/create_qrcode/basic', views.QRCodeBasicFoodCreateView.as_view(), name='qrcode_basic_create'), path('<int:slug>/create_qrcode/basic', views.QRCodeBasicFoodCreateView.as_view(), name='qrcode_basic_create'),
path('create/transformed', views.TransformedFoodCreateView.as_view(), name='transformed_create'), path('create/transformed', views.TransformedFoodCreateView.as_view(), name='transformed_create'),
path('update/basic/<int:pk>', views.BasicFoodUpdateView.as_view(), name='basic_update'), path('update/basic/<int:pk>', views.BasicFoodUpdateView.as_view(), name='basic_update'),
path('update/transformed/<int:pk>', views.TransformedFoodUpdateView.as_view(), name='transformed_update'), path('update/transformed/<int:pk>', views.TransformedFoodUpdateView.as_view(), name='transformed_update'),
path('add/<int:pk>', views.AddIngredientView.as_view(), name='add_ingredient'), path('add/<int:pk>', views.AddIngredientView.as_view(), name='add_ingredient'),
] ]

View File

@ -10,12 +10,13 @@ from django.utils.translation import gettext_lazy as _
from django.utils import timezone from django.utils import timezone
from django.views.generic import DetailView, UpdateView, TemplateView from django.views.generic import DetailView, UpdateView, TemplateView
from django.views.generic.list import ListView from django.views.generic.list import ListView
from django.forms import HiddenInput
from permission.backends import PermissionBackend from permission.backends import PermissionBackend
from permission.views import ProtectQuerysetMixin, ProtectedCreateView from permission.views import ProtectQuerysetMixin, ProtectedCreateView
from member.models import Club from member.models import Club
from note_kfet.middlewares import get_current_request from note_kfet.middlewares import get_current_request
from .forms import AddIngredientForms, BasicFoodForms, QRCodeForms, TransformedFoodForms from .forms import AddIngredientForms, BasicFoodForms, QRCodeForms, TransformedFoodForms, FoodForms
from .models import BasicFood, Food, QRCode, TransformedFood from .models import BasicFood, Food, QRCode, TransformedFood
from .tables import TransformedFoodTable from .tables import TransformedFoodTable
@ -24,6 +25,7 @@ class AddIngredientView(ProtectQuerysetMixin, UpdateView):
""" """
A view to add an ingredient A view to add an ingredient
""" """
# TO DO : ajouter un champ fully_used dans le form et changer was_eaten en conséquence + mieux filtrer les plat dispo avec des perms
model = Food model = Food
template_name = 'food/add_ingredient_form.html' template_name = 'food/add_ingredient_form.html'
extra_context = {"title": _("Add the ingredient")} extra_context = {"title": _("Add the ingredient")}
@ -39,8 +41,9 @@ class AddIngredientView(ProtectQuerysetMixin, UpdateView):
form.instance.creater = self.request.user form.instance.creater = self.request.user
food = Food.objects.get(pk=self.kwargs['pk']) food = Food.objects.get(pk=self.kwargs['pk'])
add_ingredient_form = AddIngredientForms(data=self.request.POST) add_ingredient_form = AddIngredientForms(data=self.request.POST)
if not food.is_ready: food_form = FoodForms(data=self.request.POST)
form.add_error(None, _("The product isn't ready")) if food.is_ready:
form.add_error(None, _("The product is already prepared"))
return self.form_invalid(form) return self.form_invalid(form)
if not add_ingredient_form.is_valid(): if not add_ingredient_form.is_valid():
return self.form_invalid(form) return self.form_invalid(form)
@ -59,11 +62,11 @@ class AddIngredientView(ProtectQuerysetMixin, UpdateView):
class BasicFoodUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView): class BasicFoodUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
""" """
A view to add a basic food A view to update a basic food
""" """
model = BasicFood model = BasicFood
form_class = BasicFoodForms form_class = BasicFoodForms
template_name = 'food/basic_food_form.html' template_name = 'food/basicfood_form.html'
extra_context = {"title": _("Add a new aliment")} extra_context = {"title": _("Add a new aliment")}
@transaction.atomic @transaction.atomic
@ -81,6 +84,18 @@ class BasicFoodUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
self.object.refresh_from_db() self.object.refresh_from_db()
return reverse('food:food_view', kwargs={"pk": self.object.pk}) return reverse('food:food_view', kwargs={"pk": self.object.pk})
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
form = context['form']
# TO DO : Add perms here
if 1==0:
form.fields['is_active'].widget = HiddenInput()
if 1==0:
form.fields['was_eaten'].widget = HiddenInput()
form.fields['is_active'].help_text = _("Uncheck if the food doesn't exist anymore")
form.fields['was_eaten'].help_text = _("Check if the food has been entirely eaten")
return context
class FoodCreateView(ProtectQuerysetMixin, LoginRequiredMixin, TemplateView): class FoodCreateView(ProtectQuerysetMixin, LoginRequiredMixin, TemplateView):
""" """
@ -98,7 +113,6 @@ class FoodView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
extra_context = {"title": _("Details")} extra_context = {"title": _("Details")}
context_object_name = "food" context_object_name = "food"
class QRCodeBasicFoodCreateView(ProtectQuerysetMixin, ProtectedCreateView): class QRCodeBasicFoodCreateView(ProtectQuerysetMixin, ProtectedCreateView):
##################################################################### #####################################################################
# TO DO # TO DO
@ -110,7 +124,7 @@ class QRCodeBasicFoodCreateView(ProtectQuerysetMixin, ProtectedCreateView):
""" """
model = BasicFood model = BasicFood
form_class = BasicFoodForms form_class = BasicFoodForms
template_name = 'food/basic_food_form.html' template_name = 'food/basicfood_form.html'
extra_context = {"title": _("Add a new basic food with QRCode")} extra_context = {"title": _("Add a new basic food with QRCode")}
@transaction.atomic @transaction.atomic
@ -124,7 +138,9 @@ class QRCodeBasicFoodCreateView(ProtectQuerysetMixin, ProtectedCreateView):
basic_food = form.save(commit=False) basic_food = form.save(commit=False)
# We assume the date of labeling and the same as the date of arrival # We assume the date of labeling and the same as the date of arrival
basic_food.arrival_date = timezone.now() basic_food.arrival_date = timezone.now()
basic_food.is_ready = True basic_food.is_ready = False
basic_food.is_active = True
basic_food.was_eaten = False
basic_food._force_save = True basic_food._force_save = True
basic_food.save() basic_food.save()
basic_food.refresh_from_db() basic_food.refresh_from_db()
@ -146,6 +162,16 @@ class QRCodeBasicFoodCreateView(ProtectQuerysetMixin, ProtectedCreateView):
expiry_date=timezone.now(), expiry_date=timezone.now(),
) )
def get_context_data(self, **kwargs):
# Some field are hidden on create
context = super().get_context_data(**kwargs)
form = context['form']
form.fields['is_active'].widget = HiddenInput()
form.fields['was_eaten'].widget = HiddenInput()
return context
class QRCodeCreateView(ProtectQuerysetMixin, ProtectedCreateView): class QRCodeCreateView(ProtectQuerysetMixin, ProtectedCreateView):
""" """
@ -160,6 +186,8 @@ class QRCodeCreateView(ProtectQuerysetMixin, ProtectedCreateView):
qrcode = kwargs["slug"] qrcode = kwargs["slug"]
if self.model.objects.filter(qr_code_number=qrcode).count() > 0: if self.model.objects.filter(qr_code_number=qrcode).count() > 0:
return HttpResponseRedirect(reverse("food:qrcode_view", kwargs=kwargs)) return HttpResponseRedirect(reverse("food:qrcode_view", kwargs=kwargs))
elif not TransformedFood.objects.filter(is_ready=False, was_eaten=False, is_active=True).count() > 0:
return HttpResponseRedirect(reverse("food:qrcode_basic_create", kwargs=kwargs))
else: else:
return super().get(*args, **kwargs) return super().get(*args, **kwargs)
@ -213,11 +241,21 @@ class QRCodeView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
else: else:
return HttpResponseRedirect(reverse("food:qrcode_create", kwargs=kwargs)) return HttpResponseRedirect(reverse("food:qrcode_create", kwargs=kwargs))
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
# TO DO : Add perms here
context["can_update_basic"]=True
context["can_update_transformed"]=True
context["can_add_ingredient"] = True
class TransformedFoodFormView(ProtectQuerysetMixin): return context
class TransformedFoodCreateView(ProtectQuerysetMixin, ProtectedCreateView):
""" """
A view to add a tranformed food A view to add a tranformed food
""" """
# TO DO : fix the "NotImplementedError" (╯°□°)╯︵ ┻━┻ ...
model = TransformedFood model = TransformedFood
template_name = 'food/transformed_food_form.html' template_name = 'food/transformed_food_form.html'
form_class = TransformedFoodForms form_class = TransformedFoodForms
@ -233,6 +271,9 @@ class TransformedFoodFormView(ProtectQuerysetMixin):
# Save the aliment and allergens associated # Save the aliment and allergens associated
transformed_food = form.save(commit=False) transformed_food = form.save(commit=False)
transformed_food.expiry_date = transformed_food.creation_date transformed_food.expiry_date = transformed_food.creation_date
transformed_food.is_active = True
transformed_food.is_ready = False
transformed_food.was_eaten = False
transformed_food._force_save = True transformed_food._force_save = True
transformed_food.save() transformed_food.save()
transformed_food.refresh_from_db() transformed_food.refresh_from_db()
@ -244,18 +285,58 @@ class TransformedFoodFormView(ProtectQuerysetMixin):
self.object.refresh_from_db() self.object.refresh_from_db()
return reverse('food:food_view', kwargs={"pk": self.object.pk}) return reverse('food:food_view', kwargs={"pk": self.object.pk})
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
# Some field are hidden on create
form = context['form']
form.fields['is_active'].widget = HiddenInput()
form.fields['is_ready'].widget = HiddenInput()
form.fields['was_eaten'].widget = HiddenInput()
class TransformedFoodUpdateView(TransformedFoodFormView, LoginRequiredMixin, UpdateView): # Field shelf life is only display for authorized user
pass # TO DO : Add permission here
if not True:
form.fields['shelf_life'].widget = HiddenInput()
return context
class TransformedFoodCreateView(TransformedFoodFormView, ProtectedCreateView): class TransformedFoodUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
def get_sample_object(self): """
return TransformedFood( A view to update transformed product
name="", """
creation_date=timezone.now(), model = TransformedFood
) template_name = 'food/transformed_food_form.html'
form_class = TransformedFoodForms
extra_context = {'title' : _('Update meal')}
@transaction.atomic
def form_valid(self, form):
form.instance.creater = self.request.user
transformedfood_form = TransformedFoodForms(data=self.request.POST)
if not transformedfood_form.is_valid():
return self.form_invalid(form)
ans = super().form_valid(form)
form.instance.update()
return ans
def get_success_url(self, **kwargs):
self.object.refresh_from_db()
return reverse('food:food_view', kwargs={"pk": self.object.pk})
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
form = context['form']
fields = ['is_active','is_ready','was_eaten','shelf_life']
# TO DO : Add permissions here
permissions = [True]*len(fields)
for i in range(len(fields)):
if not permissions[i] : form[fields[i]].widget = HiddenInput()
return context
class TransformedListView(ProtectQuerysetMixin, LoginRequiredMixin, MultiTableMixin, ListView): class TransformedListView(ProtectQuerysetMixin, LoginRequiredMixin, MultiTableMixin, ListView):
""" """

View File

@ -3119,7 +3119,7 @@
"food", "food",
"transformedfood" "transformedfood"
], ],
"query": "", "query": "[]",
"type": "view", "type": "view",
"mask": 3, "mask": 3,
"field": "", "field": "",
@ -3135,7 +3135,7 @@
"food", "food",
"transformedfood" "transformedfood"
], ],
"query": "{\"owner\": \"club\"}", "query": "{\"owner\": [\"club\"]}",
"type": "view", "type": "view",
"mask": 3, "mask": 3,
"field": "", "field": "",
@ -3145,7 +3145,7 @@
}, },
{ {
"model": "permission.permission", "model": "permission.permission",
"pk": 200, "pk": 201,
"fields": { "fields": {
"model": [ "model": [
"food", "food",
@ -3239,7 +3239,7 @@
158, 158,
159, 159,
160, 160,
200 201
] ]
} }
}, },
@ -3266,7 +3266,7 @@
50, 50,
141, 141,
169, 169,
199 200
] ]
} }
}, },
@ -3441,7 +3441,7 @@
167, 167,
168, 168,
182, 182,
199 200
] ]
} }
}, },