lunes, 20 de abril de 2015

Tienda en Django

TIENDA EN DJANGO

El objetivo de esta prueba es que practiquemos con una tecnología del lado del servidor. Vamos a programa la web de una tienda utilizando tecnología Django para el lado del servidor. Es una tienda de bicicletas, discos y libros. Voy a intentar explicar lo mejor posible a partir de 4 PASOS las funciones que he introducido a mi tienda.

PASO 0:  Creando un proyecto en Django.

Vamos a diseñar una web de una tienda con tecnología Django para el lado del servidor. Para ello vamos a comenzar creando un proyecto en Django siguiendo el tutorial que se puede encontrar en el siguiente enlace: https://docs.djangoproject.com/en/1.8/intro/tutorial01/

A continuación hago un breve resumen de lo utilizado del tutorial para mi tienda.
           1.Creando el proyecto “shop”:
      $ django-admin startproject shop
            2.Creamos las tablas en la base de datos.
$ python manage.py migrate
      3.Creación de la aplicación en mi caso la llamare “stock”.
$ python manage.py encuestas startApp.
      4. La creación de la App “stock” nos va a generar los siguientes archivos:
                       4.1 models.py à Este fichero nos va servir para la creación de los modelos. En mi caso la tienda va a tener diferentes productos que vender: bici, libro, canción.
class Bici(models.Model):
marca = models.CharField(max_length=50)
modelo = models.CharField(max_length=50)
precio = models.DecimalField(max_digits=6, decimal_places=2)
image = models.ImageField(upload_to='items', verbose_name='image')
video = models.FileField(upload_to='items', verbose_name='file')
def __unicode__(self):
return self.marca
class Cancion(models.Model):
    titulo = models.CharField(max_length=50)
    autor = models.CharField(max_length=50)
    precio = models.DecimalField(max_digits=19, decimal_places=10)
    image = models.ImageField(upload_to='items', verbose_name='image')
    cancion = models.FileField(upload_to='items', verbose_name='file')
    def __unicode__(self):
        return self.titulo
class Libro(models.Model):
    titulo = models.CharField(max_length=50)
    autor = models.CharField(max_length=50)
    precio = models.DecimalField(max_digits=19, decimal_places=10)
    image = models.ImageField(upload_to='items', verbose_name='image')
    def __unicode__(self):
        return self.titulo
class Cart(models.Model):
    item = models.CharField(max_length=50)
    precio = models.DecimalField(max_digits=19, decimal_places=10)
    def __unicode__(self):
        return self.item
                   Una vez que creemos models.py, debemos modificar el fichero shop/setting.py tal y como se indica en el tutorial
INSTALLED_APPS = (
 'django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes', 
'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'stock',)
          4.2 0001_init__.py àA continuación y cada vez que hagamos una modificación en los modelos debemos hacer makemigration, para que django sepa incluir el stock en la aplicación.
    $ python manage.py makemigrations stock
        El sqlmigrate comando toma los nombres de migración y devuelve su SQL:
    $ python manage.py sqlmigrate stock 0001
        Por último crearemos los modelos en la base de datos con el siguiente comando:
    $ python manage.py migrate
        Una vez creado los modelos, vamos a proceder a introducir nuestros ficheros media a partir de la interfaz grafica de administración que nos propone django. Para ello es necesario registrarnos como administración a partir de los siguientes comandos en nuestra Shell:
$ python manage.py createsuperuser
  Nombre de usuario: Mario
  Dirección de correo electrónico: admin@example.com
  Contraseña: **********
  Contraseña de nuevo): *********  
  Superusuario creado correctamente.
 Ya podemos empezar el desarrollo en el server:
 $ python manage.py runserver.
 Solo una cosa antes de añadir los archivos en la administración y es editar el fichero admin.py
from django.contrib import admin
from stock.models import Bici
from stock.models import Cancion
from stock.models import Libro
admin.site.register(Bici)
admin.site.register(Cancion)
admin.site.register(Libro)














PASO 1: Vistas. 
Después de crear el proyecto y realizar todo la parte de administración, queremos que nuestros datos tengan forma en nuestra web. Para ello vamos a editar el fichero stock/views.py que va ser el encargado de hacer la función de render a la cual le vamos a pasar tres parámetros: La respuesta, la plantilla.html y el contexto.
from django.shortcuts import render
from stock.models import Bici
from stock.models import Libro
from stock.models import Cancion
from django.http import Http404
from django.http import HttpResponseRedirect
from django import forms
from django.http import HttpResponse
def index(request):
    if 'nombre' in request.session :
        bicis = Bici.objects.all().order_by('marca')
        libros = Libro.objects.all().order_by('titulo')
        canciones = Cancion.objects.all().order_by('titulo')
         items = Cart.objects.all().order_by('item')
        nombre = request.session['nombre']
        context = {'bicis': bicis, 'nombre' : nombre, 'items': items,
                   'libros': libros,
                   'canciones': canciones}
        return render(request, 'stock/index.html', context)
    else:
        return HttpResponseRedirect('/stock/login/')
En mi caso, le he añadido un registro de sesión a mi web donde te obliga a autentificarte antes de hacer uso de la aplicación. En caso de que no estes autentificado devolverá un HttpResponseRedirect que conducirá a la siguiente vista:
class LoginForm(forms.Form):
    nombre = forms.CharField(max_length=50)
def login(request):
    if request.method == 'POST':
        form = LoginForm(request.POST)
        if form.is_valid():
            request.session['nombre'] = form.cleaned_data['nombre']
            return HttpResponseRedirect('/stock/')
    else:
        form = LoginForm()
    return render(request, 'stock/login.html', {'form': form})
También le he añadido otras vista como son: Comprar, FormularioUser, BorrarCart, Bicis, Libros y Canciones. Todas ellas con su correspondiente render donde le introduzco el contexto y la plantilla html.

             Antes de ponernos al diseño de la plantilla html y su correspondiente archivo css, es importante tener en cuenta los fichero shop/urls.py y stock/urls.py, ya que van a ser el motor de enrutamiento por donde se van a generar las vistas.
Comenzamos con el shop/urls.py
            from django.conf.urls import patterns, include, url
from django.contrib import admin
admin.autodiscover()
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.conf import settings
urlpatterns = patterns('',
    url(r'^stock/', include('stock.urls', namespace="stock")),
    url(r'^admin/', include(admin.site.urls)), )
El fichero stock/urls.py
            from django.conf.urls import patterns, url
from stock import views
urlpatterns = patterns('',
url(r'^$', views.index, name='index'),
                  url(r'^usuarioform/$', views.usuarioform, name='usuarioform'),
url(r'^comprar/$', views.comprar, name='comprar'),
                  url(r'^login/$', views.login, name='login'),
                  url(r'^borrarcart/$', views.borrarcart, name='borrarcart'),

url(r'^bicis/$', views.bicis, name='indexbicis'),
                  url(r'^libros/$', views.libros, name='indexlibros'),
url(r'^canciones/$', views.canciones, name='indexcanciones'),))


 PASO 2: Uploads, Templates y Static
Tanto Uploads, Templates y Static son carpetas, las cuales van almacenar:
            -shop/shop/Uploads/itemsà Almacenara todos los archivos que serán itroducidos posteriormente en nuestras plantillas.
            -shop/stock/staticà Almacenara el archivo .css que dará estilo a nuestra plantilla.
body{
    overflow: auto;
    height: 1000px;
    width: auto;
    background-image: url(fondobody.png);
}
#contenedor{
    width: 100%;
    height: 100%;
}
#encabezado{
    width: 98%;
    height: 55%;
}
.
.
.
.
            -shop/stock/templates/stockà Directorio donde se encontraran todas las plantillas pertinentes.            (index.html/found.html/login.html/bici.html…). Importante en las plantillas hacer referencia al siguiente código:
                       <link rel="stylesheet" type="text/css" href="{% static 'stock/estyle.css' %}" />à Importamos el archivo css que se encuentra en stock/static
{% load staticfiles %}à Carga los archicos que se encuentran en upload/ítems.
PASO 3: Instalación y uso de Dajaxice.
3.1  Instalar paquetes python Dajaxice.
                       Descargar Dajaxice desde aquí: https://github.com/jorgebastida/django-dajaxice/downloads
Descomprimirlo en un directorio
Cambiar a ese directorio (esto es, cd django-dajaxice-0.9)
Instalar con 'el comando sudo python setup.py install '
3.2 Obtener Dajaxice para nuestro proyecto en Django
- Añadir dajaxice a settings.py
INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'stock',
    'dajaxice',)
TEMPLATE_LOADERS = ('django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
 django.template.loaders.eggs.Loader',)
TEMPLATE_CONTEXT_PROCESSORS  =  ( 'django.contrib.auth.context_processors.auth' ,'django.core.context_processors.debug' ,   'django.core.context_processors.i18n','django.core.context_processors.media' ,  'django.core.context_processors.static', 'django.core.context_processors.request', 'django.contrib.messages.context_processors.messages'
)
STATICFILES_FINDERS  =  (
    'django.contrib.staticfiles.finders.FileSystemFinder' ,
    'django.contrib.staticfiles.finders.AppDirectoriesFinder' ,
    'dajaxice.finders.DajaxiceFinder' ,
)
RUTA_PROYECTO = os.path.dirname (os.path.realpath(__file__))
MEDIA_ROOT = os.path.join(RUTA_PROYECTO,'uploads')
- Añada las siguientes líneas de importación a la parte superior de urls.py :
from django.conf.urls import patterns, include, url
from django.contrib import admin
admin.autodiscover()
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.conf import settings
from dajaxice.core import dajaxice_autodiscover, dajaxice_config
urlpatterns = patterns('',
    url(r'^stock/', include('stock.urls', namespace="stock")),
    url(r'^admin/', include(admin.site.urls)),
    url(dajaxice_config.dajaxice_url, include('dajaxice.urls')),
url(r'^uploads/(?P<path>.*)$','django.views.static.serve',{'document_root':settings.MEDIA_ROOT,}),
)
urlpatterns += staticfiles_urlpatterns()
            Ahora con un poco de suerte su proyecto debe tener todo configurado y listo para empezar a escribir funciones en dajaxice.

 3.3 Invocar sus funciones Dajaxice.
 Una vez que tenemos todo listo para poder utilizar Dajaxice, lo primero es crearnos un fichero Ajax.py donde le vamos a introducir las funciones que vamos a querer tener en nuestra tienda en nuestro caso son dos:
                       1º Carrito: Cada producto que seleccionemos cuando pinchemos a añadir carrito, se añadirá en una lista.
                       @dajaxice_register
def additem(request, producto_nombre, producto_precio):
nuevoitem = Cart(item = producto_nombre, precio = producto_precio)
nuevoitem.save()
itemsstring = ''
itemslist = Cart.objects.all().order_by('item')
for i in itemslist:
itemsstring = itemsstring + '<p>' + i.item + ' Precio: ' + str(i.precio) + '</p>'
return json.dumps({'message': itemsstring})

            2º Búsqueda: El usuario podrá buscar entre todos los productos que oferte la tienda.
                  @dajaxice_register
def search(request, param):
    bicis = Bici.objects.filter(Q(marca__icontains = param))
    libros = Libro.objects.filter(Q(titulo__icontains = param))
    canciones = Cancion.objects.filter(Q(titulo__icontains = param))
    context = {'bikes_founded' : bicis, 'libros_founded': libros, 'canciones_founded': canciones}
    return render(request, 'stock/found.html', context)

 3.4 Por último tendremos que darle función en nuestras plantillas. Eso lo hacemos de la            siguiente manera:
 Buscar:
<input type="text" id="buscar">
<button onclick="Dajaxice.stock.search(find,{ 'param' : $('#buscar').val() });">Buscar</button>
<div id="found">
</div>
Carrito:
<div id="cart">
{% if items %}
{% for item in items %}
<p>{{item.item}}. Precio: {{item.precio}}€</p>
{% endfor %}
{% else %}
<p>No has añadido ningún producto.</p>
{% endif %}
</div>
<button onclick="Dajaxice.stock.additem(my_js_callback,{'producto_nombre': '{{bici.marca}}', 'producto_precio' : '{{bici.precio}}'});">Añadir al carrito</button>
                 *Ambas acciones necesitan de dos funciones js que modifican el elemento del árbol DOM como son:
<script>
function my_js_callback(data){
document.getElementById("cart").innerHTML = data.message;}
function find(data){
document.getElementById("found").innerHTML = data;}
</script>

4 comentarios:

  1. Pésimo ejemplo incompleto, si vas a hacer algo hazlo bien solo confundes, de verdad muy mal.

    ResponderEliminar
  2. Lo peor que he visto, se hace un modelo genérico de producto, que pasa con tu models.py si tienes mas de 1000 productos

    ResponderEliminar
  3. que lapidarios los comentarios anteriores, si bien es una gentileza del amigo que se de la molestia de diseñar e incluir este materal y ponerlo a dispocision, pienso que ya por eso tiene su valor. Ahora siempre hay aporte y de acuerdo a su enfoque el logra un carrito de compras funcional. Ahora los que tomemos esto como guia deberiamos completar y corregir el código si es necesario (nadie se lo sabe todo)

    ResponderEliminar