diff --git a/Thermomix1/.gitignore b/Thermomix1/.gitignore new file mode 100644 index 0000000..7447f89 --- /dev/null +++ b/Thermomix1/.gitignore @@ -0,0 +1 @@ +/bin \ No newline at end of file diff --git a/Thermomix1/.project b/Thermomix1/.project new file mode 100644 index 0000000..9ef7901 --- /dev/null +++ b/Thermomix1/.project @@ -0,0 +1,18 @@ + + + Thermomix1 + + + + + + org.python.pydev.PyDevBuilder + + + + + + org.python.pydev.pythonNature + org.python.pydev.django.djangoNature + + diff --git a/Thermomix1/.pydevproject b/Thermomix1/.pydevproject new file mode 100644 index 0000000..6e842d0 --- /dev/null +++ b/Thermomix1/.pydevproject @@ -0,0 +1,12 @@ + + + +DJANGO_MANAGE_LOCATION +manage.py + + +/${PROJECT_DIR_NAME} + +python 2.7 +Default + diff --git a/Thermomix1/.settings/org.eclipse.core.resources.prefs b/Thermomix1/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..b4a2ed9 --- /dev/null +++ b/Thermomix1/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,4 @@ +eclipse.preferences.version=1 +encoding//recipes/adminx.py=utf-8 +encoding//recipes/models.py=utf-8 +encoding//shopping/model.py=utf-8 diff --git a/Thermomix1/Thermomix1/__init__.py b/Thermomix1/Thermomix1/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Thermomix1/Thermomix1/settings.py b/Thermomix1/Thermomix1/settings.py new file mode 100644 index 0000000..6be5578 --- /dev/null +++ b/Thermomix1/Thermomix1/settings.py @@ -0,0 +1,190 @@ +# Django settings for wictrl project. + +import sys +import os.path + + +reload(sys) +sys.setdefaultencoding('utf-8') +gettext = lambda s: s + +BASE_DIR = os.path.dirname(os.path.dirname(__file__)) +PROJECT_ROOT = os.path.join( + os.path.realpath(os.path.dirname(__file__)), os.pardir) + +DEBUG = True +TEMPLATE_DEBUG = DEBUG + + +ADMINS = ( + ('Recetas', 'support@thermomix.com'), +) + +MANAGERS = ADMINS + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.postgresql_psycopg2', + 'NAME': 'thermomix1', + 'USER': 'postgres', + 'PASSWORD': 'master', + 'HOST': 'localhost', + 'PORT': '', + } +} +# Hosts/domain names that are valid for this site; required if DEBUG is False +# See https://docs.djangoproject.com/en/1.5/ref/settings/#allowed-hosts +ALLOWED_HOSTS = '*' + +# Local time zone for this installation. Choices can be found here: +# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name +# although not all choices may be available on all operating systems. +# In a Windows environment this must be set to your system time zone. +TIME_ZONE = 'America/Chicago' + +# Language code for this installation. All choices can be found here: +# http://www.i18nguy.com/unicode/language-identifiers.html +LANGUAGE_CODE = 'en-us' + +LANGUAGES = ( + ('en', gettext('English')), + ('zh_CN', gettext('Chinese')), +) + +SITE_ID = 1 + +# If you set this to False, Django will make some optimizations so as not +# to load the internationalization machinery. +USE_I18N = True + +# If you set this to False, Django will not format dates, numbers and +# calendars according to the current locale. +USE_L10N = True + +# If you set this to False, Django will not use timezone-aware datetimes. +USE_TZ = True + +# Absolute filesystem path to the directory that will hold user-uploaded files. +# Example: "/home/media/media.lawrence.com/media/" +MEDIA_ROOT = os.path.join(PROJECT_ROOT, 'media') + +# URL that handles the media served from MEDIA_ROOT. Make sure to use a +# trailing slash. +# Examples: "http://media.lawrence.com/media/", "http://example.com/media/" +MEDIA_URL = '/media/' + +# Absolute path to the directory static files should be collected to. +# Don't put anything in this directory yourself; store your static files +# in apps' "static/" subdirectories and in STATICFILES_DIRS. +# Example: "/home/media/media.lawrence.com/static/" +STATIC_ROOT = 'static/' + +# URL prefix for static files. +# Example: "http://media.lawrence.com/static/" +STATIC_URL = '/static/' + +# Additional locations of static files +STATICFILES_DIRS = ( + os.path.join(BASE_DIR, 'recipes/static'), + +) +# List of finder classes that know how to find static files in +# various locations. +STATICFILES_FINDERS = ( + 'django.contrib.staticfiles.finders.FileSystemFinder', + 'django.contrib.staticfiles.finders.AppDirectoriesFinder', + # 'django.contrib.staticfiles.finders.DefaultStorageFinder', +) + +# Make this unique, and don't share it with anybody. +SECRET_KEY = '5=!nss_+^nvyyc_j(tdcf!7(_una*3gtw+_8v5jaa=)j0g^d_2' + +# List of callables that know how to import templates from various sources. +TEMPLATE_LOADERS = ( + 'django.template.loaders.filesystem.Loader', + 'django.template.loaders.app_directories.Loader', + # 'django.template.loaders.eggs.Loader', +) + +MIDDLEWARE_CLASSES = ( + 'django.middleware.common.CommonMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + # Uncomment the next line for simple clickjacking protection: + # 'django.middleware.clickjacking.XFrameOptionsMiddleware', +) + +ROOT_URLCONF = 'Thermomix1.urls' + +# Python dotted path to the WSGI application used by Django's runserver. +WSGI_APPLICATION = 'Thermomix1.wsgi.application' + +TEMPLATE_DIRS = ( + # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". + # Always use forward slashes, even on Windows. + # Don't forget to use absolute paths, not relative paths. + os.path.join(PROJECT_ROOT, "templates"), +) + +INSTALLED_APPS = ( + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'django.contrib.admin', + + 'xadmin', + 'crispy_forms', + 'reversion', + 'sorl.thumbnail', + + 'base', + 'recipes', + 'shopping' +) + +DATE_FORMAT = 'Y-m-d' +DATETIME_FORMAT = 'Y-m-d H:i' +TIME_FORMAT = 'H:i' + +TEST_RUNNER = 'django.test.runner.DiscoverRunner' + +# A sample logging configuration. The only tangible logging +# performed by this configuration is to send an email to +# the site admins on every HTTP 500 error when DEBUG=False. +# See http://docs.djangoproject.com/en/dev/topics/logging for +# more details on how to customize your logging configuration. +LOGGING = { + 'version': 1, + 'disable_existing_loggers': False, + 'filters': { + 'require_debug_false': { + '()': 'django.utils.log.RequireDebugFalse' + } + }, + 'handlers': { + 'mail_admins': { + 'level': 'ERROR', + 'filters': ['require_debug_false'], + 'class': 'django.utils.log.AdminEmailHandler' + }, + 'console': { + 'level': 'DEBUG', + 'class': 'logging.StreamHandler' + }, + }, + 'loggers': { + 'django.request': { + 'handlers': ['mail_admins'], + 'level': 'ERROR', + 'propagate': True, + }, + # 'django.db.backends': { + # 'handlers': ['console'], + # 'level': 'DEBUG', + # } + } +} diff --git a/Thermomix1/Thermomix1/urls.py b/Thermomix1/Thermomix1/urls.py new file mode 100644 index 0000000..50540bb --- /dev/null +++ b/Thermomix1/Thermomix1/urls.py @@ -0,0 +1,17 @@ +from django.conf.urls import patterns, include, url +from django.conf import settings +from django.conf.urls.static import static +# Uncomment the next two lines to enable the admin: +import xadmin + +from xadmin.plugins import xversion +xversion.register_models() + +from django.contrib import admin + +urlpatterns = patterns('', + (r'^recipes/', include('recipes.urls')), + url(r'^admin/', include(admin.site.urls)), + url(r'^', include(xadmin.site.urls)) +) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + \ No newline at end of file diff --git a/Thermomix1/Thermomix1/wsgi.py b/Thermomix1/Thermomix1/wsgi.py new file mode 100644 index 0000000..631ac4d --- /dev/null +++ b/Thermomix1/Thermomix1/wsgi.py @@ -0,0 +1,28 @@ +""" +WSGI config for wictrl project. + +This module contains the WSGI application used by Django's development server +and any production WSGI deployments. It should expose a module-level variable +named ``application``. Django's ``runserver`` and ``runfcgi`` commands discover +this application via the ``WSGI_APPLICATION`` setting. + +Usually you will have the standard Django WSGI application here, but it also +might make sense to replace the whole Django WSGI application with a custom one +that later delegates to the Django one. For example, you could introduce WSGI +middleware here, or combine a Django application with an application of another +framework. + +""" +import os + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "Thermomix1.settings") + +# This application object is used by any WSGI server configured to use this +# file. This includes Django's development server, if the WSGI_APPLICATION +# setting points here. +from django.core.wsgi import get_wsgi_application +application = get_wsgi_application() + +# Apply WSGI middleware here. +# from helloworld.wsgi import HelloWorldApplication +# application = HelloWorldApplication(application) diff --git a/Thermomix1/base/__init__.py b/Thermomix1/base/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Thermomix1/base/adminx.py b/Thermomix1/base/adminx.py new file mode 100644 index 0000000..0c10248 --- /dev/null +++ b/Thermomix1/base/adminx.py @@ -0,0 +1,20 @@ +''' +Created on 16 de dic. de 2015 + +@author: fjmora +''' +import xadmin +from xadmin import views + + +class MainDashboard(object): + pass + +xadmin.site.register(views.website.IndexView,MainDashboard) + + +class BaseSetting(object): + enable_themes = True + use_bootswatch = True + +xadmin.site.register(views.BaseAdminView, BaseSetting) \ No newline at end of file diff --git a/Thermomix1/manage.py b/Thermomix1/manage.py new file mode 100644 index 0000000..fdd27e4 --- /dev/null +++ b/Thermomix1/manage.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python +import os +import sys + +if __name__ == "__main__": + PROJECT_ROOT = os.path.realpath(os.path.dirname(__file__)) + sys.path.insert(0, os.path.join(PROJECT_ROOT, os.pardir)) + + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "Thermomix1.settings") + + from django.core.management import execute_from_command_line + + execute_from_command_line(sys.argv) diff --git a/Thermomix1/media/recipes/2015/12/16/Comida-para-Marte-impresiones-3D-y-pizza-3.jpg b/Thermomix1/media/recipes/2015/12/16/Comida-para-Marte-impresiones-3D-y-pizza-3.jpg new file mode 100644 index 0000000..3865e8b Binary files /dev/null and b/Thermomix1/media/recipes/2015/12/16/Comida-para-Marte-impresiones-3D-y-pizza-3.jpg differ diff --git a/Thermomix1/media/recipes/2015/12/16/test.jpg b/Thermomix1/media/recipes/2015/12/16/test.jpg new file mode 100644 index 0000000..fce1fdc Binary files /dev/null and b/Thermomix1/media/recipes/2015/12/16/test.jpg differ diff --git a/Thermomix1/recipes/__init__.py b/Thermomix1/recipes/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Thermomix1/recipes/adminx.py b/Thermomix1/recipes/adminx.py new file mode 100644 index 0000000..969d598 --- /dev/null +++ b/Thermomix1/recipes/adminx.py @@ -0,0 +1,156 @@ +#encoding:utf-8 +''' +Created on 17 de nov. de 2015 + +@author: fjmora +''' + +from django.utils.safestring import mark_safe +import xadmin +from recipes.models import Ingredients, RecipeImages, Recipe, Category, Units,\ + UserFavoriteRecipe, Bom, RecipeComment +from xadmin.views.base import filter_hook +from django.utils.translation import ugettext as _ +import datetime + +class IngredientInlineAdmin(object): + model = Ingredients + extra = 0 + style = 'accordion' + +class ImagesInlineAdmin(object): + model = RecipeImages + extra = 0 + style = 'tab' # other values: `one` (default), `table`, `accordian` + + +class IngredientsAdmin(object): + fields = ('bom',) + + +class BomAdmin(object): + list_display = ('name','description','category') + list_editable = ('name', 'category') + search_fields = ['name','description', 'category'] + list_filter = ['category'] + fields = ('name','description','category') + + +class RecipeAdmin(object): + #TODO: En el formulario poner un check para identificarse uno mismo como el autor de la receta + #inlines = [IngredientInlineAdmin,ImagesInlineAdmin] + list_display = ('title','is_thermomix','version','create_date','view_recipe','favorite') + list_editable = ('title','is_thermomix','version') + exclude = ['create_date','saveBy']#,'saveBy' + fieldsets = ( + (None, { + 'fields' : ('title','autor','version','preparation') + }), + ) + + inlines = [IngredientInlineAdmin,ImagesInlineAdmin] + + #TODO: Pendiente de crear el html que muestre un resumen de la receta + def view_recipe(self, obj): + url = "" + return mark_safe(url) + + #TODO: Pendiente de implementar la logica de favoritos + def favorite(self, obj): + url = "" % obj.id + return mark_safe(url) + + view_recipe.short_description = "Show recipe" + view_recipe.is_column = True + favorite.short_description = "Favorite" + favorite.is_column = True + + @filter_hook + def save_models(self): + self.new_obj.saveBy = self.user + self.new_obj.create_date = datetime.datetime.now() + self.new_obj.save() +# @filter_hook +# def save_forms(self): +# self.form_obj.full_clean() +# item = self.org_obj or Recipe() +# item.saveBy = self.request.user +# +# self.new_obj = item; +# +# if self.form_obj.is_valid(): +# obj = self.form_obj.save(commit=False) # get just the object but don't commit it yet. +# obj.save() # finally save it. +# self.form_obj.save_m2m() +# +# @filter_hook +# def save_related(self): +# self.form_obj.save_m2m() + +class CategoryAdmin(object): + pass + +class UnitsAdmin(object): + pass + +class UserFavoriteRecipeAdmin(object): + pass + +class RecipeImageUserAdmin(object): + list_display = ('recipe_image',) + + def recipe_image(self, obj): + url = u'' % obj.profile_image + return url + + recipe_image.allow_tags = True + recipe_image.short_description = _(u'Imágenes') + + @filter_hook + def save_models(self): + self.new_obj.user = self.user + self.new_obj.save() + +class RecipeCommentAdmin(object): + exclude = ['user','creation_date'] + + @filter_hook + def save_models(self): + self.new_obj.user = self.user + self.new_obj.creation_date = datetime.datetime.now() + self.new_obj.save() + +# fieldsets = ( +# (None, { +# 'fields' : ('text','recipe') +# }), +# ) + + # exclude = ['user','creation_date'] + +# @filter_hook +# def save_forms(self): +# self.form_obj.full_clean() +# item = self.org_obj or RecipeComment() +# item.user = self.request.user +# +# self.new_obj = item; +# +# if self.form_obj.is_valid(): +# obj = self.form_obj.save(commit=False) # get just the object but don't commit it yet. +# obj.user = item.user +# obj.save() # finally save it. +# #self.form_obj.save_m2m() +# +# @filter_hook +# def save_related(self): +# pass + +xadmin.site.register(Recipe,RecipeAdmin) +xadmin.site.register(Category,CategoryAdmin) +xadmin.site.register(Units,UnitsAdmin) +xadmin.site.register(Ingredients,IngredientsAdmin) +xadmin.site.register(UserFavoriteRecipe,UserFavoriteRecipeAdmin) +xadmin.site.register(RecipeImages,RecipeImageUserAdmin) +xadmin.site.register(Bom,BomAdmin) +xadmin.site.register(RecipeComment,RecipeCommentAdmin) \ No newline at end of file diff --git a/Thermomix1/recipes/forms.py b/Thermomix1/recipes/forms.py new file mode 100644 index 0000000..edde0cc --- /dev/null +++ b/Thermomix1/recipes/forms.py @@ -0,0 +1,12 @@ +''' +Created on 16 de dic. de 2015 + +@author: fjmora +''' +from django import forms + +class RecipeImagesForm(forms.Form): + docfile = forms.FileField( + label='Select a file', + ) + \ No newline at end of file diff --git a/Thermomix1/recipes/migrations/0001_initial.py b/Thermomix1/recipes/migrations/0001_initial.py new file mode 100644 index 0000000..641afd0 --- /dev/null +++ b/Thermomix1/recipes/migrations/0001_initial.py @@ -0,0 +1,153 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations +import sorl.thumbnail.fields +import recipes.models +from django.conf import settings + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Bom', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('name', models.CharField(max_length=200, verbose_name='Nombre')), + ('description', models.CharField(max_length=800, verbose_name='Descripci\xf3n')), + ], + options={ + 'verbose_name': 'Materia prima', + 'verbose_name_plural': 'Materias primas', + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='Category', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('code', models.CharField(max_length=10, verbose_name='C\xf3digo')), + ('name', models.CharField(max_length=300, verbose_name='Nombre')), + ('valid', models.BooleanField(default=True, verbose_name='V\xe1lido')), + ], + options={ + 'verbose_name': 'Categor\xeda', + 'verbose_name_plural': 'Categor\xedas', + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='Ingredients', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('quantity', models.FloatField(null=True, verbose_name='Cantidad', blank=True)), + ('detalle', models.CharField(max_length=500, null=True, verbose_name='Detalle', blank=True)), + ('bom', models.ForeignKey(verbose_name='Materias primas', to='recipes.Bom')), + ], + options={ + 'verbose_name': 'Ingrediente', + 'verbose_name_plural': 'Ingredientes', + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='Recipe', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('title', models.CharField(max_length=200, verbose_name='T\xedtulo')), + ('description', models.TextField(null=True, verbose_name='Descripci\xf3n', blank=True)), + ('autor', models.CharField(max_length=200, null=True, verbose_name='Autor', blank=True)), + ('is_thermomix', models.BooleanField(default=True, verbose_name='Thermomix')), + ('create_date', models.DateTimeField(verbose_name='Fecha de creaci\xf3n')), + ('version', models.CharField(default=b'1.0', max_length=100, verbose_name='Versi\xf3n')), + ('preparation', models.TextField(verbose_name='Preparaci\xf3n')), + ('aclaraciones', models.TextField(null=True, verbose_name='Aclaraciones', blank=True)), + ('sugerencias', models.TextField(null=True, verbose_name='Sugerencias', blank=True)), + ('saveBy', models.ForeignKey(verbose_name='Usuario', blank=True, to=settings.AUTH_USER_MODEL, null=True)), + ], + options={ + 'verbose_name': 'Receta', + 'verbose_name_plural': 'Recetas', + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='RecipeComment', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('text', models.TextField()), + ('creation_date', models.DateTimeField()), + ('recipe', models.ForeignKey(verbose_name='Receta', to='recipes.Recipe')), + ('user', models.ForeignKey(verbose_name='Usuario', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'verbose_name': 'Comentario', + 'verbose_name_plural': 'Comentarios', + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='RecipeImages', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('profile_image', sorl.thumbnail.fields.ImageField(upload_to=recipes.models.content_file_name)), + ('recipe', models.ForeignKey(verbose_name='Receta', to='recipes.Recipe')), + ('user', models.ForeignKey(verbose_name='Usuario', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'verbose_name': 'Im\xe1genes de receta', + 'verbose_name_plural': 'Im\xe1genes de recetas', + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='Units', + fields=[ + ('code', models.CharField(max_length=10, serialize=False, verbose_name='C\xf3digo', primary_key=True)), + ('description', models.CharField(max_length=100, verbose_name='Descripci\xf3n')), + ], + options={ + 'verbose_name': 'Unidad', + 'verbose_name_plural': 'Unidades', + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='UserFavoriteRecipe', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('favorite', models.BooleanField(default=False, verbose_name='Favorita')), + ('times', models.IntegerField(verbose_name='Veces usada')), + ('recipe', models.ForeignKey(verbose_name='Receta', to='recipes.Recipe')), + ('user', models.ForeignKey(verbose_name='Usuario', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'verbose_name': 'Recetas de usuario', + 'verbose_name_plural': 'Recetas de usuario', + }, + bases=(models.Model,), + ), + migrations.AddField( + model_name='ingredients', + name='recipe', + field=models.ForeignKey(verbose_name='Receta', to='recipes.Recipe'), + preserve_default=True, + ), + migrations.AddField( + model_name='ingredients', + name='units', + field=models.ForeignKey(verbose_name='Unidades', blank=True, to='recipes.Units', null=True), + preserve_default=True, + ), + migrations.AddField( + model_name='bom', + name='category', + field=models.ForeignKey(verbose_name='Categor\xeda', to='recipes.Category'), + preserve_default=True, + ), + ] diff --git a/Thermomix1/recipes/migrations/__init__.py b/Thermomix1/recipes/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Thermomix1/recipes/models.py b/Thermomix1/recipes/models.py new file mode 100644 index 0000000..4e626d8 --- /dev/null +++ b/Thermomix1/recipes/models.py @@ -0,0 +1,142 @@ +#encoding:utf-8 +''' +Created on 17 de nov. de 2015 + +@author: fjmora +''' +from django.db import models +from django.db.models.fields import CharField, TextField +from django.contrib.auth.models import User +from django.utils.translation import ugettext as _ +from django.db.models.fields.files import ImageField, FileField +from django.conf import settings +from __builtin__ import staticmethod +import datetime +from sorl.thumbnail import ImageField + + +# Unidades (Kg,g,l,etc.) +class Units(models.Model): + code = models.CharField(_(u'Código'),primary_key=True,max_length=10) + description = models.CharField(_(u'Descripción'),max_length=100) + + def __str__(self): + return "%s (%s)" % (self.code,self.description) + + class Meta: + verbose_name = _(u'Unidad') + verbose_name_plural = _(u'Unidades') + +# Categoría para materias +class Category(models.Model): + code = CharField(_(u'Código'),max_length=10) + name = CharField(_(u'Nombre'),max_length=300) + valid = models.BooleanField(_(u'Válido'),default=True) + + def __str__(self): + return "%s" % self.name + + class Meta: + verbose_name = _(u'Categoría') + verbose_name_plural = _(u'Categorías') + + +# Materias primas +class Bom(models.Model): + + name = models.CharField(_(u'Nombre'),max_length=200) + description = models.CharField(_(u'Descripción'),max_length=800) + category = models.ForeignKey(Category,verbose_name=_(u'Categoría')) + + @staticmethod + def autocomplete_search_fields(): + return ("name__iexact",) + + def __str__(self): + return "%s" % (self.name) + + def __unicode__(self): + return u"%s" % self.name + + def related_label(self): + return u"%s" % (self.name) + + class Meta: + verbose_name = _(u'Materia prima') + verbose_name_plural = _(u'Materias primas') + +# Recetas +class Recipe(models.Model): + title = models.CharField(_(u'Título'),max_length=200) + description = models.TextField(_(u'Descripción'),blank=True,null=True) + autor = models.CharField(_(u'Autor'),max_length=200,blank=True,null=True) + is_thermomix = models.BooleanField(_(u'Thermomix'),default=True) + saveBy = models.ForeignKey(User,verbose_name=_(u'Usuario'),blank=True,null=True) + create_date = models.DateTimeField(_(u'Fecha de creación')) + version = models.CharField(_(u'Versión'),max_length=100,default="1.0") + preparation = models.TextField(_(u'Preparación')) + aclaraciones = models.TextField(_(u'Aclaraciones'),blank=True,null=True) + sugerencias = models.TextField(_(u'Sugerencias'),blank=True,null=True) + + def __str__(self): + return "%s" % (self.title) + + class Meta: + verbose_name = _(u'Receta') + verbose_name_plural = _(u'Recetas') + + +#Recetas favoritas de cada usuario +class UserFavoriteRecipe(models.Model): + recipe = models.ForeignKey(Recipe,verbose_name=_(u'Receta')) + user = models.ForeignKey(User,verbose_name=_(u'Usuario')) + favorite = models.BooleanField(_(u'Favorita'),default=False) + times = models.IntegerField(_(u'Veces realizada'),) + + class Meta: + verbose_name = _(u'Recetas de usuario') + verbose_name_plural = _(u'Recetas de usuario') + +class RecipeComment(models.Model): + text = TextField() + user = models.ForeignKey(User,verbose_name=_(u'Usuario')) + recipe = models.ForeignKey(Recipe,verbose_name=_(u'Receta')) + creation_date = models.DateTimeField() + + class Meta: + verbose_name = _(u'Comentario') + verbose_name_plural = _(u'Comentarios') + +def content_file_name(instance, filename): + return '/'.join(['recipe', instance.user.username, filename]) + +class RecipeImages(models.Model): + profile_image = models.FileField(upload_to='recipes/%Y/%m/%d') + user = models.ForeignKey(User,verbose_name=_(u'Usuario')) + recipe = models.ForeignKey(Recipe,verbose_name=_(u'Receta')) + + class Meta: + verbose_name = _(u'Imágenes de receta') + verbose_name_plural = _(u'Imágenes de recetas') + + + +# Ingredientes, compuestos por una materia prima, cantidad, y unidada correspondiente +class Ingredients(models.Model): + bom = models.ForeignKey(Bom,verbose_name=_(u'Materias primas')) + quantity = models.FloatField(_(u'Cantidad'),blank=True,null=True) + units = models.ForeignKey(Units,blank=True,null=True,verbose_name=_(u'Unidades')) + recipe = models.ForeignKey(Recipe,verbose_name=_(u'Receta')) + detalle = models.CharField(_(u'Detalle'),max_length=500,blank=True,null=True) + + def __str__(self): + if self.quantity is not None and self.units is not None: + return "%s - (%s %s)" % (self.bom.name, self.quantity,self.units.code) + else: + return "%s" % (self.bom.name) + + class Meta: + verbose_name = _(u'Ingrediente') + verbose_name_plural = _(u'Ingredientes') + + diff --git a/Thermomix1/recipes/static/images/favorite_off.png b/Thermomix1/recipes/static/images/favorite_off.png new file mode 100644 index 0000000..0161467 Binary files /dev/null and b/Thermomix1/recipes/static/images/favorite_off.png differ diff --git a/Thermomix1/recipes/static/images/favorite_on.png b/Thermomix1/recipes/static/images/favorite_on.png new file mode 100644 index 0000000..a8cb9df Binary files /dev/null and b/Thermomix1/recipes/static/images/favorite_on.png differ diff --git a/Thermomix1/recipes/static/images/view.png b/Thermomix1/recipes/static/images/view.png new file mode 100644 index 0000000..f5de96d Binary files /dev/null and b/Thermomix1/recipes/static/images/view.png differ diff --git a/Thermomix1/recipes/templates/recipes/index.html b/Thermomix1/recipes/templates/recipes/index.html new file mode 100644 index 0000000..18c5de9 --- /dev/null +++ b/Thermomix1/recipes/templates/recipes/index.html @@ -0,0 +1,4 @@ +

+
+
+
Template: Thermomix1/recipes/templates/recipes/list.html
\ No newline at end of file diff --git a/Thermomix1/recipes/templates/recipes/list.html b/Thermomix1/recipes/templates/recipes/list.html new file mode 100644 index 0000000..01a966c --- /dev/null +++ b/Thermomix1/recipes/templates/recipes/list.html @@ -0,0 +1,36 @@ + + + + + Minimal Django File Upload Example + + + + + {% if documents %} + + {% else %} +

No documents.

+ {% endif %} + + +
+ {% csrf_token %} +

{{ form.non_field_errors }}

+

{{ form.docfile.label_tag }}

+

+ {{ form.docfile.errors }} + {{ form.docfile }} +

+

+
+ + + + \ No newline at end of file diff --git a/Thermomix1/recipes/tests.py b/Thermomix1/recipes/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/Thermomix1/recipes/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/Thermomix1/recipes/urls.py b/Thermomix1/recipes/urls.py new file mode 100644 index 0000000..e8b417a --- /dev/null +++ b/Thermomix1/recipes/urls.py @@ -0,0 +1,13 @@ +''' +Created on 16 de dic. de 2015 + +@author: fjmora +''' +from django.conf.urls import patterns, include, url +from recipes import views + +urlpatterns = patterns('recipes.views', + url(r'^$', 'list', name='list'), + url(r'^list/$', 'list', name='list'), + url(r'^recipe/favorite_recipe/(?P\d+)$', views.change_favorite_recipe), +) \ No newline at end of file diff --git a/Thermomix1/recipes/views.py b/Thermomix1/recipes/views.py new file mode 100644 index 0000000..0d395bc --- /dev/null +++ b/Thermomix1/recipes/views.py @@ -0,0 +1,60 @@ +from django.shortcuts import render_to_response, render +from django.template import RequestContext +from django.http import HttpResponseRedirect +from django.core.urlresolvers import reverse +from recipes.forms import RecipeImagesForm +from recipes.models import RecipeImages, Recipe, UserFavoriteRecipe +import mimetypes +from django.http.response import HttpResponse, HttpResponseRedirectBase + +# Create your views here. + +def list(request): + # Handle file upload + if request.method == 'POST': + form = RecipeImagesForm(request.POST, request.FILES) + if form.is_valid(): + newdoc = RecipeImages(docfile = request.FILES['docfile']) + newdoc.save() + + # Redirect to the document list after POST + return HttpResponseRedirect(reverse('Thermomix.recipes.views.list')) + else: + form = RecipeImagesForm() # A empty, unbound form + + # Load documents for the list page + documents = RecipeImages.objects.all() + + # Render list page with the documents and the form + return render_to_response( + 'recipes/list.html', + {'documents': documents, 'form': form}, + context_instance=RequestContext(request) + ) + +def index(request): + return render_to_response('recipes/index.html') + + +# View (in blog/views.py) +def change_favorite_recipe(request, id): + recipe = Recipe.objects.filter(pk=id).first() + favoriteRecipe = UserFavoriteRecipe.objects.filter(user__id=request.user.id,recipe__id=id).first() + + if favoriteRecipe is None: + favoriteRecipe = UserFavoriteRecipe() + favoriteRecipe.recipe = recipe + favoriteRecipe.user = request.user + favoriteRecipe.favorite = True + favoriteRecipe.times = 0 + elif favoriteRecipe.favorite == False: + favoriteRecipe.favorite = True + else: + favoriteRecipe.favorite = False + + favoriteRecipe.save() + + #return render(request, 'form.html', {'form': form}) + return render_to_response('../../') + #return render_to_response('/recipes/recipe/model_list.html') + diff --git a/Thermomix1/shopping/__init__.py b/Thermomix1/shopping/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Thermomix1/shopping/adminx.py b/Thermomix1/shopping/adminx.py new file mode 100644 index 0000000..890374b --- /dev/null +++ b/Thermomix1/shopping/adminx.py @@ -0,0 +1,12 @@ +''' +Created on 18 de nov. de 2015 + +@author: fjmora +''' +from shopping.model import ShoppingList +import xadmin + +class ShoppingListAdmin(object): + pass + +xadmin.site.register(ShoppingList,ShoppingListAdmin) \ No newline at end of file diff --git a/Thermomix1/shopping/migrations/0001_initial.py b/Thermomix1/shopping/migrations/0001_initial.py new file mode 100644 index 0000000..a7f141c --- /dev/null +++ b/Thermomix1/shopping/migrations/0001_initial.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('recipes', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='ShoppingList', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('name', models.CharField(max_length=100, verbose_name='Nombre')), + ('creation_date', models.DateField(verbose_name='Fecha de creaci\xf3n')), + ('made_date', models.DateField(verbose_name='Fecha de compra')), + ('made', models.BooleanField(default=False, verbose_name='Compra realizada')), + ('ingredients', models.ManyToManyField(to='recipes.Ingredients')), + ], + options={ + 'verbose_name': 'Lista de la compra', + 'verbose_name_plural': 'Listas de la compra', + }, + bases=(models.Model,), + ), + ] diff --git a/Thermomix1/shopping/migrations/__init__.py b/Thermomix1/shopping/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Thermomix1/shopping/model.py b/Thermomix1/shopping/model.py new file mode 100644 index 0000000..bb6543e --- /dev/null +++ b/Thermomix1/shopping/model.py @@ -0,0 +1,21 @@ +#encoding:utf-8 + + +from django.db import models +from django.utils.translation import ugettext as _ +from recipes.models import Ingredients + +# Unidades (Kg,g,l,etc.) +class ShoppingList(models.Model): + name = models.CharField(_(u'Nombre'),max_length=100) + creation_date = models.DateField(_(u'Fecha de creación')) + made_date = models.DateField(_(u'Fecha de compra')) + made = models.BooleanField(_(u'Compra realizada'),default=False) + ingredients = models.ManyToManyField(Ingredients) + + def __str__(self): + return "%s" % (self.name) + + class Meta: + verbose_name = _(u'Lista de la compra') + verbose_name_plural = _(u'Listas de la compra') diff --git a/Thermomix1/shopping/tests.py b/Thermomix1/shopping/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/Thermomix1/shopping/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here.