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 %}
+
+
+
+
+
+
+
\ 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.