Run pre-commit
This commit is contained in:
parent
64c58260d9
commit
18325aa59e
59 changed files with 1227 additions and 747 deletions
|
@ -19,4 +19,3 @@ git push heroku master
|
|||
|
||||
You may need to upgrade Python since Heroku tends to deprecate old patch versions rather quickly.
|
||||
In this case, edit `runtime.txt`.
|
||||
|
||||
|
|
|
@ -7,4 +7,4 @@ SERVER_EMAIL=server@example.com
|
|||
AUTHORIZED_EMAILS=user1@example.com,user2@example.com
|
||||
LIBRARIAN_EMAILS=user3@example.com,user4@example.com
|
||||
MAILGUN_ACCESS_KEY=access-key
|
||||
MAILGUN_SERVER_NAME=mg.example.com
|
||||
MAILGUN_SERVER_NAME=mg.example.com
|
||||
|
|
|
@ -5,11 +5,11 @@ import requests
|
|||
|
||||
|
||||
def main():
|
||||
port = os.getenv('PORT', 8000)
|
||||
res = requests.get(f'http://127.0.0.1:{port}/')
|
||||
port = os.getenv("PORT", 8000)
|
||||
res = requests.get(f"http://127.0.0.1:{port}/")
|
||||
if res.status_code >= 400:
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
278
manuels/admin.py
278
manuels/admin.py
|
@ -1,57 +1,78 @@
|
|||
from django.contrib import admin, messages
|
||||
from django.db.models import Prefetch
|
||||
from import_export import resources, fields
|
||||
from import_export import fields, resources
|
||||
from import_export.admin import ExportMixin
|
||||
from import_export.widgets import IntegerWidget, DecimalWidget
|
||||
from import_export.widgets import DecimalWidget, IntegerWidget
|
||||
|
||||
from manuels.models import Teacher, Book, Level, Editor, SuppliesRequirement, CommonSupply, ISBNError
|
||||
from manuels.models import (
|
||||
Book,
|
||||
CommonSupply,
|
||||
Editor,
|
||||
ISBNError,
|
||||
Level,
|
||||
SuppliesRequirement,
|
||||
Teacher,
|
||||
)
|
||||
|
||||
|
||||
class TeacherResource(resources.ModelResource):
|
||||
class Meta:
|
||||
model = Teacher
|
||||
fields = ('first_name', 'last_name', 'email', 'phone_number')
|
||||
fields = ("first_name", "last_name", "email", "phone_number")
|
||||
|
||||
|
||||
@admin.register(Teacher)
|
||||
class TeacherAdmin(ExportMixin, admin.ModelAdmin):
|
||||
resource_class = TeacherResource
|
||||
list_display = ['full_name', 'email', 'phone_number', 'has_confirmed_list']
|
||||
list_display = ["full_name", "email", "phone_number", "has_confirmed_list"]
|
||||
|
||||
def send_link(self, request, queryset):
|
||||
for teacher in queryset:
|
||||
teacher.send_link(request)
|
||||
messages.success(request, f'Le lien a bien été envoyé aux {queryset.count()} coordonateur(s) sélectionné(s).')
|
||||
messages.success(
|
||||
request,
|
||||
f"Le lien a bien été envoyé aux {queryset.count()} coordonateur(s) sélectionné(s).",
|
||||
)
|
||||
|
||||
send_link.short_description = 'Envoyer le lien'
|
||||
send_link.short_description = "Envoyer le lien"
|
||||
|
||||
actions = [send_link]
|
||||
|
||||
|
||||
class LevelResource(resources.ModelResource):
|
||||
non_acquired_book_count = fields.Field(attribute='non_acquired_book_count', widget=IntegerWidget())
|
||||
non_acquired_book_price = fields.Field(attribute='non_acquired_book_price', widget=DecimalWidget())
|
||||
non_acquired_consumable_count = fields.Field(attribute='non_acquired_consumable_count', widget=IntegerWidget())
|
||||
non_acquired_consumable_price = fields.Field(attribute='non_acquired_consumable_price', widget=DecimalWidget())
|
||||
non_acquired_total_price = fields.Field(attribute='non_acquired_total_price', widget=DecimalWidget())
|
||||
non_acquired_book_count = fields.Field(
|
||||
attribute="non_acquired_book_count", widget=IntegerWidget()
|
||||
)
|
||||
non_acquired_book_price = fields.Field(
|
||||
attribute="non_acquired_book_price", widget=DecimalWidget()
|
||||
)
|
||||
non_acquired_consumable_count = fields.Field(
|
||||
attribute="non_acquired_consumable_count", widget=IntegerWidget()
|
||||
)
|
||||
non_acquired_consumable_price = fields.Field(
|
||||
attribute="non_acquired_consumable_price", widget=DecimalWidget()
|
||||
)
|
||||
non_acquired_total_price = fields.Field(
|
||||
attribute="non_acquired_total_price", widget=DecimalWidget()
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = Level
|
||||
fields = (
|
||||
'name',
|
||||
'non_acquired_book_count',
|
||||
'non_acquired_book_price',
|
||||
'non_acquired_consumable_count',
|
||||
'non_acquired_consumable_price',
|
||||
'non_acquired_total_price',
|
||||
"name",
|
||||
"non_acquired_book_count",
|
||||
"non_acquired_book_price",
|
||||
"non_acquired_consumable_count",
|
||||
"non_acquired_consumable_price",
|
||||
"non_acquired_total_price",
|
||||
)
|
||||
export_order = (
|
||||
'name',
|
||||
'non_acquired_book_count',
|
||||
'non_acquired_book_price',
|
||||
'non_acquired_consumable_count',
|
||||
'non_acquired_consumable_price',
|
||||
'non_acquired_total_price',
|
||||
"name",
|
||||
"non_acquired_book_count",
|
||||
"non_acquired_book_price",
|
||||
"non_acquired_consumable_count",
|
||||
"non_acquired_consumable_price",
|
||||
"non_acquired_total_price",
|
||||
)
|
||||
|
||||
|
||||
|
@ -59,87 +80,160 @@ class LevelResource(resources.ModelResource):
|
|||
class LevelAdmin(ExportMixin, admin.ModelAdmin):
|
||||
resource_class = LevelResource
|
||||
list_display = [
|
||||
'name',
|
||||
'order',
|
||||
'non_acquired_book_count',
|
||||
'non_acquired_book_price',
|
||||
'non_acquired_consumable_count',
|
||||
'non_acquired_consumable_price',
|
||||
'non_acquired_total_price',
|
||||
"name",
|
||||
"order",
|
||||
"non_acquired_book_count",
|
||||
"non_acquired_book_price",
|
||||
"non_acquired_consumable_count",
|
||||
"non_acquired_consumable_price",
|
||||
"non_acquired_total_price",
|
||||
]
|
||||
list_editable = ['order']
|
||||
list_display_links = ['name']
|
||||
list_editable = ["order"]
|
||||
list_display_links = ["name"]
|
||||
|
||||
def get_queryset(self, request):
|
||||
return super(LevelAdmin, self).get_queryset(request).prefetch_related(
|
||||
Prefetch("book_set", to_attr="prefetched_books"))
|
||||
return (
|
||||
super(LevelAdmin, self)
|
||||
.get_queryset(request)
|
||||
.prefetch_related(Prefetch("book_set", to_attr="prefetched_books"))
|
||||
)
|
||||
|
||||
def non_acquired_book_count(self, obj: Level):
|
||||
return obj.non_acquired_book_count
|
||||
|
||||
non_acquired_book_count.short_description = 'Nombre de livres à acheter (hors consommables)'
|
||||
non_acquired_book_count.short_description = (
|
||||
"Nombre de livres à acheter (hors consommables)"
|
||||
)
|
||||
|
||||
def non_acquired_book_price(self, obj: Level):
|
||||
return f'{obj.non_acquired_book_price:.2f}€'
|
||||
return f"{obj.non_acquired_book_price:.2f}€"
|
||||
|
||||
non_acquired_book_price.short_description = 'Coût des livres à acheter (hors consommables)'
|
||||
non_acquired_book_price.short_description = (
|
||||
"Coût des livres à acheter (hors consommables)"
|
||||
)
|
||||
|
||||
def non_acquired_consumable_count(self, obj: Level):
|
||||
return obj.non_acquired_consumable_count
|
||||
|
||||
non_acquired_consumable_count.short_description = 'Nombre de consommables à acheter'
|
||||
non_acquired_consumable_count.short_description = "Nombre de consommables à acheter"
|
||||
|
||||
def non_acquired_consumable_price(self, obj: Level):
|
||||
return f'{obj.non_acquired_consumable_price:.2f}€'
|
||||
return f"{obj.non_acquired_consumable_price:.2f}€"
|
||||
|
||||
non_acquired_consumable_price.short_description = 'Coût des consommables à acheter'
|
||||
non_acquired_consumable_price.short_description = "Coût des consommables à acheter"
|
||||
|
||||
def non_acquired_total_price(self, obj: Level):
|
||||
return f'{obj.non_acquired_total_price:.2f}€'
|
||||
return f"{obj.non_acquired_total_price:.2f}€"
|
||||
|
||||
non_acquired_total_price.short_description = 'Coût total à acheter'
|
||||
non_acquired_total_price.short_description = "Coût total à acheter"
|
||||
|
||||
|
||||
class BookResource(resources.ModelResource):
|
||||
decitre_url = fields.Field(attribute='decitre_url')
|
||||
decitre_url = fields.Field(attribute="decitre_url")
|
||||
|
||||
class Meta:
|
||||
model = Book
|
||||
fields = ('title', 'authors', 'editor__name', 'publication_year', 'isbn', 'comments', 'other_editor',
|
||||
'price', 'previously_acquired', 'teacher__first_name', 'teacher__last_name', 'level__name', 'field',
|
||||
'consumable', "decitre_url")
|
||||
export_order = ('level__name', 'field', 'title', 'authors', 'editor__name', 'publication_year', 'isbn', 'price',
|
||||
'other_editor', 'previously_acquired', 'teacher__first_name', 'teacher__last_name', 'comments',
|
||||
'consumable', "decitre_url")
|
||||
fields = (
|
||||
"title",
|
||||
"authors",
|
||||
"editor__name",
|
||||
"publication_year",
|
||||
"isbn",
|
||||
"comments",
|
||||
"other_editor",
|
||||
"price",
|
||||
"previously_acquired",
|
||||
"teacher__first_name",
|
||||
"teacher__last_name",
|
||||
"level__name",
|
||||
"field",
|
||||
"consumable",
|
||||
"decitre_url",
|
||||
)
|
||||
export_order = (
|
||||
"level__name",
|
||||
"field",
|
||||
"title",
|
||||
"authors",
|
||||
"editor__name",
|
||||
"publication_year",
|
||||
"isbn",
|
||||
"price",
|
||||
"other_editor",
|
||||
"previously_acquired",
|
||||
"teacher__first_name",
|
||||
"teacher__last_name",
|
||||
"comments",
|
||||
"consumable",
|
||||
"decitre_url",
|
||||
)
|
||||
|
||||
|
||||
@admin.register(Book)
|
||||
class BookAdmin(ExportMixin, admin.ModelAdmin):
|
||||
resource_class = BookResource
|
||||
list_display = ['level', 'field', 'title', 'authors', 'editor', 'other_editor', 'publication_year', 'isbn',
|
||||
'price', 'previously_acquired', 'teacher', 'done', 'consumable']
|
||||
list_editable = ['done']
|
||||
list_filter = ['done', 'previously_acquired', 'consumable', 'level', 'editor', 'teacher']
|
||||
list_display_links = ['title']
|
||||
fieldsets = [
|
||||
('Infos livre', {
|
||||
'fields': ('title', 'consumable', 'authors', ('editor', 'other_editor'), 'publication_year',
|
||||
'isbn', 'created_at', 'updated_at', 'comments')
|
||||
}),
|
||||
('Élève', {
|
||||
'fields': ('price', 'previously_acquired',)
|
||||
}),
|
||||
('Coordonnateur', {
|
||||
'fields': ('teacher', 'level', 'field')
|
||||
}),
|
||||
('Gestion', {
|
||||
'fields': ('done',)
|
||||
}),
|
||||
list_display = [
|
||||
"level",
|
||||
"field",
|
||||
"title",
|
||||
"authors",
|
||||
"editor",
|
||||
"other_editor",
|
||||
"publication_year",
|
||||
"isbn",
|
||||
"price",
|
||||
"previously_acquired",
|
||||
"teacher",
|
||||
"done",
|
||||
"consumable",
|
||||
]
|
||||
readonly_fields = ['created_at', 'updated_at']
|
||||
list_editable = ["done"]
|
||||
list_filter = [
|
||||
"done",
|
||||
"previously_acquired",
|
||||
"consumable",
|
||||
"level",
|
||||
"editor",
|
||||
"teacher",
|
||||
]
|
||||
list_display_links = ["title"]
|
||||
fieldsets = [
|
||||
(
|
||||
"Infos livre",
|
||||
{
|
||||
"fields": (
|
||||
"title",
|
||||
"consumable",
|
||||
"authors",
|
||||
("editor", "other_editor"),
|
||||
"publication_year",
|
||||
"isbn",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
"comments",
|
||||
)
|
||||
},
|
||||
),
|
||||
(
|
||||
"Élève",
|
||||
{
|
||||
"fields": (
|
||||
"price",
|
||||
"previously_acquired",
|
||||
)
|
||||
},
|
||||
),
|
||||
("Coordonnateur", {"fields": ("teacher", "level", "field")}),
|
||||
("Gestion", {"fields": ("done",)}),
|
||||
]
|
||||
readonly_fields = ["created_at", "updated_at"]
|
||||
|
||||
def get_queryset(self, request):
|
||||
return super(BookAdmin, self).get_queryset(request).select_related("editor", "level", "teacher")
|
||||
return (
|
||||
super(BookAdmin, self)
|
||||
.get_queryset(request)
|
||||
.select_related("editor", "level", "teacher")
|
||||
)
|
||||
|
||||
def update_with_decitre(self, request, queryset):
|
||||
for book in queryset:
|
||||
|
@ -147,15 +241,15 @@ class BookAdmin(ExportMixin, admin.ModelAdmin):
|
|||
book.update_from_decitre()
|
||||
messages.success(
|
||||
request,
|
||||
f'Mise à jour réussie du livre "{book.title}" ({book.level.name} - {book.field})'
|
||||
f'Mise à jour réussie du livre "{book.title}" ({book.level.name} - {book.field})',
|
||||
)
|
||||
except ISBNError as e:
|
||||
messages.warning(
|
||||
request,
|
||||
f'Erreur lors de la mise à jour du livre "{book.title}" ({book.level.name} - {book.field}) : {e.data.get("error")}'
|
||||
f'Erreur lors de la mise à jour du livre "{book.title}" ({book.level.name} - {book.field}) : {e.data.get("error")}',
|
||||
)
|
||||
|
||||
update_with_decitre.short_description = 'Mettre à jour avec Decitre'
|
||||
update_with_decitre.short_description = "Mettre à jour avec Decitre"
|
||||
|
||||
def mark_as_done(self, request, queryset):
|
||||
queryset.update(done=True)
|
||||
|
@ -171,25 +265,41 @@ class EditorAdmin(admin.ModelAdmin):
|
|||
|
||||
@admin.register(CommonSupply)
|
||||
class CommonSupplyAdmin(admin.ModelAdmin):
|
||||
list_display = ['name', 'order']
|
||||
list_display_links = ['name']
|
||||
list_editable = ['order']
|
||||
list_display = ["name", "order"]
|
||||
list_display_links = ["name"]
|
||||
list_editable = ["order"]
|
||||
|
||||
|
||||
class SuppliesResource(resources.ModelResource):
|
||||
class Meta:
|
||||
model = SuppliesRequirement
|
||||
fields = ('supplies', 'field', 'level__name', 'teacher__first_name', 'teacher__last_name')
|
||||
export_order = ('level__name', 'field', 'supplies', 'teacher__first_name', 'teacher__last_name')
|
||||
fields = (
|
||||
"supplies",
|
||||
"field",
|
||||
"level__name",
|
||||
"teacher__first_name",
|
||||
"teacher__last_name",
|
||||
)
|
||||
export_order = (
|
||||
"level__name",
|
||||
"field",
|
||||
"supplies",
|
||||
"teacher__first_name",
|
||||
"teacher__last_name",
|
||||
)
|
||||
|
||||
|
||||
@admin.register(SuppliesRequirement)
|
||||
class SuppliesRequirementAdmin(ExportMixin, admin.ModelAdmin):
|
||||
resource_class = SuppliesResource
|
||||
list_display = ['id', 'teacher', 'level', 'field', 'supplies', 'done']
|
||||
list_editable = ['done']
|
||||
readonly_fields = ['created_at', 'updated_at']
|
||||
list_filter = ['done', 'teacher', 'level']
|
||||
list_display = ["id", "teacher", "level", "field", "supplies", "done"]
|
||||
list_editable = ["done"]
|
||||
readonly_fields = ["created_at", "updated_at"]
|
||||
list_filter = ["done", "teacher", "level"]
|
||||
|
||||
def get_queryset(self, request):
|
||||
return super(SuppliesRequirementAdmin, self).get_queryset(request).select_related("level", "teacher")
|
||||
return (
|
||||
super(SuppliesRequirementAdmin, self)
|
||||
.get_queryset(request)
|
||||
.select_related("level", "teacher")
|
||||
)
|
||||
|
|
|
@ -2,4 +2,4 @@ from django.apps import AppConfig
|
|||
|
||||
|
||||
class ManuelsConfig(AppConfig):
|
||||
name = 'manuels'
|
||||
name = "manuels"
|
||||
|
|
|
@ -2,4 +2,4 @@ from django.conf import settings
|
|||
|
||||
|
||||
def authorized_mails(request):
|
||||
return {'authorized_mails': settings.AUTHORIZED_EMAILS}
|
||||
return {"authorized_mails": settings.AUTHORIZED_EMAILS}
|
||||
|
|
127
manuels/forms.py
127
manuels/forms.py
|
@ -1,93 +1,136 @@
|
|||
from django import forms
|
||||
from django.core.exceptions import ValidationError
|
||||
|
||||
from manuels.models import Book, SuppliesRequirement, Level
|
||||
from manuels.models import Book, Level, SuppliesRequirement
|
||||
|
||||
|
||||
class EditBookForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Book
|
||||
fields = ['teacher', 'level', 'field', 'no_book', 'see_later', 'title', 'authors', 'editor', 'other_editor',
|
||||
'publication_year', 'isbn', 'price', 'previously_acquired', 'comments', 'consumable']
|
||||
fields = [
|
||||
"teacher",
|
||||
"level",
|
||||
"field",
|
||||
"no_book",
|
||||
"see_later",
|
||||
"title",
|
||||
"authors",
|
||||
"editor",
|
||||
"other_editor",
|
||||
"publication_year",
|
||||
"isbn",
|
||||
"price",
|
||||
"previously_acquired",
|
||||
"comments",
|
||||
"consumable",
|
||||
]
|
||||
|
||||
no_book = forms.BooleanField(label='Pas de livre pour cette classe/matière', required=False, initial=False)
|
||||
no_book = forms.BooleanField(
|
||||
label="Pas de livre pour cette classe/matière", required=False, initial=False
|
||||
)
|
||||
see_later = forms.BooleanField(
|
||||
label='Voir à la rentrée', help_text="Notamment en cas de désaccord sur l'adoption ou non d'un manuel",
|
||||
required=False, initial=False
|
||||
label="Voir à la rentrée",
|
||||
help_text="Notamment en cas de désaccord sur l'adoption ou non d'un manuel",
|
||||
required=False,
|
||||
initial=False,
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields['title'].widget = forms.TextInput()
|
||||
self.fields['authors'].widget = forms.TextInput()
|
||||
self.fields['comments'].widget.attrs.update(rows=3)
|
||||
self.fields['teacher'].widget.attrs.update({'class': 'custom-select'})
|
||||
self.fields['editor'].widget.attrs.update({'class': 'custom-select'})
|
||||
self.fields['previously_acquired'].widget.attrs.update({'class': 'custom-select'})
|
||||
self.fields['consumable'].widget.attrs.update({'class': 'custom-select'})
|
||||
if 'level' in self.fields:
|
||||
self.fields['level'].widget.attrs.update({'class': 'custom-select'})
|
||||
self.fields["title"].widget = forms.TextInput()
|
||||
self.fields["authors"].widget = forms.TextInput()
|
||||
self.fields["comments"].widget.attrs.update(rows=3)
|
||||
self.fields["teacher"].widget.attrs.update({"class": "custom-select"})
|
||||
self.fields["editor"].widget.attrs.update({"class": "custom-select"})
|
||||
self.fields["previously_acquired"].widget.attrs.update(
|
||||
{"class": "custom-select"}
|
||||
)
|
||||
self.fields["consumable"].widget.attrs.update({"class": "custom-select"})
|
||||
if "level" in self.fields:
|
||||
self.fields["level"].widget.attrs.update({"class": "custom-select"})
|
||||
|
||||
def clean(self):
|
||||
editor = self.cleaned_data['editor']
|
||||
other_editor = self.cleaned_data['other_editor']
|
||||
title = self.cleaned_data['title']
|
||||
editor = self.cleaned_data["editor"]
|
||||
other_editor = self.cleaned_data["other_editor"]
|
||||
title = self.cleaned_data["title"]
|
||||
|
||||
if (editor
|
||||
and 'autre' in editor.name.lower()
|
||||
and not other_editor
|
||||
and title not in ['PAS DE LIVRE POUR CETTE CLASSE', 'VOIR À LA RENTRÉE']):
|
||||
if (
|
||||
editor
|
||||
and "autre" in editor.name.lower()
|
||||
and not other_editor
|
||||
and title not in ["PAS DE LIVRE POUR CETTE CLASSE", "VOIR À LA RENTRÉE"]
|
||||
):
|
||||
self.add_error(
|
||||
'other_editor',
|
||||
"other_editor",
|
||||
ValidationError(
|
||||
"Vous devez préciser l'éditeur si vous n'en choisissez pas un parmi la liste.",
|
||||
code='missing'
|
||||
)
|
||||
code="missing",
|
||||
),
|
||||
)
|
||||
|
||||
def clean_previously_acquired(self):
|
||||
data = self.cleaned_data['previously_acquired']
|
||||
if data is None or data == '':
|
||||
raise ValidationError('Vous devez choisir une valeur')
|
||||
data = self.cleaned_data["previously_acquired"]
|
||||
if data is None or data == "":
|
||||
raise ValidationError("Vous devez choisir une valeur")
|
||||
|
||||
return data
|
||||
|
||||
|
||||
class AddBookForm(EditBookForm):
|
||||
class Meta(EditBookForm.Meta):
|
||||
fields = ['teacher', 'levels', 'field', 'no_book', 'see_later', 'title', 'authors', 'editor', 'other_editor',
|
||||
'publication_year', 'isbn', 'price', 'previously_acquired', 'comments', 'add_another', 'consumable']
|
||||
fields = [
|
||||
"teacher",
|
||||
"levels",
|
||||
"field",
|
||||
"no_book",
|
||||
"see_later",
|
||||
"title",
|
||||
"authors",
|
||||
"editor",
|
||||
"other_editor",
|
||||
"publication_year",
|
||||
"isbn",
|
||||
"price",
|
||||
"previously_acquired",
|
||||
"comments",
|
||||
"add_another",
|
||||
"consumable",
|
||||
]
|
||||
|
||||
add_another = forms.BooleanField(label='Ajouter un autre livre', required=False, initial=True)
|
||||
add_another = forms.BooleanField(
|
||||
label="Ajouter un autre livre", required=False, initial=True
|
||||
)
|
||||
levels = forms.ModelMultipleChoiceField(
|
||||
queryset=Level.objects.all(),
|
||||
label='Classes',
|
||||
label="Classes",
|
||||
required=True,
|
||||
help_text='Maintenez la touche Ctrl (ou Cmd) enfoncée pour en sélectionner plusieurs.'
|
||||
help_text="Maintenez la touche Ctrl (ou Cmd) enfoncée pour en sélectionner plusieurs.",
|
||||
)
|
||||
|
||||
|
||||
class EditSuppliesForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = SuppliesRequirement
|
||||
fields = ['teacher', 'level', 'field', 'supplies']
|
||||
fields = ["teacher", "level", "field", "supplies"]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields['supplies'].widget.attrs.update(rows=3)
|
||||
self.fields['teacher'].widget.attrs.update({'class': 'custom-select'})
|
||||
if 'level' in self.fields:
|
||||
self.fields['level'].widget.attrs.update({'class': 'custom-select'})
|
||||
self.fields["supplies"].widget.attrs.update(rows=3)
|
||||
self.fields["teacher"].widget.attrs.update({"class": "custom-select"})
|
||||
if "level" in self.fields:
|
||||
self.fields["level"].widget.attrs.update({"class": "custom-select"})
|
||||
|
||||
|
||||
class AddSuppliesForm(EditSuppliesForm):
|
||||
class Meta(EditSuppliesForm.Meta):
|
||||
fields = ['teacher', 'levels', 'field', 'supplies']
|
||||
fields = ["teacher", "levels", "field", "supplies"]
|
||||
|
||||
add_another = forms.BooleanField(label="Ajouter d'autres fournitures", required=False, initial=True)
|
||||
add_another = forms.BooleanField(
|
||||
label="Ajouter d'autres fournitures", required=False, initial=True
|
||||
)
|
||||
levels = forms.ModelMultipleChoiceField(
|
||||
queryset=Level.objects.all(),
|
||||
label='Classes',
|
||||
label="Classes",
|
||||
required=True,
|
||||
help_text='Maintenez la touche Ctrl (ou Cmd) enfoncée pour en sélectionner plusieurs.'
|
||||
help_text="Maintenez la touche Ctrl (ou Cmd) enfoncée pour en sélectionner plusieurs.",
|
||||
)
|
||||
|
|
|
@ -3,7 +3,7 @@ from django.core.management import BaseCommand
|
|||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = 'Clears django cache'
|
||||
help = "Clears django cache"
|
||||
|
||||
def handle(self, *args, **options):
|
||||
cache.clear()
|
||||
|
|
|
@ -1,71 +1,142 @@
|
|||
# Generated by Django 2.0.5 on 2018-05-21 22:47
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import manuels.models
|
||||
import uuid
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
import manuels.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
dependencies = []
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Book',
|
||||
name="Book",
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('field', models.CharField(max_length=100, verbose_name='matière')),
|
||||
('title', models.TextField(verbose_name='titre')),
|
||||
('authors', models.TextField(verbose_name='auteurs')),
|
||||
('editor', models.CharField(max_length=200, verbose_name='éditeur')),
|
||||
('collection', models.CharField(blank=True, max_length=200, verbose_name='collection')),
|
||||
('publication_year', models.PositiveIntegerField(verbose_name='année de publication')),
|
||||
('isbn', models.CharField(max_length=20, validators=[manuels.models.isbn_validator], verbose_name='ISBN/EAN')),
|
||||
('price', models.PositiveIntegerField(verbose_name='prix')),
|
||||
('previously_acquired', models.BooleanField(choices=[(True, 'Oui'), (False, 'Non')], verbose_name="manuel acquis précédemment par l'élève")),
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("field", models.CharField(max_length=100, verbose_name="matière")),
|
||||
("title", models.TextField(verbose_name="titre")),
|
||||
("authors", models.TextField(verbose_name="auteurs")),
|
||||
("editor", models.CharField(max_length=200, verbose_name="éditeur")),
|
||||
(
|
||||
"collection",
|
||||
models.CharField(
|
||||
blank=True, max_length=200, verbose_name="collection"
|
||||
),
|
||||
),
|
||||
(
|
||||
"publication_year",
|
||||
models.PositiveIntegerField(verbose_name="année de publication"),
|
||||
),
|
||||
(
|
||||
"isbn",
|
||||
models.CharField(
|
||||
max_length=20,
|
||||
validators=[manuels.models.isbn_validator],
|
||||
verbose_name="ISBN/EAN",
|
||||
),
|
||||
),
|
||||
("price", models.PositiveIntegerField(verbose_name="prix")),
|
||||
(
|
||||
"previously_acquired",
|
||||
models.BooleanField(
|
||||
choices=[(True, "Oui"), (False, "Non")],
|
||||
verbose_name="manuel acquis précédemment par l'élève",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'livre',
|
||||
'verbose_name_plural': 'livres',
|
||||
"verbose_name": "livre",
|
||||
"verbose_name_plural": "livres",
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Level',
|
||||
name="Level",
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=10, verbose_name='nom')),
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("name", models.CharField(max_length=10, verbose_name="nom")),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'classe',
|
||||
'verbose_name_plural': 'classes',
|
||||
"verbose_name": "classe",
|
||||
"verbose_name_plural": "classes",
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Teacher',
|
||||
name="Teacher",
|
||||
fields=[
|
||||
('uuid', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
|
||||
('first_name', models.CharField(max_length=100, verbose_name='prénom')),
|
||||
('last_name', models.CharField(max_length=100, verbose_name='nom')),
|
||||
('phone_number', models.CharField(help_text="En cas d'urgence", max_length=10, verbose_name='numéro de téléphone')),
|
||||
('email', models.EmailField(help_text='Utilisée pour vous transmettre votre lien personnel', max_length=254, unique=True, verbose_name='adresse email')),
|
||||
(
|
||||
"uuid",
|
||||
models.UUIDField(
|
||||
default=uuid.uuid4,
|
||||
editable=False,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
),
|
||||
),
|
||||
("first_name", models.CharField(max_length=100, verbose_name="prénom")),
|
||||
("last_name", models.CharField(max_length=100, verbose_name="nom")),
|
||||
(
|
||||
"phone_number",
|
||||
models.CharField(
|
||||
help_text="En cas d'urgence",
|
||||
max_length=10,
|
||||
verbose_name="numéro de téléphone",
|
||||
),
|
||||
),
|
||||
(
|
||||
"email",
|
||||
models.EmailField(
|
||||
help_text="Utilisée pour vous transmettre votre lien personnel",
|
||||
max_length=254,
|
||||
unique=True,
|
||||
verbose_name="adresse email",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'enseignant',
|
||||
'verbose_name_plural': 'enseignants',
|
||||
"verbose_name": "enseignant",
|
||||
"verbose_name_plural": "enseignants",
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='book',
|
||||
name='level',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='manuels.Level', verbose_name='classe'),
|
||||
model_name="book",
|
||||
name="level",
|
||||
field=models.ForeignKey(
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
to="manuels.Level",
|
||||
verbose_name="classe",
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='book',
|
||||
name='teacher',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='manuels.Teacher', verbose_name='enseignant'),
|
||||
model_name="book",
|
||||
name="teacher",
|
||||
field=models.ForeignKey(
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
to="manuels.Teacher",
|
||||
verbose_name="enseignant",
|
||||
),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -1,30 +1,43 @@
|
|||
# Generated by Django 2.0.5 on 2018-05-21 23:32
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('manuels', '0001_initial'),
|
||||
("manuels", "0001_initial"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Editor',
|
||||
name="Editor",
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=50, verbose_name='nom')),
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("name", models.CharField(max_length=50, verbose_name="nom")),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'éditeur',
|
||||
'verbose_name_plural': 'éditeurs',
|
||||
"verbose_name": "éditeur",
|
||||
"verbose_name_plural": "éditeurs",
|
||||
},
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='book',
|
||||
name='editor',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='manuels.Editor', verbose_name='éditeur'),
|
||||
model_name="book",
|
||||
name="editor",
|
||||
field=models.ForeignKey(
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
to="manuels.Editor",
|
||||
verbose_name="éditeur",
|
||||
),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -1,58 +1,66 @@
|
|||
# Generated by Django 2.0.5 on 2018-05-21 23:45
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.utils.timezone
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('manuels', '0002_auto_20180522_0132'),
|
||||
("manuels", "0002_auto_20180522_0132"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='book',
|
||||
name='created_at',
|
||||
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
|
||||
model_name="book",
|
||||
name="created_at",
|
||||
field=models.DateTimeField(
|
||||
auto_now_add=True, default=django.utils.timezone.now
|
||||
),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='book',
|
||||
name='updated_at',
|
||||
model_name="book",
|
||||
name="updated_at",
|
||||
field=models.DateTimeField(auto_now=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='editor',
|
||||
name='created_at',
|
||||
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
|
||||
model_name="editor",
|
||||
name="created_at",
|
||||
field=models.DateTimeField(
|
||||
auto_now_add=True, default=django.utils.timezone.now
|
||||
),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='editor',
|
||||
name='updated_at',
|
||||
model_name="editor",
|
||||
name="updated_at",
|
||||
field=models.DateTimeField(auto_now=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='level',
|
||||
name='created_at',
|
||||
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
|
||||
model_name="level",
|
||||
name="created_at",
|
||||
field=models.DateTimeField(
|
||||
auto_now_add=True, default=django.utils.timezone.now
|
||||
),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='level',
|
||||
name='updated_at',
|
||||
model_name="level",
|
||||
name="updated_at",
|
||||
field=models.DateTimeField(auto_now=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='teacher',
|
||||
name='created_at',
|
||||
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
|
||||
model_name="teacher",
|
||||
name="created_at",
|
||||
field=models.DateTimeField(
|
||||
auto_now_add=True, default=django.utils.timezone.now
|
||||
),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='teacher',
|
||||
name='updated_at',
|
||||
model_name="teacher",
|
||||
name="updated_at",
|
||||
field=models.DateTimeField(auto_now=True),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -6,48 +6,48 @@ from django.db import migrations, models
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('manuels', '0003_auto_20180522_0145'),
|
||||
("manuels", "0003_auto_20180522_0145"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='book',
|
||||
name='created_at',
|
||||
field=models.DateTimeField(auto_now_add=True, verbose_name='créé le'),
|
||||
model_name="book",
|
||||
name="created_at",
|
||||
field=models.DateTimeField(auto_now_add=True, verbose_name="créé le"),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='book',
|
||||
name='updated_at',
|
||||
field=models.DateTimeField(auto_now=True, verbose_name='mis à jour le'),
|
||||
model_name="book",
|
||||
name="updated_at",
|
||||
field=models.DateTimeField(auto_now=True, verbose_name="mis à jour le"),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='editor',
|
||||
name='created_at',
|
||||
field=models.DateTimeField(auto_now_add=True, verbose_name='créé le'),
|
||||
model_name="editor",
|
||||
name="created_at",
|
||||
field=models.DateTimeField(auto_now_add=True, verbose_name="créé le"),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='editor',
|
||||
name='updated_at',
|
||||
field=models.DateTimeField(auto_now=True, verbose_name='mis à jour le'),
|
||||
model_name="editor",
|
||||
name="updated_at",
|
||||
field=models.DateTimeField(auto_now=True, verbose_name="mis à jour le"),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='level',
|
||||
name='created_at',
|
||||
field=models.DateTimeField(auto_now_add=True, verbose_name='créé le'),
|
||||
model_name="level",
|
||||
name="created_at",
|
||||
field=models.DateTimeField(auto_now_add=True, verbose_name="créé le"),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='level',
|
||||
name='updated_at',
|
||||
field=models.DateTimeField(auto_now=True, verbose_name='mis à jour le'),
|
||||
model_name="level",
|
||||
name="updated_at",
|
||||
field=models.DateTimeField(auto_now=True, verbose_name="mis à jour le"),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='teacher',
|
||||
name='created_at',
|
||||
field=models.DateTimeField(auto_now_add=True, verbose_name='créé le'),
|
||||
model_name="teacher",
|
||||
name="created_at",
|
||||
field=models.DateTimeField(auto_now_add=True, verbose_name="créé le"),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='teacher',
|
||||
name='updated_at',
|
||||
field=models.DateTimeField(auto_now=True, verbose_name='mis à jour le'),
|
||||
model_name="teacher",
|
||||
name="updated_at",
|
||||
field=models.DateTimeField(auto_now=True, verbose_name="mis à jour le"),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -1,29 +1,59 @@
|
|||
# Generated by Django 2.0.5 on 2018-05-22 07:34
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('manuels', '0004_auto_20180522_0148'),
|
||||
("manuels", "0004_auto_20180522_0148"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='SuppliesRequirement',
|
||||
name="SuppliesRequirement",
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('created_at', models.DateTimeField(auto_now_add=True, verbose_name='créé le')),
|
||||
('updated_at', models.DateTimeField(auto_now=True, verbose_name='mis à jour le')),
|
||||
('supplies', models.TextField(verbose_name='fournitures')),
|
||||
('level', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='manuels.Level', verbose_name='classe')),
|
||||
('teacher', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='manuels.Teacher', verbose_name='enseignant')),
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"created_at",
|
||||
models.DateTimeField(auto_now_add=True, verbose_name="créé le"),
|
||||
),
|
||||
(
|
||||
"updated_at",
|
||||
models.DateTimeField(auto_now=True, verbose_name="mis à jour le"),
|
||||
),
|
||||
("supplies", models.TextField(verbose_name="fournitures")),
|
||||
(
|
||||
"level",
|
||||
models.ForeignKey(
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
to="manuels.Level",
|
||||
verbose_name="classe",
|
||||
),
|
||||
),
|
||||
(
|
||||
"teacher",
|
||||
models.ForeignKey(
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
to="manuels.Teacher",
|
||||
verbose_name="enseignant",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'demande de fournitures',
|
||||
'verbose_name_plural': 'demandes de fournitures',
|
||||
"verbose_name": "demande de fournitures",
|
||||
"verbose_name_plural": "demandes de fournitures",
|
||||
},
|
||||
),
|
||||
]
|
||||
|
|
|
@ -6,13 +6,17 @@ from django.db import migrations, models
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('manuels', '0005_suppliesrequirement'),
|
||||
("manuels", "0005_suppliesrequirement"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='book',
|
||||
name='previously_acquired',
|
||||
field=models.BooleanField(choices=[(True, 'Oui'), (False, 'Non')], default=False, verbose_name="manuel acquis précédemment par l'élève"),
|
||||
model_name="book",
|
||||
name="previously_acquired",
|
||||
field=models.BooleanField(
|
||||
choices=[(True, "Oui"), (False, "Non")],
|
||||
default=False,
|
||||
verbose_name="manuel acquis précédemment par l'élève",
|
||||
),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -6,13 +6,17 @@ from django.db import migrations, models
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('manuels', '0006_auto_20180522_1009'),
|
||||
("manuels", "0006_auto_20180522_1009"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='book',
|
||||
name='previously_acquired',
|
||||
field=models.BooleanField(choices=[(False, 'Non'), (True, 'Oui')], default=False, verbose_name="manuel acquis précédemment par l'élève"),
|
||||
model_name="book",
|
||||
name="previously_acquired",
|
||||
field=models.BooleanField(
|
||||
choices=[(False, "Non"), (True, "Oui")],
|
||||
default=False,
|
||||
verbose_name="manuel acquis précédemment par l'élève",
|
||||
),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -1,39 +1,64 @@
|
|||
# Generated by Django 2.0.5 on 2018-05-22 08:51
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('manuels', '0007_auto_20180522_1026'),
|
||||
("manuels", "0007_auto_20180522_1026"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='book',
|
||||
name='editor',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='manuels.Editor', verbose_name='éditeur'),
|
||||
model_name="book",
|
||||
name="editor",
|
||||
field=models.ForeignKey(
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
to="manuels.Editor",
|
||||
verbose_name="éditeur",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='book',
|
||||
name='level',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='manuels.Level', verbose_name='classe'),
|
||||
model_name="book",
|
||||
name="level",
|
||||
field=models.ForeignKey(
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
to="manuels.Level",
|
||||
verbose_name="classe",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='book',
|
||||
name='teacher',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='manuels.Teacher', verbose_name='enseignant'),
|
||||
model_name="book",
|
||||
name="teacher",
|
||||
field=models.ForeignKey(
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
to="manuels.Teacher",
|
||||
verbose_name="enseignant",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='suppliesrequirement',
|
||||
name='level',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='manuels.Level', verbose_name='classe'),
|
||||
model_name="suppliesrequirement",
|
||||
name="level",
|
||||
field=models.ForeignKey(
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
to="manuels.Level",
|
||||
verbose_name="classe",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='suppliesrequirement',
|
||||
name='teacher',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='manuels.Teacher', verbose_name='enseignant'),
|
||||
model_name="suppliesrequirement",
|
||||
name="teacher",
|
||||
field=models.ForeignKey(
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
to="manuels.Teacher",
|
||||
verbose_name="enseignant",
|
||||
),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -6,14 +6,14 @@ from django.db import migrations, models
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('manuels', '0008_auto_20180522_1051'),
|
||||
("manuels", "0008_auto_20180522_1051"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='suppliesrequirement',
|
||||
name='field',
|
||||
field=models.CharField(default='', max_length=100, verbose_name='matière'),
|
||||
model_name="suppliesrequirement",
|
||||
name="field",
|
||||
field=models.CharField(default="", max_length=100, verbose_name="matière"),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
||||
|
|
|
@ -6,12 +6,12 @@ from django.db import migrations
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('manuels', '0009_suppliesrequirement_field'),
|
||||
("manuels", "0009_suppliesrequirement_field"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='book',
|
||||
name='collection',
|
||||
model_name="book",
|
||||
name="collection",
|
||||
),
|
||||
]
|
||||
|
|
|
@ -1,19 +1,25 @@
|
|||
# Generated by Django 2.0.5 on 2018-05-23 22:13
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
import manuels.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('manuels', '0010_remove_book_collection'),
|
||||
("manuels", "0010_remove_book_collection"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='teacher',
|
||||
name='phone_number',
|
||||
field=models.CharField(help_text="En cas d'urgence, 10 chiffres.", max_length=10, validators=[manuels.models.phone_validator], verbose_name='numéro de téléphone'),
|
||||
model_name="teacher",
|
||||
name="phone_number",
|
||||
field=models.CharField(
|
||||
help_text="En cas d'urgence, 10 chiffres.",
|
||||
max_length=10,
|
||||
validators=[manuels.models.phone_validator],
|
||||
verbose_name="numéro de téléphone",
|
||||
),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -1,19 +1,25 @@
|
|||
# Generated by Django 2.0.5 on 2018-05-23 22:14
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
import manuels.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('manuels', '0011_auto_20180524_0013'),
|
||||
("manuels", "0011_auto_20180524_0013"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='book',
|
||||
name='isbn',
|
||||
field=models.CharField(help_text='Format attendu : 10 ou 13 chiffres, éventuellement séparés par des tirets et éventuellement suivis de la lettre <code>X</code>', max_length=20, validators=[manuels.models.isbn_validator], verbose_name='ISBN/EAN'),
|
||||
model_name="book",
|
||||
name="isbn",
|
||||
field=models.CharField(
|
||||
help_text="Format attendu : 10 ou 13 chiffres, éventuellement séparés par des tirets et éventuellement suivis de la lettre <code>X</code>",
|
||||
max_length=20,
|
||||
validators=[manuels.models.isbn_validator],
|
||||
verbose_name="ISBN/EAN",
|
||||
),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -6,28 +6,28 @@ from django.db import migrations, models
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('manuels', '0012_auto_20180524_0014'),
|
||||
("manuels", "0012_auto_20180524_0014"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='book',
|
||||
name='field',
|
||||
field=models.CharField(max_length=200, verbose_name='matière'),
|
||||
model_name="book",
|
||||
name="field",
|
||||
field=models.CharField(max_length=200, verbose_name="matière"),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='editor',
|
||||
name='name',
|
||||
field=models.CharField(max_length=100, verbose_name='nom'),
|
||||
model_name="editor",
|
||||
name="name",
|
||||
field=models.CharField(max_length=100, verbose_name="nom"),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='level',
|
||||
name='name',
|
||||
field=models.CharField(max_length=50, verbose_name='nom'),
|
||||
model_name="level",
|
||||
name="name",
|
||||
field=models.CharField(max_length=50, verbose_name="nom"),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='suppliesrequirement',
|
||||
name='field',
|
||||
field=models.CharField(max_length=200, verbose_name='matière'),
|
||||
model_name="suppliesrequirement",
|
||||
name="field",
|
||||
field=models.CharField(max_length=200, verbose_name="matière"),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -6,13 +6,13 @@ from django.db import migrations
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('manuels', '0013_auto_20180524_0016'),
|
||||
("manuels", "0013_auto_20180524_0016"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameField(
|
||||
model_name='suppliesrequirement',
|
||||
old_name='field',
|
||||
new_name='fields',
|
||||
model_name="suppliesrequirement",
|
||||
old_name="field",
|
||||
new_name="fields",
|
||||
),
|
||||
]
|
||||
|
|
|
@ -6,13 +6,13 @@ from django.db import migrations, models
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('manuels', '0014_auto_20180524_0034'),
|
||||
("manuels", "0014_auto_20180524_0034"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='suppliesrequirement',
|
||||
name='fields',
|
||||
field=models.TextField(verbose_name='matières'),
|
||||
model_name="suppliesrequirement",
|
||||
name="fields",
|
||||
field=models.TextField(verbose_name="matières"),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -6,18 +6,18 @@ from django.db import migrations, models
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('manuels', '0015_auto_20180524_0035'),
|
||||
("manuels", "0015_auto_20180524_0035"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='book',
|
||||
name='field',
|
||||
field=models.CharField(max_length=200, verbose_name='discipline'),
|
||||
model_name="book",
|
||||
name="field",
|
||||
field=models.CharField(max_length=200, verbose_name="discipline"),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='suppliesrequirement',
|
||||
name='fields',
|
||||
field=models.TextField(verbose_name='disciplines'),
|
||||
model_name="suppliesrequirement",
|
||||
name="fields",
|
||||
field=models.TextField(verbose_name="disciplines"),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -6,18 +6,18 @@ from django.db import migrations, models
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('manuels', '0016_auto_20180530_1801'),
|
||||
("manuels", "0016_auto_20180530_1801"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='book',
|
||||
name='done',
|
||||
field=models.BooleanField(default=False, verbose_name='Traité'),
|
||||
model_name="book",
|
||||
name="done",
|
||||
field=models.BooleanField(default=False, verbose_name="Traité"),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='suppliesrequirement',
|
||||
name='done',
|
||||
field=models.BooleanField(default=False, verbose_name='Traité'),
|
||||
model_name="suppliesrequirement",
|
||||
name="done",
|
||||
field=models.BooleanField(default=False, verbose_name="Traité"),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -6,14 +6,18 @@ from django.db import migrations, models
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('manuels', '0017_auto_20180530_1804'),
|
||||
("manuels", "0017_auto_20180530_1804"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='book',
|
||||
name='comments',
|
||||
field=models.TextField(default='', help_text="Ce message sera visible par la documentaliste. Vous pouvez l'utiliser par exemple si vous souhaitez saisir un éditeur qui n'est pas proposé.", verbose_name='commentaires'),
|
||||
model_name="book",
|
||||
name="comments",
|
||||
field=models.TextField(
|
||||
default="",
|
||||
help_text="Ce message sera visible par la documentaliste. Vous pouvez l'utiliser par exemple si vous souhaitez saisir un éditeur qui n'est pas proposé.",
|
||||
verbose_name="commentaires",
|
||||
),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
||||
|
|
|
@ -6,13 +6,17 @@ from django.db import migrations, models
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('manuels', '0018_book_comments'),
|
||||
("manuels", "0018_book_comments"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='book',
|
||||
name='comments',
|
||||
field=models.TextField(blank=True, help_text="Ce message sera visible par la documentaliste. Vous pouvez l'utiliser par exemple si vous souhaitez saisir un éditeur qui n'est pas proposé.", verbose_name='commentaires'),
|
||||
model_name="book",
|
||||
name="comments",
|
||||
field=models.TextField(
|
||||
blank=True,
|
||||
help_text="Ce message sera visible par la documentaliste. Vous pouvez l'utiliser par exemple si vous souhaitez saisir un éditeur qui n'est pas proposé.",
|
||||
verbose_name="commentaires",
|
||||
),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -1,28 +1,41 @@
|
|||
# Generated by Django 2.0.5 on 2018-06-02 14:30
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('manuels', '0019_auto_20180531_0815'),
|
||||
("manuels", "0019_auto_20180531_0815"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='teacher',
|
||||
options={'verbose_name': 'coordonnateur', 'verbose_name_plural': 'coordonnateurs'},
|
||||
name="teacher",
|
||||
options={
|
||||
"verbose_name": "coordonnateur",
|
||||
"verbose_name_plural": "coordonnateurs",
|
||||
},
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='book',
|
||||
name='teacher',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='manuels.Teacher', verbose_name='coordonnateur'),
|
||||
model_name="book",
|
||||
name="teacher",
|
||||
field=models.ForeignKey(
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
to="manuels.Teacher",
|
||||
verbose_name="coordonnateur",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='suppliesrequirement',
|
||||
name='teacher',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='manuels.Teacher', verbose_name='coordonnateur'),
|
||||
model_name="suppliesrequirement",
|
||||
name="teacher",
|
||||
field=models.ForeignKey(
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
to="manuels.Teacher",
|
||||
verbose_name="coordonnateur",
|
||||
),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -6,16 +6,24 @@ from django.db import migrations
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('manuels', '0020_auto_20180602_1630'),
|
||||
("manuels", "0020_auto_20180602_1630"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='editor',
|
||||
options={'ordering': ['name'], 'verbose_name': 'éditeur', 'verbose_name_plural': 'éditeurs'},
|
||||
name="editor",
|
||||
options={
|
||||
"ordering": ["name"],
|
||||
"verbose_name": "éditeur",
|
||||
"verbose_name_plural": "éditeurs",
|
||||
},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='teacher',
|
||||
options={'ordering': ['first_name'], 'verbose_name': 'coordonnateur', 'verbose_name_plural': 'coordonnateurs'},
|
||||
name="teacher",
|
||||
options={
|
||||
"ordering": ["first_name"],
|
||||
"verbose_name": "coordonnateur",
|
||||
"verbose_name_plural": "coordonnateurs",
|
||||
},
|
||||
),
|
||||
]
|
||||
|
|
|
@ -6,13 +6,15 @@ from django.db import migrations, models
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('manuels', '0021_auto_20180602_1638'),
|
||||
("manuels", "0021_auto_20180602_1638"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='teacher',
|
||||
name='has_confirmed_list',
|
||||
field=models.BooleanField(default=False, verbose_name='a confirmé les listes'),
|
||||
model_name="teacher",
|
||||
name="has_confirmed_list",
|
||||
field=models.BooleanField(
|
||||
default=False, verbose_name="a confirmé les listes"
|
||||
),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -1,19 +1,23 @@
|
|||
# Generated by Django 2.0.5 on 2018-06-04 16:27
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
import manuels.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('manuels', '0022_teacher_has_confirmed_list'),
|
||||
("manuels", "0022_teacher_has_confirmed_list"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='book',
|
||||
name='price',
|
||||
field=models.FloatField(validators=[manuels.models.positive_float_validator], verbose_name='prix'),
|
||||
model_name="book",
|
||||
name="price",
|
||||
field=models.FloatField(
|
||||
validators=[manuels.models.positive_float_validator],
|
||||
verbose_name="prix",
|
||||
),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -6,13 +6,13 @@ from django.db import migrations, models
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('manuels', '0023_auto_20180604_1827'),
|
||||
("manuels", "0023_auto_20180604_1827"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='book',
|
||||
name='other_editor',
|
||||
field=models.CharField(blank=True, max_length=100, verbose_name='préciser'),
|
||||
model_name="book",
|
||||
name="other_editor",
|
||||
field=models.CharField(blank=True, max_length=100, verbose_name="préciser"),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -6,13 +6,17 @@ from django.db import migrations, models
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('manuels', '0024_book_other_editor'),
|
||||
("manuels", "0024_book_other_editor"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='book',
|
||||
name='comments',
|
||||
field=models.TextField(blank=True, help_text='Ce message sera visible par la documentaliste.', verbose_name='commentaires'),
|
||||
model_name="book",
|
||||
name="comments",
|
||||
field=models.TextField(
|
||||
blank=True,
|
||||
help_text="Ce message sera visible par la documentaliste.",
|
||||
verbose_name="commentaires",
|
||||
),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -1,19 +1,25 @@
|
|||
# Generated by Django 2.0.6 on 2018-06-16 07:16
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
import manuels.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('manuels', '0025_auto_20180607_0746'),
|
||||
("manuels", "0025_auto_20180607_0746"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='book',
|
||||
name='isbn',
|
||||
field=models.CharField(help_text="Format attendu : 10 ou 13 chiffres, éventuellement séparés par des tirets et éventuellement suivis de la lettre <code>X</code>. La recherche sur Decitre ne fonctionnera qu'avec un code ISBN à13 chiffres (ou EAN)", max_length=20, validators=[manuels.models.isbn_validator], verbose_name='ISBN/EAN'),
|
||||
model_name="book",
|
||||
name="isbn",
|
||||
field=models.CharField(
|
||||
help_text="Format attendu : 10 ou 13 chiffres, éventuellement séparés par des tirets et éventuellement suivis de la lettre <code>X</code>. La recherche sur Decitre ne fonctionnera qu'avec un code ISBN à13 chiffres (ou EAN)",
|
||||
max_length=20,
|
||||
validators=[manuels.models.isbn_validator],
|
||||
verbose_name="ISBN/EAN",
|
||||
),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -6,28 +6,34 @@ from django.db import migrations, models
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('manuels', '0026_auto_20180616_0916'),
|
||||
("manuels", "0026_auto_20180616_0916"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='book',
|
||||
name='done',
|
||||
field=models.BooleanField(blank=True, default=False, verbose_name='Traité'),
|
||||
model_name="book",
|
||||
name="done",
|
||||
field=models.BooleanField(blank=True, default=False, verbose_name="Traité"),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='book',
|
||||
name='previously_acquired',
|
||||
field=models.BooleanField(choices=[(None, '------------'), (False, 'Non'), (True, 'Oui')], default=None, verbose_name="manuel acquis précédemment par l'élève"),
|
||||
model_name="book",
|
||||
name="previously_acquired",
|
||||
field=models.BooleanField(
|
||||
choices=[(None, "------------"), (False, "Non"), (True, "Oui")],
|
||||
default=None,
|
||||
verbose_name="manuel acquis précédemment par l'élève",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='suppliesrequirement',
|
||||
name='done',
|
||||
field=models.BooleanField(blank=True, default=False, verbose_name='Traité'),
|
||||
model_name="suppliesrequirement",
|
||||
name="done",
|
||||
field=models.BooleanField(blank=True, default=False, verbose_name="Traité"),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='teacher',
|
||||
name='has_confirmed_list',
|
||||
field=models.BooleanField(blank=True, default=False, verbose_name='a confirmé les listes'),
|
||||
model_name="teacher",
|
||||
name="has_confirmed_list",
|
||||
field=models.BooleanField(
|
||||
blank=True, default=False, verbose_name="a confirmé les listes"
|
||||
),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -6,23 +6,31 @@ from django.db import migrations, models
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('manuels', '0027_auto_20190401_2036'),
|
||||
("manuels", "0027_auto_20190401_2036"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='level',
|
||||
options={'ordering': ['order', 'name'], 'verbose_name': 'classe', 'verbose_name_plural': 'classes'},
|
||||
name="level",
|
||||
options={
|
||||
"ordering": ["order", "name"],
|
||||
"verbose_name": "classe",
|
||||
"verbose_name_plural": "classes",
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='book',
|
||||
name='consumable',
|
||||
field=models.BooleanField(default=False, help_text="Exemple : un cahier d'exercices est un consommable", verbose_name='consommable'),
|
||||
model_name="book",
|
||||
name="consumable",
|
||||
field=models.BooleanField(
|
||||
default=False,
|
||||
help_text="Exemple : un cahier d'exercices est un consommable",
|
||||
verbose_name="consommable",
|
||||
),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='level',
|
||||
name='order',
|
||||
field=models.IntegerField(default=0, verbose_name='ordre'),
|
||||
model_name="level",
|
||||
name="order",
|
||||
field=models.IntegerField(default=0, verbose_name="ordre"),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -6,13 +6,18 @@ from django.db import migrations, models
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('manuels', '0028_auto_20190406_1901'),
|
||||
("manuels", "0028_auto_20190406_1901"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='book',
|
||||
name='consumable',
|
||||
field=models.BooleanField(choices=[(None, '------------'), (False, 'Non'), (True, 'Oui')], default=None, help_text="Exemple : un cahier d'exercices est un consommable", verbose_name='consommable'),
|
||||
model_name="book",
|
||||
name="consumable",
|
||||
field=models.BooleanField(
|
||||
choices=[(None, "------------"), (False, "Non"), (True, "Oui")],
|
||||
default=None,
|
||||
help_text="Exemple : un cahier d'exercices est un consommable",
|
||||
verbose_name="consommable",
|
||||
),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -6,13 +6,13 @@ from django.db import migrations
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('manuels', '0029_auto_20190406_1904'),
|
||||
("manuels", "0029_auto_20190406_1904"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameField(
|
||||
model_name='suppliesrequirement',
|
||||
old_name='fields',
|
||||
new_name='field',
|
||||
model_name="suppliesrequirement",
|
||||
old_name="fields",
|
||||
new_name="field",
|
||||
),
|
||||
]
|
||||
|
|
|
@ -6,13 +6,13 @@ from django.db import migrations, models
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('manuels', '0030_auto_20190406_1912'),
|
||||
("manuels", "0030_auto_20190406_1912"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='suppliesrequirement',
|
||||
name='field',
|
||||
field=models.CharField(max_length=50, verbose_name='disciplines'),
|
||||
model_name="suppliesrequirement",
|
||||
name="field",
|
||||
field=models.CharField(max_length=50, verbose_name="disciplines"),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -6,13 +6,13 @@ from django.db import migrations, models
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('manuels', '0031_auto_20190406_1912'),
|
||||
("manuels", "0031_auto_20190406_1912"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='suppliesrequirement',
|
||||
name='field',
|
||||
field=models.CharField(max_length=50, verbose_name='discipline'),
|
||||
model_name="suppliesrequirement",
|
||||
name="field",
|
||||
field=models.CharField(max_length=50, verbose_name="discipline"),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -1,19 +1,25 @@
|
|||
# Generated by Django 2.2 on 2019-04-06 17:19
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
import manuels.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('manuels', '0032_auto_20190406_1913'),
|
||||
("manuels", "0032_auto_20190406_1913"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='book',
|
||||
name='isbn',
|
||||
field=models.CharField(help_text="Format attendu : 10 ou 13 chiffres, éventuellement séparés par des tirets et éventuellement suivis de la lettre <code>X</code>. La recherche sur Decitre ne fonctionnera qu'avec un code ISBN à 13 chiffres (ou EAN)", max_length=20, validators=[manuels.models.isbn_validator], verbose_name='ISBN/EAN'),
|
||||
model_name="book",
|
||||
name="isbn",
|
||||
field=models.CharField(
|
||||
help_text="Format attendu : 10 ou 13 chiffres, éventuellement séparés par des tirets et éventuellement suivis de la lettre <code>X</code>. La recherche sur Decitre ne fonctionnera qu'avec un code ISBN à 13 chiffres (ou EAN)",
|
||||
max_length=20,
|
||||
validators=[manuels.models.isbn_validator],
|
||||
verbose_name="ISBN/EAN",
|
||||
),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -6,21 +6,35 @@ from django.db import migrations, models
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('manuels', '0033_auto_20190406_1919'),
|
||||
("manuels", "0033_auto_20190406_1919"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='CommonSupply',
|
||||
name="CommonSupply",
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('created_at', models.DateTimeField(auto_now_add=True, verbose_name='créé le')),
|
||||
('updated_at', models.DateTimeField(auto_now=True, verbose_name='mis à jour le')),
|
||||
('name', models.CharField(max_length=200, verbose_name='nom')),
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"created_at",
|
||||
models.DateTimeField(auto_now_add=True, verbose_name="créé le"),
|
||||
),
|
||||
(
|
||||
"updated_at",
|
||||
models.DateTimeField(auto_now=True, verbose_name="mis à jour le"),
|
||||
),
|
||||
("name", models.CharField(max_length=200, verbose_name="nom")),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'fourniture commune',
|
||||
'verbose_name_plural': 'fournitures communes',
|
||||
"verbose_name": "fourniture commune",
|
||||
"verbose_name_plural": "fournitures communes",
|
||||
},
|
||||
),
|
||||
]
|
||||
|
|
|
@ -6,14 +6,14 @@ from django.db import migrations, models
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('manuels', '0034_commonsupply'),
|
||||
("manuels", "0034_commonsupply"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='commonsupply',
|
||||
name='order',
|
||||
field=models.IntegerField(default=0, verbose_name='ordre'),
|
||||
model_name="commonsupply",
|
||||
name="order",
|
||||
field=models.IntegerField(default=0, verbose_name="ordre"),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
||||
|
|
|
@ -6,12 +6,16 @@ from django.db import migrations
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('manuels', '0035_commonsupply_order'),
|
||||
("manuels", "0035_commonsupply_order"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='commonsupply',
|
||||
options={'ordering': ('order',), 'verbose_name': 'fourniture commune', 'verbose_name_plural': 'fournitures communes'},
|
||||
name="commonsupply",
|
||||
options={
|
||||
"ordering": ("order",),
|
||||
"verbose_name": "fourniture commune",
|
||||
"verbose_name_plural": "fournitures communes",
|
||||
},
|
||||
),
|
||||
]
|
||||
|
|
|
@ -8,18 +8,27 @@ from django.db import migrations
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('manuels', '0036_auto_20190615_1114'),
|
||||
("manuels", "0036_auto_20190615_1114"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='commonsupply',
|
||||
options={'ordering': ('order', 'name'), 'verbose_name': 'fourniture commune', 'verbose_name_plural': 'fournitures communes'},
|
||||
name="commonsupply",
|
||||
options={
|
||||
"ordering": ("order", "name"),
|
||||
"verbose_name": "fourniture commune",
|
||||
"verbose_name_plural": "fournitures communes",
|
||||
},
|
||||
),
|
||||
CITextExtension(),
|
||||
migrations.AlterField(
|
||||
model_name='teacher',
|
||||
name='email',
|
||||
field=django.contrib.postgres.fields.citext.CIEmailField(help_text='Utilisée pour vous transmettre votre lien personnel', max_length=254, unique=True, verbose_name='adresse email'),
|
||||
model_name="teacher",
|
||||
name="email",
|
||||
field=django.contrib.postgres.fields.citext.CIEmailField(
|
||||
help_text="Utilisée pour vous transmettre votre lien personnel",
|
||||
max_length=254,
|
||||
unique=True,
|
||||
verbose_name="adresse email",
|
||||
),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -1,19 +1,25 @@
|
|||
# Generated by Django 3.0.7 on 2021-05-10 06:54
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
import manuels.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('manuels', '0037_auto_20190627_1905'),
|
||||
("manuels", "0037_auto_20190627_1905"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='book',
|
||||
name='isbn',
|
||||
field=models.CharField(help_text="Format attendu : 10 ou 13 chiffres, éventuellement séparés par des tirets et éventuellement suivis de la lettre <code>X</code>. La recherche sur Decitre ne fonctionnera qu'avec un code ISBN à 13 chiffres (ou EAN)", max_length=20, validators=[manuels.models.isbn_validator], verbose_name='ISBN/EAN du manuel élève (hors specimen)'),
|
||||
model_name="book",
|
||||
name="isbn",
|
||||
field=models.CharField(
|
||||
help_text="Format attendu : 10 ou 13 chiffres, éventuellement séparés par des tirets et éventuellement suivis de la lettre <code>X</code>. La recherche sur Decitre ne fonctionnera qu'avec un code ISBN à 13 chiffres (ou EAN)",
|
||||
max_length=20,
|
||||
validators=[manuels.models.isbn_validator],
|
||||
verbose_name="ISBN/EAN du manuel élève (hors specimen)",
|
||||
),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -28,101 +28,105 @@ class BaseModel(models.Model):
|
|||
class Meta:
|
||||
abstract = True
|
||||
|
||||
created_at = models.DateTimeField('créé le', auto_now_add=True)
|
||||
updated_at = models.DateTimeField('mis à jour le', auto_now=True)
|
||||
created_at = models.DateTimeField("créé le", auto_now_add=True)
|
||||
updated_at = models.DateTimeField("mis à jour le", auto_now=True)
|
||||
|
||||
|
||||
def phone_validator(value):
|
||||
regex = re.compile(r'^\d{10}$')
|
||||
regex = re.compile(r"^\d{10}$")
|
||||
if not regex.match(value):
|
||||
raise ValidationError(
|
||||
"%(value)s n'est pas un numéro de téléphone valide. Format attendu : 10 chiffres.",
|
||||
params={'value': value}
|
||||
params={"value": value},
|
||||
)
|
||||
|
||||
|
||||
class Teacher(BaseModel):
|
||||
class Meta:
|
||||
verbose_name = 'coordonnateur'
|
||||
verbose_name_plural = 'coordonnateurs'
|
||||
ordering = ['first_name']
|
||||
verbose_name = "coordonnateur"
|
||||
verbose_name_plural = "coordonnateurs"
|
||||
ordering = ["first_name"]
|
||||
|
||||
uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
||||
first_name = models.CharField('prénom', max_length=100)
|
||||
last_name = models.CharField('nom', max_length=100)
|
||||
first_name = models.CharField("prénom", max_length=100)
|
||||
last_name = models.CharField("nom", max_length=100)
|
||||
phone_number = models.CharField(
|
||||
'numéro de téléphone',
|
||||
"numéro de téléphone",
|
||||
help_text="En cas d'urgence, 10 chiffres.",
|
||||
max_length=10,
|
||||
validators=[phone_validator]
|
||||
validators=[phone_validator],
|
||||
)
|
||||
email = CIEmailField(
|
||||
'adresse email',
|
||||
help_text='Utilisée pour vous transmettre votre lien personnel',
|
||||
unique=True
|
||||
"adresse email",
|
||||
help_text="Utilisée pour vous transmettre votre lien personnel",
|
||||
unique=True,
|
||||
)
|
||||
has_confirmed_list = models.BooleanField(
|
||||
'a confirmé les listes',
|
||||
default=False,
|
||||
blank=True
|
||||
"a confirmé les listes", default=False, blank=True
|
||||
)
|
||||
|
||||
def get_absolute_url(self):
|
||||
from django.urls import reverse
|
||||
return reverse('list_books', kwargs={'pk': str(self.pk)})
|
||||
|
||||
return reverse("list_books", kwargs={"pk": str(self.pk)})
|
||||
|
||||
@property
|
||||
def full_name(self):
|
||||
return f'{self.first_name} {self.last_name}'
|
||||
return f"{self.first_name} {self.last_name}"
|
||||
|
||||
def __str__(self):
|
||||
return self.full_name
|
||||
|
||||
def send_link(self, request):
|
||||
dest = self.email
|
||||
link = request.build_absolute_uri(reverse('list_books', args=[str(self.pk)]))
|
||||
link = request.build_absolute_uri(reverse("list_books", args=[str(self.pk)]))
|
||||
msg = EmailMultiAlternatives(
|
||||
subject='Gestion des manuels scolaires',
|
||||
body=f'Bonjour {self.first_name},\n'
|
||||
f'Voici votre lien pour la gestion des manuels scolaires : {link}',
|
||||
subject="Gestion des manuels scolaires",
|
||||
body=f"Bonjour {self.first_name},\n"
|
||||
f"Voici votre lien pour la gestion des manuels scolaires : {link}",
|
||||
from_email=settings.SERVER_EMAIL,
|
||||
to=[dest],
|
||||
)
|
||||
reply_to = [os.getenv('REPLY_TO')]
|
||||
reply_to = [os.getenv("REPLY_TO")]
|
||||
if reply_to:
|
||||
msg.reply_to = reply_to
|
||||
msg.attach_alternative(
|
||||
render_to_string('manuels/emails_link.html', {'link': link, 'teacher': self}), "text/html"
|
||||
render_to_string(
|
||||
"manuels/emails_link.html", {"link": link, "teacher": self}
|
||||
),
|
||||
"text/html",
|
||||
)
|
||||
msg.send()
|
||||
|
||||
def send_confirmation(self, request):
|
||||
dest = settings.LIBRARIAN_EMAILS
|
||||
link = request.build_absolute_uri(reverse('home_page'))
|
||||
link = request.build_absolute_uri(reverse("home_page"))
|
||||
msg = EmailMultiAlternatives(
|
||||
subject="Gestion des manuels scolaires - Confirmation d'un coordonnateur",
|
||||
body=f'Bonjour,\n'
|
||||
f'{self.first_name} a confirmé ses listes sur {link}',
|
||||
body=f"Bonjour,\n" f"{self.first_name} a confirmé ses listes sur {link}",
|
||||
from_email=settings.SERVER_EMAIL,
|
||||
to=dest,
|
||||
)
|
||||
reply_to = [os.getenv('REPLY_TO')]
|
||||
reply_to = [os.getenv("REPLY_TO")]
|
||||
if reply_to:
|
||||
msg.reply_to = reply_to
|
||||
msg.attach_alternative(
|
||||
render_to_string('manuels/emails_confirmation.html', {'link': link, 'teacher': self}), "text/html"
|
||||
render_to_string(
|
||||
"manuels/emails_confirmation.html", {"link": link, "teacher": self}
|
||||
),
|
||||
"text/html",
|
||||
)
|
||||
msg.send()
|
||||
|
||||
|
||||
class Level(BaseModel):
|
||||
class Meta:
|
||||
verbose_name = 'classe'
|
||||
verbose_name_plural = 'classes'
|
||||
ordering = ['order', 'name']
|
||||
verbose_name = "classe"
|
||||
verbose_name_plural = "classes"
|
||||
ordering = ["order", "name"]
|
||||
|
||||
name = models.CharField('nom', max_length=50)
|
||||
order = models.IntegerField('ordre', default=0)
|
||||
name = models.CharField("nom", max_length=50)
|
||||
order = models.IntegerField("ordre", default=0)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
@ -130,7 +134,10 @@ class Level(BaseModel):
|
|||
@property
|
||||
def non_acquired_consumables(self):
|
||||
if hasattr(self, "prefetched_books"):
|
||||
return filter(lambda book: book.consumable and not book.previously_acquired, self.prefetched_books)
|
||||
return filter(
|
||||
lambda book: book.consumable and not book.previously_acquired,
|
||||
self.prefetched_books,
|
||||
)
|
||||
return self.book_set.filter(consumable=True, previously_acquired=False)
|
||||
|
||||
@property
|
||||
|
@ -143,13 +150,17 @@ class Level(BaseModel):
|
|||
def non_acquired_consumable_price(self):
|
||||
if hasattr(self, "prefetched_books"):
|
||||
return sum(map(lambda book: book.price, self.non_acquired_consumables))
|
||||
return self.non_acquired_consumables.aggregate(Sum('price')).get(
|
||||
'price__sum', 0)
|
||||
return self.non_acquired_consumables.aggregate(Sum("price")).get(
|
||||
"price__sum", 0
|
||||
)
|
||||
|
||||
@property
|
||||
def non_acquired_books(self):
|
||||
if hasattr(self, "prefetched_books"):
|
||||
return filter(lambda book: not book.consumable and not book.previously_acquired, self.prefetched_books)
|
||||
return filter(
|
||||
lambda book: not book.consumable and not book.previously_acquired,
|
||||
self.prefetched_books,
|
||||
)
|
||||
return self.book_set.filter(consumable=False, previously_acquired=False)
|
||||
|
||||
@property
|
||||
|
@ -162,39 +173,41 @@ class Level(BaseModel):
|
|||
def non_acquired_book_price(self):
|
||||
if hasattr(self, "prefetched_books"):
|
||||
return sum(map(lambda book: book.price, self.non_acquired_books))
|
||||
return self.non_acquired_books.aggregate(Sum('price')).get(
|
||||
'price__sum', 0)
|
||||
return self.non_acquired_books.aggregate(Sum("price")).get("price__sum", 0)
|
||||
|
||||
@property
|
||||
def non_acquired_items(self):
|
||||
if hasattr(self, "prefetched_books"):
|
||||
return filter(lambda book: not book.previously_acquired, self.prefetched_books)
|
||||
return filter(
|
||||
lambda book: not book.previously_acquired, self.prefetched_books
|
||||
)
|
||||
return self.book_set.filter(previously_acquired=False)
|
||||
|
||||
@property
|
||||
def non_acquired_total_price(self):
|
||||
if hasattr(self, "prefetched_books"):
|
||||
return sum(map(lambda book: book.price, self.non_acquired_items))
|
||||
return self.non_acquired_items.aggregate(Sum('price')).get(
|
||||
'price__sum', 0)
|
||||
return self.non_acquired_items.aggregate(Sum("price")).get("price__sum", 0)
|
||||
|
||||
|
||||
class Editor(BaseModel):
|
||||
class Meta:
|
||||
verbose_name = 'éditeur'
|
||||
verbose_name_plural = 'éditeurs'
|
||||
ordering = ['name']
|
||||
verbose_name = "éditeur"
|
||||
verbose_name_plural = "éditeurs"
|
||||
ordering = ["name"]
|
||||
|
||||
name = models.CharField('nom', max_length=100)
|
||||
name = models.CharField("nom", max_length=100)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
def isbn_validator(value):
|
||||
regex = re.compile(r'(\d-?){10,13}X?')
|
||||
regex = re.compile(r"(\d-?){10,13}X?")
|
||||
if not regex.match(value):
|
||||
raise ValidationError("%(value)s n'est pas un ISBN valide.", params={'value': value})
|
||||
raise ValidationError(
|
||||
"%(value)s n'est pas un ISBN valide.", params={"value": value}
|
||||
)
|
||||
|
||||
|
||||
def positive_float_validator(value):
|
||||
|
@ -209,30 +222,36 @@ def positive_float_validator(value):
|
|||
|
||||
class Book(BaseModel):
|
||||
class Meta:
|
||||
verbose_name = 'livre'
|
||||
verbose_name_plural = 'livres'
|
||||
verbose_name = "livre"
|
||||
verbose_name_plural = "livres"
|
||||
|
||||
teacher = models.ForeignKey(verbose_name='coordonnateur', to=Teacher, on_delete=models.PROTECT, null=True)
|
||||
level = models.ForeignKey(verbose_name='classe', to=Level, on_delete=models.PROTECT, null=True)
|
||||
field = models.CharField('discipline', max_length=200)
|
||||
title = models.TextField('titre')
|
||||
authors = models.TextField('auteurs')
|
||||
editor = models.ForeignKey(verbose_name='éditeur', to=Editor, on_delete=models.PROTECT, null=True)
|
||||
other_editor = models.CharField(verbose_name='préciser', max_length=100, blank=True)
|
||||
publication_year = models.PositiveIntegerField('année de publication')
|
||||
teacher = models.ForeignKey(
|
||||
verbose_name="coordonnateur", to=Teacher, on_delete=models.PROTECT, null=True
|
||||
)
|
||||
level = models.ForeignKey(
|
||||
verbose_name="classe", to=Level, on_delete=models.PROTECT, null=True
|
||||
)
|
||||
field = models.CharField("discipline", max_length=200)
|
||||
title = models.TextField("titre")
|
||||
authors = models.TextField("auteurs")
|
||||
editor = models.ForeignKey(
|
||||
verbose_name="éditeur", to=Editor, on_delete=models.PROTECT, null=True
|
||||
)
|
||||
other_editor = models.CharField(verbose_name="préciser", max_length=100, blank=True)
|
||||
publication_year = models.PositiveIntegerField("année de publication")
|
||||
isbn = models.CharField(
|
||||
'ISBN/EAN du manuel élève (hors specimen)',
|
||||
"ISBN/EAN du manuel élève (hors specimen)",
|
||||
max_length=20,
|
||||
help_text="Format attendu : 10 ou 13 chiffres, éventuellement séparés par des tirets et éventuellement "
|
||||
"suivis de la lettre <code>X</code>. La recherche sur Decitre ne fonctionnera qu'avec un code ISBN à "
|
||||
"13 chiffres (ou EAN)",
|
||||
validators=[isbn_validator]
|
||||
"suivis de la lettre <code>X</code>. La recherche sur Decitre ne fonctionnera qu'avec un code ISBN à "
|
||||
"13 chiffres (ou EAN)",
|
||||
validators=[isbn_validator],
|
||||
)
|
||||
price = models.FloatField('prix', validators=[positive_float_validator])
|
||||
price = models.FloatField("prix", validators=[positive_float_validator])
|
||||
YES_NO_CHOICE = (
|
||||
(None, '------------'),
|
||||
(False, 'Non'),
|
||||
(True, 'Oui'),
|
||||
(None, "------------"),
|
||||
(False, "Non"),
|
||||
(True, "Oui"),
|
||||
)
|
||||
previously_acquired = models.BooleanField(
|
||||
"manuel acquis précédemment par l'élève",
|
||||
|
@ -240,18 +259,14 @@ class Book(BaseModel):
|
|||
blank=False,
|
||||
default=None,
|
||||
)
|
||||
done = models.BooleanField(
|
||||
'Traité',
|
||||
blank=True,
|
||||
default=False
|
||||
)
|
||||
done = models.BooleanField("Traité", blank=True, default=False)
|
||||
comments = models.TextField(
|
||||
'commentaires',
|
||||
"commentaires",
|
||||
blank=True,
|
||||
help_text="Ce message sera visible par la documentaliste."
|
||||
help_text="Ce message sera visible par la documentaliste.",
|
||||
)
|
||||
consumable = models.BooleanField(
|
||||
'consommable',
|
||||
"consommable",
|
||||
help_text="Exemple : un cahier d'exercices est un consommable",
|
||||
choices=YES_NO_CHOICE,
|
||||
blank=False,
|
||||
|
@ -261,32 +276,35 @@ class Book(BaseModel):
|
|||
@property
|
||||
def previously_acquired_text(self):
|
||||
if self.previously_acquired:
|
||||
return 'Oui'
|
||||
return "Oui"
|
||||
else:
|
||||
return 'Non'
|
||||
return "Non"
|
||||
|
||||
@property
|
||||
def consumable_text(self):
|
||||
if self.consumable:
|
||||
return 'Oui'
|
||||
return "Oui"
|
||||
else:
|
||||
return 'Non'
|
||||
return "Non"
|
||||
|
||||
def __str__(self):
|
||||
return f'{self.title} ({self.authors}) - {self.isbn}'
|
||||
return f"{self.title} ({self.authors}) - {self.isbn}"
|
||||
|
||||
def get_absolute_url(self):
|
||||
from django.urls import reverse
|
||||
return reverse('edit_book', kwargs={'teacher_pk': str(self.teacher.pk), 'pk': str(self.pk)})
|
||||
|
||||
return reverse(
|
||||
"edit_book", kwargs={"teacher_pk": str(self.teacher.pk), "pk": str(self.pk)}
|
||||
)
|
||||
|
||||
def update_from_decitre(self):
|
||||
decitre_data = self.fetch_from_decitre(self.isbn)
|
||||
self.title = decitre_data.get('title')
|
||||
self.authors = decitre_data.get('authors')
|
||||
self.price = decitre_data.get('price')
|
||||
self.publication_year = decitre_data.get('year')
|
||||
self.title = decitre_data.get("title")
|
||||
self.authors = decitre_data.get("authors")
|
||||
self.price = decitre_data.get("price")
|
||||
self.publication_year = decitre_data.get("year")
|
||||
|
||||
editor = decitre_data.get('editor')
|
||||
editor = decitre_data.get("editor")
|
||||
potential_editor = (
|
||||
Editor.objects.filter(name__iexact=editor).first()
|
||||
or Editor.objects.filter(name__icontains=editor).first()
|
||||
|
@ -302,31 +320,35 @@ class Book(BaseModel):
|
|||
|
||||
@property
|
||||
def decitre_url(self):
|
||||
isbn = self.isbn.strip().replace('-', '')
|
||||
isbn = self.isbn.strip().replace("-", "")
|
||||
if not validate_isbn(isbn) or len(isbn) == 10:
|
||||
return ""
|
||||
return f'https://www.decitre.fr/livres/{isbn}.html'
|
||||
return f"https://www.decitre.fr/livres/{isbn}.html"
|
||||
|
||||
@staticmethod
|
||||
def fetch_from_decitre(isbn: str):
|
||||
isbn = isbn.strip().replace('-', '')
|
||||
isbn = isbn.strip().replace("-", "")
|
||||
|
||||
if not validate_isbn(isbn):
|
||||
raise ISBNError({
|
||||
'error': "L'ISBN saisi n'est pas valide."
|
||||
})
|
||||
raise ISBNError({"error": "L'ISBN saisi n'est pas valide."})
|
||||
|
||||
if len(isbn) == 10:
|
||||
raise ISBNError({
|
||||
'error': "La recherche sur Decitre ne fonctionne qu'avec un ISBN 13 (ou EAN)."
|
||||
})
|
||||
raise ISBNError(
|
||||
{
|
||||
"error": "La recherche sur Decitre ne fonctionne qu'avec un ISBN 13 (ou EAN)."
|
||||
}
|
||||
)
|
||||
|
||||
try:
|
||||
res = requests.get(f'https://www.decitre.fr/livres/{isbn}.html', timeout=10)
|
||||
res = requests.get(f"https://www.decitre.fr/livres/{isbn}.html", timeout=10)
|
||||
except requests.exceptions.Timeout as exc:
|
||||
raise ISBNError({
|
||||
'error': "Decitre n'a pas répondu dans les temps. Message : {}".format(str(exc))
|
||||
})
|
||||
raise ISBNError(
|
||||
{
|
||||
"error": "Decitre n'a pas répondu dans les temps. Message : {}".format(
|
||||
str(exc)
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
try:
|
||||
res.raise_for_status()
|
||||
|
@ -334,89 +356,92 @@ class Book(BaseModel):
|
|||
message = (
|
||||
"Erreur lors de la recherche. Il se peut que le livre n'existe pas dans la base de connaissances "
|
||||
"de Decitre ou que vous ayez mal saisi l'ISBN. Vous pouvez toujours saisir "
|
||||
"les informations du livre à la main. Message : {}").format(str(exc))
|
||||
raise ISBNError({
|
||||
'error': message
|
||||
})
|
||||
"les informations du livre à la main. Message : {}"
|
||||
).format(str(exc))
|
||||
raise ISBNError({"error": message})
|
||||
|
||||
decitre_soup = bs4.BeautifulSoup(res.text, "html.parser")
|
||||
title = decitre_soup.select('h1.product-title')
|
||||
title = decitre_soup.select("h1.product-title")
|
||||
if title:
|
||||
title = title[0]
|
||||
if title.span:
|
||||
title.span.extract()
|
||||
title = title.get_text(strip=True)
|
||||
|
||||
authors = decitre_soup.select('.authors')
|
||||
authors = decitre_soup.select(".authors")
|
||||
if authors:
|
||||
authors = authors[0]
|
||||
authors = authors.get_text(strip=True)
|
||||
|
||||
price = decitre_soup.select('.fp-top--add-to-cart div.price span.final-price')
|
||||
price = decitre_soup.select(".fp-top--add-to-cart div.price span.final-price")
|
||||
if price:
|
||||
price = price[0]
|
||||
price = price.get_text().replace('€', '').replace(',', '.').strip()
|
||||
price = price.get_text().replace("€", "").replace(",", ".").strip()
|
||||
|
||||
year = None
|
||||
editor = None
|
||||
extra_info = decitre_soup.select('.informations-container')
|
||||
logger.debug('raw extra_info')
|
||||
extra_info = decitre_soup.select(".informations-container")
|
||||
logger.debug("raw extra_info")
|
||||
logger.debug(extra_info)
|
||||
if not extra_info:
|
||||
logger.debug('#fiche-technique')
|
||||
extra_info = decitre_soup.select('#fiche-technique')
|
||||
logger.debug('raw extra_info fiche technique')
|
||||
logger.debug("#fiche-technique")
|
||||
extra_info = decitre_soup.select("#fiche-technique")
|
||||
logger.debug("raw extra_info fiche technique")
|
||||
logger.debug(extra_info)
|
||||
|
||||
if extra_info:
|
||||
extra_info = extra_info[0].get_text(strip=True)
|
||||
logger.debug('extra_info')
|
||||
logger.debug("extra_info")
|
||||
logger.debug(extra_info)
|
||||
matches = re.search(
|
||||
r'Date de parution(?: :)?\d{2}/\d{2}/(?P<year>\d{4})Editeur(?: :)?(?P<editor>.+?)(?:ISBN|Collection)',
|
||||
extra_info)
|
||||
r"Date de parution(?: :)?\d{2}/\d{2}/(?P<year>\d{4})Editeur(?: :)?(?P<editor>.+?)(?:ISBN|Collection)",
|
||||
extra_info,
|
||||
)
|
||||
if matches:
|
||||
groups = matches.groupdict()
|
||||
year = groups.get('year')
|
||||
editor = groups.get('editor').strip()
|
||||
year = groups.get("year")
|
||||
editor = groups.get("editor").strip()
|
||||
|
||||
return {
|
||||
'title': title,
|
||||
'authors': authors,
|
||||
'isbn': isbn,
|
||||
'price': float(price) if price else None,
|
||||
'year': year,
|
||||
'editor': editor,
|
||||
"title": title,
|
||||
"authors": authors,
|
||||
"isbn": isbn,
|
||||
"price": float(price) if price else None,
|
||||
"year": year,
|
||||
"editor": editor,
|
||||
}
|
||||
|
||||
|
||||
class SuppliesRequirement(BaseModel):
|
||||
class Meta:
|
||||
verbose_name = 'demande de fournitures'
|
||||
verbose_name_plural = 'demandes de fournitures'
|
||||
verbose_name = "demande de fournitures"
|
||||
verbose_name_plural = "demandes de fournitures"
|
||||
|
||||
teacher = models.ForeignKey(verbose_name='coordonnateur', to=Teacher, on_delete=models.PROTECT, null=True)
|
||||
level = models.ForeignKey(verbose_name='classe', to=Level, on_delete=models.PROTECT, null=True)
|
||||
field = models.CharField('discipline', max_length=50)
|
||||
supplies = models.TextField('fournitures')
|
||||
done = models.BooleanField(
|
||||
'Traité',
|
||||
blank=True,
|
||||
default=False
|
||||
teacher = models.ForeignKey(
|
||||
verbose_name="coordonnateur", to=Teacher, on_delete=models.PROTECT, null=True
|
||||
)
|
||||
level = models.ForeignKey(
|
||||
verbose_name="classe", to=Level, on_delete=models.PROTECT, null=True
|
||||
)
|
||||
field = models.CharField("discipline", max_length=50)
|
||||
supplies = models.TextField("fournitures")
|
||||
done = models.BooleanField("Traité", blank=True, default=False)
|
||||
|
||||
def __str__(self):
|
||||
return f'{self.supplies} pour {self.level} ({self.teacher})'
|
||||
return f"{self.supplies} pour {self.level} ({self.teacher})"
|
||||
|
||||
|
||||
class CommonSupply(BaseModel):
|
||||
class Meta:
|
||||
verbose_name = 'fourniture commune'
|
||||
verbose_name_plural = 'fournitures communes'
|
||||
ordering = ('order', 'name',)
|
||||
verbose_name = "fourniture commune"
|
||||
verbose_name_plural = "fournitures communes"
|
||||
ordering = (
|
||||
"order",
|
||||
"name",
|
||||
)
|
||||
|
||||
name = models.CharField('nom', max_length=200)
|
||||
order = models.IntegerField('ordre')
|
||||
name = models.CharField("nom", max_length=200)
|
||||
order = models.IntegerField("ordre")
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
|
|
@ -112,4 +112,4 @@
|
|||
{% block end_js %}
|
||||
<script defer src="{% static 'manuels/no_book.js' %}"></script>
|
||||
<script defer src="{% static 'manuels/fetch-isbn.js' %}"></script>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -7,4 +7,4 @@
|
|||
<p class="mb-0">
|
||||
{{ object }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -28,4 +28,4 @@
|
|||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -144,4 +144,4 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -8,4 +8,4 @@
|
|||
<li>{{ supply.name }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -4,4 +4,3 @@ from django.test import TestCase
|
|||
class MyTestCase(TestCase):
|
||||
def test_something(self):
|
||||
self.assertEqual(True, False)
|
||||
|
||||
|
|
|
@ -1,24 +1,57 @@
|
|||
from django.conf import settings
|
||||
from django.urls import path, include
|
||||
from django.urls import include, path
|
||||
|
||||
from manuels.views import AddBookView, ListBooksView, clear_teacher_view, AddSuppliesView, EditBookView, \
|
||||
EditSuppliesView, DeleteBookView, DeleteSuppliesView, ConfirmTeacherView, isbn_api
|
||||
from manuels.views import (
|
||||
AddBookView,
|
||||
AddSuppliesView,
|
||||
ConfirmTeacherView,
|
||||
DeleteBookView,
|
||||
DeleteSuppliesView,
|
||||
EditBookView,
|
||||
EditSuppliesView,
|
||||
ListBooksView,
|
||||
clear_teacher_view,
|
||||
isbn_api,
|
||||
)
|
||||
|
||||
urlpatterns = [
|
||||
path('teacher/<uuid:pk>/add_book', AddBookView.as_view(), name='add_book'),
|
||||
path('teacher/<uuid:pk>/add_supplies', AddSuppliesView.as_view(), name='add_supplies'),
|
||||
path('teacher/<uuid:pk>', ListBooksView.as_view(), name='list_books'),
|
||||
path('teacher/<uuid:teacher_pk>/book/<int:pk>', EditBookView.as_view(), name='edit_book'),
|
||||
path('teacher/<uuid:teacher_pk>/book/<int:pk>/delete', DeleteBookView.as_view(), name='delete_book'),
|
||||
path('teacher/<uuid:teacher_pk>/supplies/<int:pk>', EditSuppliesView.as_view(), name='edit_supplies'),
|
||||
path('teacher/<uuid:teacher_pk>/supplies/<int:pk>/delete', DeleteSuppliesView.as_view(), name='delete_supplies'),
|
||||
path('teacher/<uuid:pk>/confirm', ConfirmTeacherView.as_view(), name='confirm_teacher'),
|
||||
path('clear', clear_teacher_view, name='clear_teacher'),
|
||||
path('isbn_api/<str:isbn>', isbn_api, name='isbn_api'),
|
||||
path("teacher/<uuid:pk>/add_book", AddBookView.as_view(), name="add_book"),
|
||||
path(
|
||||
"teacher/<uuid:pk>/add_supplies", AddSuppliesView.as_view(), name="add_supplies"
|
||||
),
|
||||
path("teacher/<uuid:pk>", ListBooksView.as_view(), name="list_books"),
|
||||
path(
|
||||
"teacher/<uuid:teacher_pk>/book/<int:pk>",
|
||||
EditBookView.as_view(),
|
||||
name="edit_book",
|
||||
),
|
||||
path(
|
||||
"teacher/<uuid:teacher_pk>/book/<int:pk>/delete",
|
||||
DeleteBookView.as_view(),
|
||||
name="delete_book",
|
||||
),
|
||||
path(
|
||||
"teacher/<uuid:teacher_pk>/supplies/<int:pk>",
|
||||
EditSuppliesView.as_view(),
|
||||
name="edit_supplies",
|
||||
),
|
||||
path(
|
||||
"teacher/<uuid:teacher_pk>/supplies/<int:pk>/delete",
|
||||
DeleteSuppliesView.as_view(),
|
||||
name="delete_supplies",
|
||||
),
|
||||
path(
|
||||
"teacher/<uuid:pk>/confirm",
|
||||
ConfirmTeacherView.as_view(),
|
||||
name="confirm_teacher",
|
||||
),
|
||||
path("clear", clear_teacher_view, name="clear_teacher"),
|
||||
path("isbn_api/<str:isbn>", isbn_api, name="isbn_api"),
|
||||
]
|
||||
|
||||
if settings.DEBUG:
|
||||
import debug_toolbar
|
||||
|
||||
urlpatterns = [
|
||||
path('__debug__/', include(debug_toolbar.urls)),
|
||||
path("__debug__/", include(debug_toolbar.urls)),
|
||||
] + urlpatterns
|
||||
|
|
|
@ -2,7 +2,7 @@ def validate_isbn(isbn):
|
|||
_sum = 0
|
||||
if len(isbn) == 10:
|
||||
for i, digit in enumerate(isbn):
|
||||
if digit == 'X':
|
||||
if digit == "X":
|
||||
digit = 10
|
||||
else:
|
||||
digit = int(digit)
|
||||
|
|
161
manuels/views.py
161
manuels/views.py
|
@ -8,10 +8,10 @@ from django.http import HttpResponseRedirect, JsonResponse
|
|||
from django.shortcuts import redirect
|
||||
from django.urls import reverse
|
||||
from django.views.decorators.cache import cache_page
|
||||
from django.views.generic import CreateView, UpdateView, DeleteView, TemplateView
|
||||
from django.views.generic import CreateView, DeleteView, TemplateView, UpdateView
|
||||
|
||||
from manuels.forms import AddBookForm, AddSuppliesForm, EditBookForm, EditSuppliesForm
|
||||
from manuels.models import Teacher, Book, SuppliesRequirement, CommonSupply, ISBNError
|
||||
from manuels.models import Book, CommonSupply, ISBNError, SuppliesRequirement, Teacher
|
||||
from manuels.utils import validate_isbn
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
@ -19,13 +19,13 @@ logger = logging.getLogger(__name__)
|
|||
|
||||
class HomePageView(CreateView):
|
||||
model = Teacher
|
||||
fields = ['first_name', 'last_name', 'phone_number', 'email']
|
||||
template_name = 'manuels/home_page.html'
|
||||
fields = ["first_name", "last_name", "phone_number", "email"]
|
||||
template_name = "manuels/home_page.html"
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
teacher_pk = request.session.get('teacher_pk')
|
||||
teacher_pk = request.session.get("teacher_pk")
|
||||
if teacher_pk:
|
||||
return redirect('list_books', pk=teacher_pk)
|
||||
return redirect("list_books", pk=teacher_pk)
|
||||
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
||||
|
@ -37,26 +37,31 @@ class HomePageView(CreateView):
|
|||
|
||||
class BaseTeacherView:
|
||||
teacher = None
|
||||
teacher_field = 'pk'
|
||||
teacher_field = "pk"
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.teacher = Teacher.objects.filter(pk=self.kwargs[self.teacher_field]).first()
|
||||
self.teacher = Teacher.objects.filter(
|
||||
pk=self.kwargs[self.teacher_field]
|
||||
).first()
|
||||
if not self.teacher:
|
||||
messages.warning(request, "Impossible de trouver le coordonnateur demandé. Si vous pensez que ceci est "
|
||||
"une erreur, merci de vous adresser à votre documentaliste.")
|
||||
return redirect('clear_teacher')
|
||||
request.session['teacher_pk'] = str(self.teacher.pk)
|
||||
messages.warning(
|
||||
request,
|
||||
"Impossible de trouver le coordonnateur demandé. Si vous pensez que ceci est "
|
||||
"une erreur, merci de vous adresser à votre documentaliste.",
|
||||
)
|
||||
return redirect("clear_teacher")
|
||||
request.session["teacher_pk"] = str(self.teacher.pk)
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data()
|
||||
context['teacher'] = self.teacher
|
||||
context["teacher"] = self.teacher
|
||||
|
||||
return context
|
||||
|
||||
|
||||
class ListBooksView(BaseTeacherView, TemplateView):
|
||||
template_name = 'manuels/list_books_supplies.html'
|
||||
template_name = "manuels/list_books_supplies.html"
|
||||
|
||||
|
||||
class ItemView(BaseTeacherView):
|
||||
|
@ -66,79 +71,80 @@ class ItemView(BaseTeacherView):
|
|||
success_target = None
|
||||
message_template = None
|
||||
verb = None
|
||||
button_class = 'primary'
|
||||
button_icon = 'fas fa-check-circle'
|
||||
button_class = "primary"
|
||||
button_icon = "fas fa-check-circle"
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
response = super().dispatch(request, *args, **kwargs)
|
||||
if self.teacher and self.teacher.has_confirmed_list:
|
||||
messages.error(request, "Vous avez déjà confirmé vos listes. Il n'est plus possible de les modifier.")
|
||||
return redirect('list_books', pk=self.teacher.pk)
|
||||
messages.error(
|
||||
request,
|
||||
"Vous avez déjà confirmé vos listes. Il n'est plus possible de les modifier.",
|
||||
)
|
||||
return redirect("list_books", pk=self.teacher.pk)
|
||||
return response
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context['item'] = self.item_text
|
||||
context['item_plural'] = self.item_text_plural
|
||||
context['message_template'] = self.message_template
|
||||
context['verb'] = self.verb
|
||||
context['button_class'] = self.button_class
|
||||
context['button_icon'] = self.button_icon
|
||||
context["item"] = self.item_text
|
||||
context["item_plural"] = self.item_text_plural
|
||||
context["message_template"] = self.message_template
|
||||
context["verb"] = self.verb
|
||||
context["button_class"] = self.button_class
|
||||
context["button_icon"] = self.button_icon
|
||||
return context
|
||||
|
||||
def get_initial(self):
|
||||
return {
|
||||
'teacher': self.teacher
|
||||
}
|
||||
return {"teacher": self.teacher}
|
||||
|
||||
def get_form(self, form_class=None):
|
||||
form = super().get_form(form_class)
|
||||
form.fields['teacher'].queryset = Teacher.objects.filter(pk=self.teacher.pk)
|
||||
form.fields["teacher"].queryset = Teacher.objects.filter(pk=self.teacher.pk)
|
||||
return form
|
||||
|
||||
|
||||
class AddItemView(ItemView, CreateView):
|
||||
verb = 'Ajouter'
|
||||
button_icon = 'fas fa-plus-circle'
|
||||
verb = "Ajouter"
|
||||
button_icon = "fas fa-plus-circle"
|
||||
|
||||
def get_success_url(self):
|
||||
if self.add_another:
|
||||
return reverse(self.success_target, args=[str(self.teacher.pk)])
|
||||
else:
|
||||
return reverse('list_books', args=[str(self.teacher.pk)])
|
||||
return reverse("list_books", args=[str(self.teacher.pk)])
|
||||
|
||||
def form_valid(self, form):
|
||||
self.add_another = form.cleaned_data['add_another']
|
||||
self.add_another = form.cleaned_data["add_another"]
|
||||
return HttpResponseRedirect(self.get_success_url())
|
||||
|
||||
|
||||
class BookView:
|
||||
model = Book
|
||||
success_target = 'add_book'
|
||||
item_text = 'un livre'
|
||||
item_text_plural = 'livres'
|
||||
success_target = "add_book"
|
||||
item_text = "un livre"
|
||||
item_text_plural = "livres"
|
||||
|
||||
|
||||
class AddBookView(BookView, AddItemView):
|
||||
form_class = AddBookForm
|
||||
template_name = 'manuels/add_book.html'
|
||||
template_name = "manuels/add_book.html"
|
||||
|
||||
def form_valid(self, form: AddBookForm):
|
||||
for level in form.cleaned_data['levels']:
|
||||
for level in form.cleaned_data["levels"]:
|
||||
book = Book.objects.create(
|
||||
teacher=form.cleaned_data['teacher'],
|
||||
teacher=form.cleaned_data["teacher"],
|
||||
level=level,
|
||||
field=form.cleaned_data['field'],
|
||||
title=form.cleaned_data['title'],
|
||||
authors=form.cleaned_data['authors'],
|
||||
editor=form.cleaned_data['editor'],
|
||||
other_editor=form.cleaned_data['other_editor'],
|
||||
publication_year=form.cleaned_data['publication_year'],
|
||||
isbn=form.cleaned_data['isbn'],
|
||||
price=form.cleaned_data['price'],
|
||||
previously_acquired=form.cleaned_data['previously_acquired'],
|
||||
comments=form.cleaned_data['comments'],
|
||||
consumable=form.cleaned_data['consumable'],
|
||||
field=form.cleaned_data["field"],
|
||||
title=form.cleaned_data["title"],
|
||||
authors=form.cleaned_data["authors"],
|
||||
editor=form.cleaned_data["editor"],
|
||||
other_editor=form.cleaned_data["other_editor"],
|
||||
publication_year=form.cleaned_data["publication_year"],
|
||||
isbn=form.cleaned_data["isbn"],
|
||||
price=form.cleaned_data["price"],
|
||||
previously_acquired=form.cleaned_data["previously_acquired"],
|
||||
comments=form.cleaned_data["comments"],
|
||||
consumable=form.cleaned_data["consumable"],
|
||||
)
|
||||
messages.success(self.request, f'"{book}" a été ajouté.')
|
||||
|
||||
|
@ -147,28 +153,28 @@ class AddBookView(BookView, AddItemView):
|
|||
|
||||
class SuppliesView:
|
||||
model = SuppliesRequirement
|
||||
success_target = 'add_supplies'
|
||||
item_text = 'des fournitures'
|
||||
item_text_plural = 'fournitures'
|
||||
success_target = "add_supplies"
|
||||
item_text = "des fournitures"
|
||||
item_text_plural = "fournitures"
|
||||
|
||||
|
||||
class AddSuppliesView(SuppliesView, AddItemView):
|
||||
form_class = AddSuppliesForm
|
||||
message_template = 'manuels/supplies_message.html'
|
||||
template_name = 'manuels/add_supplies.html'
|
||||
message_template = "manuels/supplies_message.html"
|
||||
template_name = "manuels/add_supplies.html"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context['common_supplies'] = CommonSupply.objects.all()
|
||||
context["common_supplies"] = CommonSupply.objects.all()
|
||||
return context
|
||||
|
||||
def form_valid(self, form: AddBookForm):
|
||||
for level in form.cleaned_data['levels']:
|
||||
for level in form.cleaned_data["levels"]:
|
||||
supplies = SuppliesRequirement.objects.create(
|
||||
teacher=form.cleaned_data['teacher'],
|
||||
teacher=form.cleaned_data["teacher"],
|
||||
level=level,
|
||||
field=form.cleaned_data['field'],
|
||||
supplies=form.cleaned_data['supplies'],
|
||||
field=form.cleaned_data["field"],
|
||||
supplies=form.cleaned_data["supplies"],
|
||||
)
|
||||
messages.success(self.request, f'"{supplies}" a été ajouté.')
|
||||
|
||||
|
@ -176,46 +182,46 @@ class AddSuppliesView(SuppliesView, AddItemView):
|
|||
|
||||
|
||||
class EditItemView(ItemView, UpdateView):
|
||||
teacher_field = 'teacher_pk'
|
||||
teacher_field = "teacher_pk"
|
||||
item_text = None
|
||||
item_text_plural = None
|
||||
message_template = None
|
||||
verb = 'Modifier'
|
||||
verb = "Modifier"
|
||||
|
||||
def get_queryset(self):
|
||||
return self.model.objects.filter(teacher=self.teacher)
|
||||
|
||||
def get_success_url(self):
|
||||
messages.success(self.request, f'"{self.object}" a été modifié.')
|
||||
return reverse('list_books', args=[str(self.teacher.pk)])
|
||||
return reverse("list_books", args=[str(self.teacher.pk)])
|
||||
|
||||
|
||||
class EditBookView(BookView, EditItemView):
|
||||
form_class = EditBookForm
|
||||
template_name = 'manuels/add_book.html'
|
||||
template_name = "manuels/add_book.html"
|
||||
|
||||
|
||||
class EditSuppliesView(SuppliesView, EditItemView):
|
||||
form_class = EditSuppliesForm
|
||||
template_name = 'manuels/add_supplies.html'
|
||||
template_name = "manuels/add_supplies.html"
|
||||
|
||||
|
||||
class DeleteItemView(ItemView, DeleteView):
|
||||
teacher_field = 'teacher_pk'
|
||||
teacher_field = "teacher_pk"
|
||||
item_text = None
|
||||
item_text_plural = None
|
||||
message_template = 'manuels/confirm_delete.html'
|
||||
verb = 'Supprimer'
|
||||
button_class = 'danger'
|
||||
button_icon = 'fas fa-trash'
|
||||
template_name = 'manuels/add_supplies.html'
|
||||
message_template = "manuels/confirm_delete.html"
|
||||
verb = "Supprimer"
|
||||
button_class = "danger"
|
||||
button_icon = "fas fa-trash"
|
||||
template_name = "manuels/add_supplies.html"
|
||||
|
||||
def get_queryset(self):
|
||||
return self.model.objects.filter(teacher=self.teacher)
|
||||
|
||||
def get_success_url(self):
|
||||
messages.success(self.request, f'"{self.object}" a été supprimé.')
|
||||
return reverse('list_books', args=[str(self.teacher.pk)])
|
||||
return reverse("list_books", args=[str(self.teacher.pk)])
|
||||
|
||||
|
||||
class DeleteBookView(BookView, DeleteItemView):
|
||||
|
@ -227,22 +233,25 @@ class DeleteSuppliesView(SuppliesView, DeleteItemView):
|
|||
|
||||
|
||||
def clear_teacher_view(request):
|
||||
if 'teacher_pk' in request.session:
|
||||
del request.session['teacher_pk']
|
||||
return redirect('home_page')
|
||||
if "teacher_pk" in request.session:
|
||||
del request.session["teacher_pk"]
|
||||
return redirect("home_page")
|
||||
|
||||
|
||||
class ConfirmTeacherView(BaseTeacherView, UpdateView):
|
||||
model = Teacher
|
||||
fields = []
|
||||
template_name = 'manuels/confirm_teacher.html'
|
||||
template_name = "manuels/confirm_teacher.html"
|
||||
|
||||
def form_valid(self, form):
|
||||
response = super().form_valid(form)
|
||||
self.object.has_confirmed_list = True
|
||||
self.object.save()
|
||||
self.object.send_confirmation(request=self.request)
|
||||
messages.success(self.request, "Vos listes ont été validées. Votre documentaliste a été notifiée par email.")
|
||||
messages.success(
|
||||
self.request,
|
||||
"Vos listes ont été validées. Votre documentaliste a été notifiée par email.",
|
||||
)
|
||||
return response
|
||||
|
||||
|
||||
|
|
|
@ -13,9 +13,9 @@ https://docs.djangoproject.com/en/2.0/ref/settings/
|
|||
import os
|
||||
from pathlib import Path
|
||||
|
||||
import environ
|
||||
from django.contrib.messages import constants as messages
|
||||
|
||||
import environ
|
||||
BASE_DIR = Path(__file__).resolve(strict=True).parent.parent
|
||||
|
||||
env = environ.Env(
|
||||
|
@ -27,8 +27,8 @@ env = environ.Env(
|
|||
SERVER_EMAIL=str,
|
||||
AUTHORIZED_EMAILS=(list, []),
|
||||
LIBRARIAN_EMAILS=(list, []),
|
||||
MAILGUN_ACCESS_KEY=(str, ''),
|
||||
MAILGUN_SERVER_NAME=(str, ''),
|
||||
MAILGUN_ACCESS_KEY=(str, ""),
|
||||
MAILGUN_SERVER_NAME=(str, ""),
|
||||
)
|
||||
env_file = os.getenv("ENV_FILE", None)
|
||||
if env_file:
|
||||
|
@ -39,36 +39,35 @@ if env_file:
|
|||
SECRET_KEY = env("SECRET_KEY")
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = env('DJANGO_ENV') == 'dev'
|
||||
DEBUG = env("DJANGO_ENV") == "dev"
|
||||
|
||||
ALLOWED_HOSTS = ['web', '127.0.0.1']
|
||||
ALLOWED_HOSTS = ["web", "127.0.0.1"]
|
||||
if DEBUG:
|
||||
ALLOWED_HOSTS.extend([
|
||||
'localhost',
|
||||
env('CURRENT_IP')
|
||||
])
|
||||
ALLOWED_HOSTS.extend(["localhost", env("CURRENT_IP")])
|
||||
ALLOWED_HOSTS.extend(env("HOST"))
|
||||
|
||||
ADMINS = [('Gabriel', env('ADMIN_EMAIL')), ]
|
||||
SERVER_EMAIL = env('SERVER_EMAIL')
|
||||
EMAIL_SUBJECT_PREFIX = '[Manuels] '
|
||||
ADMINS = [
|
||||
("Gabriel", env("ADMIN_EMAIL")),
|
||||
]
|
||||
SERVER_EMAIL = env("SERVER_EMAIL")
|
||||
EMAIL_SUBJECT_PREFIX = "[Manuels] "
|
||||
|
||||
AUTHORIZED_EMAILS = env('AUTHORIZED_EMAILS')
|
||||
LIBRARIAN_EMAILS = env('LIBRARIAN_EMAILS')
|
||||
AUTHORIZED_EMAILS = env("AUTHORIZED_EMAILS")
|
||||
LIBRARIAN_EMAILS = env("LIBRARIAN_EMAILS")
|
||||
|
||||
# Application definition
|
||||
|
||||
INSTALLED_APPS = [
|
||||
'django.contrib.admin',
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'anymail',
|
||||
'bootstrap4',
|
||||
'manuels',
|
||||
'import_export',
|
||||
"django.contrib.admin",
|
||||
"django.contrib.auth",
|
||||
"django.contrib.contenttypes",
|
||||
"django.contrib.sessions",
|
||||
"django.contrib.messages",
|
||||
"django.contrib.staticfiles",
|
||||
"anymail",
|
||||
"bootstrap4",
|
||||
"manuels",
|
||||
"import_export",
|
||||
]
|
||||
|
||||
if DEBUG:
|
||||
|
@ -77,47 +76,47 @@ if DEBUG:
|
|||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
'whitenoise.middleware.WhiteNoiseMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
"django.middleware.security.SecurityMiddleware",
|
||||
"whitenoise.middleware.WhiteNoiseMiddleware",
|
||||
"django.contrib.sessions.middleware.SessionMiddleware",
|
||||
"django.middleware.common.CommonMiddleware",
|
||||
"django.middleware.csrf.CsrfViewMiddleware",
|
||||
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
||||
"django.contrib.messages.middleware.MessageMiddleware",
|
||||
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
||||
]
|
||||
|
||||
if DEBUG:
|
||||
MIDDLEWARE.insert(0, "debug_toolbar.middleware.DebugToolbarMiddleware")
|
||||
|
||||
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
|
||||
STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"
|
||||
|
||||
ROOT_URLCONF = 'manuels_collection.urls'
|
||||
ROOT_URLCONF = "manuels_collection.urls"
|
||||
|
||||
TEMPLATES = [
|
||||
{
|
||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||
'DIRS': [],
|
||||
'APP_DIRS': True,
|
||||
'OPTIONS': {
|
||||
'context_processors': [
|
||||
'django.template.context_processors.debug',
|
||||
'django.template.context_processors.request',
|
||||
'django.contrib.auth.context_processors.auth',
|
||||
'django.contrib.messages.context_processors.messages',
|
||||
'manuels.context_processors.authorized_mails'
|
||||
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
||||
"DIRS": [],
|
||||
"APP_DIRS": True,
|
||||
"OPTIONS": {
|
||||
"context_processors": [
|
||||
"django.template.context_processors.debug",
|
||||
"django.template.context_processors.request",
|
||||
"django.contrib.auth.context_processors.auth",
|
||||
"django.contrib.messages.context_processors.messages",
|
||||
"manuels.context_processors.authorized_mails",
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
WSGI_APPLICATION = 'manuels_collection.wsgi.application'
|
||||
WSGI_APPLICATION = "manuels_collection.wsgi.application"
|
||||
|
||||
# Database
|
||||
# https://docs.djangoproject.com/en/2.0/ref/settings/#databases
|
||||
default_db_path = BASE_DIR / 'db.sqlite3'
|
||||
default_db_path = BASE_DIR / "db.sqlite3"
|
||||
DATABASES = {
|
||||
'default': env.db(default=f'sqlite:///{default_db_path}'),
|
||||
"default": env.db(default=f"sqlite:///{default_db_path}"),
|
||||
}
|
||||
|
||||
# Password validation
|
||||
|
@ -125,16 +124,16 @@ DATABASES = {
|
|||
|
||||
AUTH_PASSWORD_VALIDATORS = [
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
||||
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
||||
"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
||||
"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
||||
"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
|
||||
},
|
||||
]
|
||||
|
||||
|
@ -145,9 +144,9 @@ INTERNAL_IPS = [
|
|||
# Internationalization
|
||||
# https://docs.djangoproject.com/en/2.0/topics/i18n/
|
||||
|
||||
LANGUAGE_CODE = 'fr-fr'
|
||||
LANGUAGE_CODE = "fr-fr"
|
||||
|
||||
TIME_ZONE = 'Europe/Paris'
|
||||
TIME_ZONE = "Europe/Paris"
|
||||
|
||||
USE_I18N = True
|
||||
|
||||
|
@ -156,53 +155,47 @@ USE_L10N = True
|
|||
USE_TZ = True
|
||||
|
||||
# Logging
|
||||
LOG_LEVEL = 'DEBUG' if DEBUG else 'INFO'
|
||||
LOG_LEVEL = "DEBUG" if DEBUG else "INFO"
|
||||
LOGGING = {
|
||||
'version': 1,
|
||||
'disable_existing_loggers': False,
|
||||
'formatters': {
|
||||
'verbose': {
|
||||
'format': '[%(asctime)s] [%(process)d] [%(levelname)s] %(module)s - %(message)s'
|
||||
"version": 1,
|
||||
"disable_existing_loggers": False,
|
||||
"formatters": {
|
||||
"verbose": {
|
||||
"format": "[%(asctime)s] [%(process)d] [%(levelname)s] %(module)s - %(message)s"
|
||||
},
|
||||
},
|
||||
'handlers': {
|
||||
'console': {
|
||||
'class': 'logging.StreamHandler',
|
||||
'formatter': 'verbose'
|
||||
},
|
||||
"handlers": {
|
||||
"console": {"class": "logging.StreamHandler", "formatter": "verbose"},
|
||||
},
|
||||
'loggers': {
|
||||
'manuels': {
|
||||
'handlers': ['console'],
|
||||
'level': LOG_LEVEL
|
||||
},
|
||||
"loggers": {
|
||||
"manuels": {"handlers": ["console"], "level": LOG_LEVEL},
|
||||
},
|
||||
}
|
||||
|
||||
# Static files (CSS, JavaScript, Images)
|
||||
# https://docs.djangoproject.com/en/2.0/howto/static-files/
|
||||
|
||||
STATIC_URL = '/static/'
|
||||
STATIC_ROOT = BASE_DIR / 'staticfiles'
|
||||
STATIC_URL = "/static/"
|
||||
STATIC_ROOT = BASE_DIR / "staticfiles"
|
||||
|
||||
LOGIN_REDIRECT_URL = 'rooms-list'
|
||||
LOGIN_REDIRECT_URL = "rooms-list"
|
||||
|
||||
ANYMAIL = {
|
||||
"MAILGUN_API_KEY": env('MAILGUN_ACCESS_KEY'),
|
||||
"MAILGUN_SENDER_DOMAIN": env('MAILGUN_SERVER_NAME'),
|
||||
"MAILGUN_API_KEY": env("MAILGUN_ACCESS_KEY"),
|
||||
"MAILGUN_SENDER_DOMAIN": env("MAILGUN_SERVER_NAME"),
|
||||
}
|
||||
|
||||
EMAIL_BACKEND = 'anymail.backends.mailgun.EmailBackend'
|
||||
EMAIL_BACKEND = "anymail.backends.mailgun.EmailBackend"
|
||||
|
||||
MESSAGE_TAGS = {
|
||||
messages.ERROR: 'danger',
|
||||
messages.ERROR: "danger",
|
||||
}
|
||||
|
||||
CACHES = {
|
||||
'default': {
|
||||
'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
|
||||
'LOCATION': 'manuels_cache',
|
||||
"default": {
|
||||
"BACKEND": "django.core.cache.backends.db.DatabaseCache",
|
||||
"LOCATION": "manuels_cache",
|
||||
}
|
||||
}
|
||||
|
||||
DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
|
||||
DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
|
||||
|
|
|
@ -14,14 +14,14 @@ Including another URLconf
|
|||
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
||||
"""
|
||||
from django.contrib import admin
|
||||
from django.urls import path, include
|
||||
from django.urls import include, path
|
||||
|
||||
from manuels.views import HomePageView
|
||||
|
||||
admin.site.site_header = 'Manuels scolaires - Administration'
|
||||
admin.site.site_header = "Manuels scolaires - Administration"
|
||||
|
||||
urlpatterns = [
|
||||
path('admin/', admin.site.urls),
|
||||
path('', HomePageView.as_view(), name='home_page'),
|
||||
path('', include('manuels.urls')),
|
||||
path("admin/", admin.site.urls),
|
||||
path("", HomePageView.as_view(), name="home_page"),
|
||||
path("", include("manuels.urls")),
|
||||
]
|
||||
|
|
Loading…
Reference in a new issue