commit aa48b6411f4db0f164d2d8cce339aa10a495ee8a Author: Claude Paroz Date: Sat May 26 16:01:04 2018 +0200 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d558c29 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +__pycache__ +db.sqlite3 +common/local_settings.py diff --git a/common/__init__.py b/common/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/common/settings.py b/common/settings.py new file mode 100644 index 0000000..af11def --- /dev/null +++ b/common/settings.py @@ -0,0 +1,76 @@ +""" +Django settings for recettes project. +""" + +import os + +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + +DEBUG = True + +ALLOWED_HOSTS = [] + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'recette', +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + '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', +] + +ROOT_URLCONF = 'common.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [os.path.join(BASE_DIR, 'templates')], + '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', + ], + }, + }, +] + +WSGI_APPLICATION = 'common.wsgi.application' + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} + +AUTH_PASSWORD_VALIDATORS = [] + +LANGUAGE_CODE = 'fr' + +TIME_ZONE = 'Europe/Zurich' + +USE_I18N = True + +USE_L10N = True + +USE_TZ = True + +STATIC_URL = '/static/' +MEDIA_URL = '/media/' +MEDIA_ROOT = os.path.join(BASE_DIR, 'media') + +from .local_settings import * diff --git a/common/urls.py b/common/urls.py new file mode 100644 index 0000000..2eb1e03 --- /dev/null +++ b/common/urls.py @@ -0,0 +1,11 @@ +from django.contrib import admin +from django.urls import path + +from recette.views import home, recette + + +urlpatterns = [ + path('admin/', admin.site.urls), + path('', home, name='home'), + path('recette//', recette, name='recette'), +] diff --git a/common/wsgi.py b/common/wsgi.py new file mode 100644 index 0000000..a01db89 --- /dev/null +++ b/common/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for recettes project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/2.0/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "recettes.settings") + +application = get_wsgi_application() diff --git a/manage.py b/manage.py new file mode 100755 index 0000000..889e670 --- /dev/null +++ b/manage.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python +import os +import sys + +if __name__ == "__main__": + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "common.settings") + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) diff --git a/recette/__init__.py b/recette/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/recette/admin.py b/recette/admin.py new file mode 100644 index 0000000..dd0f543 --- /dev/null +++ b/recette/admin.py @@ -0,0 +1,25 @@ +from django import forms +from django.contrib import admin + +from .models import Composition, Ingredient, Recette, Unite + + +class RecetteForm(forms.ModelForm): + photo = forms.ImageField( + label="Photo", + widget=forms.ClearableFileInput(attrs={'capture': True, 'accept': "image/*"}), + required=False + ) + class Meta: + model = Recette + fields = '__all__' + + +@admin.register(Recette) +class RecetteAdmin(admin.ModelAdmin): + form = RecetteForm + + +admin.site.register(Composition) +admin.site.register(Ingredient) +admin.site.register(Unite) diff --git a/recette/forms.py b/recette/forms.py new file mode 100644 index 0000000..6f3ca9b --- /dev/null +++ b/recette/forms.py @@ -0,0 +1,5 @@ +from django import forms + + +class SearchForm(forms.Form): + text = forms.CharField() diff --git a/recette/migrations/0001_initial.py b/recette/migrations/0001_initial.py new file mode 100644 index 0000000..a00dcbe --- /dev/null +++ b/recette/migrations/0001_initial.py @@ -0,0 +1,61 @@ +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Composition', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('quantite', models.DecimalField(blank=True, decimal_places=3, max_digits=6, null=True)), + ], + ), + migrations.CreateModel( + name='Ingredient', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('nom', models.CharField(max_length=200, verbose_name='Nom')), + ], + ), + migrations.CreateModel( + name='Recette', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('nom', models.CharField(max_length=200, verbose_name='Nom')), + ('photo', models.ImageField(blank=True, upload_to='photos', verbose_name='Photo')), + ('nb_pers', models.IntegerField(default=4)), + ('prep', models.TextField(blank=True, verbose_name='Préparation')), + ('source', models.CharField(blank=True, max_length=200, verbose_name='Source')), + ('ingredients', models.ManyToManyField(blank=True, through='recette.Composition', to='recette.Ingredient')), + ], + ), + migrations.CreateModel( + name='Unite', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('nom', models.CharField(max_length=200, verbose_name='Unité')), + ], + ), + migrations.AddField( + model_name='composition', + name='ingredient', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='recette.Ingredient'), + ), + migrations.AddField( + model_name='composition', + name='recette', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='recette.Recette'), + ), + migrations.AddField( + model_name='composition', + name='unite', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='recette.Unite'), + ), + ] diff --git a/recette/migrations/__init__.py b/recette/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/recette/models.py b/recette/models.py new file mode 100644 index 0000000..697dc60 --- /dev/null +++ b/recette/models.py @@ -0,0 +1,38 @@ +from django.db import models +from django.urls import reverse + + +class Ingredient(models.Model): + nom = models.CharField("Nom", max_length=200) + + def __str__(self): + return self.nom + + +class Unite(models.Model): + nom = models.CharField("Unité", max_length=200) + + def __str__(self): + return self.nom + + +class Recette(models.Model): + nom = models.CharField("Nom", max_length=200) + photo = models.ImageField("Photo", upload_to='photos', blank=True) + nb_pers = models.IntegerField(default=4) + prep = models.TextField("Préparation", blank=True) + source = models.CharField("Source", max_length=200, blank=True) + ingredients = models.ManyToManyField(Ingredient, through='Composition', blank=True) + + def __str__(self): + return self.nom + + def get_absolute_url(self): + return reverse('recette', args=[self.pk]) + + +class Composition(models.Model): + recette = models.ForeignKey(Recette, on_delete=models.CASCADE) + ingredient = models.ForeignKey(Ingredient, on_delete=models.PROTECT) + quantite = models.DecimalField(max_digits=6, decimal_places=3, null=True, blank=True) + unite = models.ForeignKey(Unite, null=True, blank=True, on_delete=models.PROTECT) diff --git a/recette/views.py b/recette/views.py new file mode 100644 index 0000000..38fe3b3 --- /dev/null +++ b/recette/views.py @@ -0,0 +1,19 @@ +from django.shortcuts import get_object_or_404, render + +from .forms import SearchForm +from .models import Recette + + +def home(request): + form = SearchForm(request.POST or None) + recettes = [] + if request.method == 'POST': + if form.is_valid(): + recettes = Recette.objects.filter(nom__icontains=form.cleaned_data['text']) + + return render(request, 'index.html', context={'form': form, 'recettes': recettes}) + + +def recette(request, pk): + recette = get_object_or_404(Recette, pk=pk) + return render(request, 'recette.html', context={'recette': recette}) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..4cb0052 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +django>=2.0 diff --git a/templates/base.html b/templates/base.html new file mode 100644 index 0000000..7785872 --- /dev/null +++ b/templates/base.html @@ -0,0 +1,19 @@ + + + + + Recettes {% block title %}page title{% endblock %} + + {% block extrahead %} + {% endblock %} + + + +
+ {% block content %} + {% endblock %} +
+
+
Gestion
+ + diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..9b40938 --- /dev/null +++ b/templates/index.html @@ -0,0 +1,16 @@ +{% extends 'base.html' %} + +{% block content %} +

Recettes

+ +
{% csrf_token %} + {{ form.as_p }} + +
+ + +{% endblock %} diff --git a/templates/recette.html b/templates/recette.html new file mode 100644 index 0000000..26e4942 --- /dev/null +++ b/templates/recette.html @@ -0,0 +1,17 @@ +{% extends 'base.html' %} + +{% block content %} +

{{ recette.nom }}

+ +
+ +
{{ recette.preparation }}
+ +{% if recette.ingredients.count %} + +{% endif %} +{% endblock %}