Skip to content

Instantly share code, notes, and snippets.

@zazk
Created January 3, 2012 02:31
Show Gist options
  • Save zazk/1553188 to your computer and use it in GitHub Desktop.
Save zazk/1553188 to your computer and use it in GitHub Desktop.
ManyToManyCMS
# -*- coding: utf-8 -*-
""" Admin Store. """
from django.contrib import admin
from django.contrib.flatpages.models import FlatPage
from local_apps.store.models import Category, Order, OrderDetail, Product, \
ProductImage, Ubigeo, Video, Banner, InfoSite
class CategoryInline(admin.TabularInline):
model = Category
sortable_field_name = 'position'
exclude = ('banner',)
extra = 0
class OrderDetailInline(admin.TabularInline):
model = OrderDetail
extra = 0
#Add Many to Many Model
class CategoryBannerInline(admin.TabularInline):
model = Category.banner.through
sortable_field_name = 'position'
# fields = ['image']
extra = 0
#Category with 2 relations
class CategoryAdmin(admin.ModelAdmin):
model = Category
inlines = [CategoryInline,CategoryBannerInline]
raw_id_fields = ['banner']
list_display = ['name']
exclude = ('banner',)
class OrderAdmin(admin.ModelAdmin):
model = Order
inlines = [OrderDetailInline]
list_display = ['buyer', 'subtotal', 'shipping_cost', 'total_price',
'shipping_location', 'status']
class ProductImageInline(admin.TabularInline):
model = ProductImage
sortable_field_name = 'position'
extra = 0
class ProductAdmin(admin.ModelAdmin):
model = Product
inlines = [ProductImageInline]
list_display = ['name', 'price', 'is_active', 'category']
fields = ['name', 'descrip', 'price', 'category', 'is_active']
class Media:
js = ('/static/nicEdit/nicEdit.js', '/static/nicEdit/nicEdit_conf.js')
class UbigeoAdmin(admin.ModelAdmin):
model = Ubigeo
list_display = ['short_name', 'shipping_cost', 'shipping_delivery_time']
ordering = ['state', 'province', 'district']
class MyFlatPageAdmin(admin.ModelAdmin):
fields = ('title', 'content')
class Media:
js = ('/static/nicEdit/nicEdit.js', '/static/nicEdit/nicEdit_conf.js')
# def has_add_permission(self, request):
# return False
# def has_delete_permission(self, request, obj=None):
# return False
class VideoAdmin(admin.ModelAdmin):
model = Video
class Media:
js = ('/static/nicEdit/nicEdit.js', '/static/nicEdit/nicEdit_conf.js')
class BannerInline(admin.TabularInline):
model = Banner
sortable_field_name = 'position'
extra = 0
class InfoSiteAdmin(admin.ModelAdmin):
model = InfoSite
fields = ['email_contacto']
inlines = [BannerInline]
# def has_add_permission(self, request):
# return False
# def has_delete_permission(self, request, obj=None):
# return False
admin.site.unregister(FlatPage)
admin.site.register(FlatPage, MyFlatPageAdmin)
admin.site.register(Category, CategoryAdmin)
admin.site.register(Order, OrderAdmin)
admin.site.register(Product, ProductAdmin)
admin.site.register(Ubigeo, UbigeoAdmin)
admin.site.register(Video, VideoAdmin)
admin.site.register(InfoSite, InfoSiteAdmin)
# -*- coding: utf-8 -*-
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.conf import settings
import Image
import os
import urlparse
# Create your models here.
class AuditableModel(models.Model):
created = models.DateTimeField(editable=False, auto_now_add=True)
modified = models.DateTimeField(editable=False, auto_now=True)
created_by = models.IntegerField("Creado por", editable=False, null=True,
default=0)
modified_by = models.IntegerField("Modificado por", editable=False,
null=True, default=0)
class Meta:
abstract = True
# class CategoryParent(AuditableModel):
# name = models.CharField("Nombre", max_length=120)
# descrip = models.TextField(u"Descripción", blank=True)
# class Meta:
# """ ."""
# verbose_name = u'Categoría'
# verbose_name_plural = u'Categorías'
# ordering = ['name']
# def __unicode__(self):
# return self.name
# def subcategories(self):
# return Category.objects.filter(parent_category=self)
class InfoSite(AuditableModel):
email_contacto = models.EmailField(verbose_name=u'Url de contacto')
url_twitter = models.URLField(verbose_name=u'Url de twitter',
null=True, blank=True)
url_facebook = models.URLField(verbose_name=u'Url de facebook',
null=True, blank=True)
url_youtube = models.URLField(verbose_name=u'Url de youtube',
null=True, blank=True)
class Meta:
""" ."""
verbose_name = u'Información del sitio'
verbose_name_plural = u'Información del sitio'
def __unicode__(self):
return u"Información del Sitio"
class Banner(AuditableModel):
image = models.ImageField(verbose_name="Archivo", upload_to="banner/original")
position = models.IntegerField("Orden", default=0)
site = models.ForeignKey(InfoSite)
def url_normal(self):
url = "{0}/banner/normal/{1}".format(settings.MEDIA_URL, self.image)
return url
class Meta:
""" ."""
verbose_name = u'Banner'
verbose_name_plural = u'Banners'
ordering = ['position']
class Category(AuditableModel):
name = models.CharField("Nombre", max_length=120)
descrip = models.TextField("Descripción", blank=True, editable=False)
position = models.IntegerField("Orden", default=0)
banner = models.ManyToManyField(Banner, verbose_name=u"Banners",through='CategoryBanner' )
parent_category = models.ForeignKey("self",
verbose_name=u"Categoría superior",
blank=True,
null=True)
class Meta:
""" ."""
verbose_name = u'Categoría'
verbose_name_plural = u'Categorías'
ordering = ['position']
def __unicode__(self):
# print self
# full = ' %s' % ( self.name )self.parent_category.name if self.parent_category.name else ''
full = ' %s' % ( self.name )
return full
class CategoryBanner(models.Model):
banner = models.ForeignKey(Banner)
category = models.ForeignKey(Category)
position = models.IntegerField("Orden",default=0)
class Meta:
verbose_name= u'Banner'
verbose_name_plural = u'Banners'
ordering = ['position']
class ProductManager(models.Manager):
def by_category(self, id):
return Product.objects.filter(category=id, is_active=True)
class Product(AuditableModel):
name = models.CharField("Nombre", max_length=120)
descrip = models.TextField("Descripción", blank=True)
price = models.DecimalField('Precio', max_digits=12
, decimal_places=2, default=0)
category = models.ForeignKey(Category, verbose_name=u"Categoría")
is_active = models.BooleanField("Activo", default=True)
main_image = models.CharField("Foto principal", max_length=120
, null=True, blank=True)
objects = ProductManager()
def url_thumb(self):
url = "{0}/products/thumb/{1}".format(settings.MEDIA_URL, self.main_image)
return url
def url_normal(self):
url = "{0}/products/normal/{1}".format(settings.MEDIA_URL, self.main_image)
return url
def url_large(self):
url = "{0}/products/large/{1}".format(settings.MEDIA_URL, self.main_image)
return url
def update_main_image(self):
# Establecer imagen principal
first_img = ProductImage.objects.filter(product=self)[0]
if first_img:
self.main_image = str(first_img.name)
else:
self.main_image = ''
self.save()
class Meta:
""" ."""
verbose_name = u'Producto'
verbose_name_plural = u'Productos'
def __unicode__(self):
return self.name
class ProductImage(AuditableModel):
name = models.ImageField(verbose_name="Archivo", upload_to="products/original")
position = models.IntegerField("Orden", default=0)
product = models.ForeignKey(Product, related_name='images')
class Meta:
""" ."""
verbose_name = u'Imagen'
verbose_name_plural = u'Imágenes'
ordering = ['position']
def __unicode__(self):
return u'%s' % self.name
def url_thumb(self):
url = "{0}/products/thumb/{1}".format(settings.MEDIA_URL, self.name)
return url
def url_normal(self):
url = "{0}/products/normal/{1}".format(settings.MEDIA_URL, self.name)
return url
def url_large(self):
url = "{0}/products/large/{1}".format(settings.MEDIA_URL, self.name)
return url
class Order(AuditableModel):
STATUS_CHOICES = (
(0, "Pendiente"),
(1, "Pagado"),
(2, "Anulado")
)
buyer = models.ForeignKey(User, verbose_name=u"Usuario")
subtotal = models.DecimalField('Precio', max_digits=12
, decimal_places=2, default=0)
shipping_cost = models.DecimalField('Costo de envío', max_digits=12
, decimal_places=2, default=0)
total_price = models.DecimalField('Precio_total', max_digits=12
, decimal_places=2, default=0)
shipping_location = models.ForeignKey("Ubigeo", verbose_name=u"Ubigeo")
shipping_address = models.TextField("Dirección de entrega", blank=True)
status = models.SmallIntegerField("Estado"
, choices=STATUS_CHOICES, default=0)
class Meta:
""" ."""
verbose_name = u'Pedido'
verbose_name_plural = u'Pedidos'
def __unicode__(self):
return "Orden # %s" % self.id
class OrderDetail(AuditableModel):
product = models.ForeignKey(Product, verbose_name=u"Producto")
order = models.ForeignKey(Order)
quantity = models.PositiveIntegerField("Cantidad")
unit_price = models.DecimalField('Precio unitario', max_digits=12
, decimal_places=2, default=0)
total_price = models.DecimalField('Total', max_digits=12
, decimal_places=2, default=0)
class Meta:
""" ."""
verbose_name = u'Item'
verbose_name_plural = u'Items'
class Ubigeo(AuditableModel):
short_name = models.CharField("Nombre", max_length=70, editable=False)
state = models.CharField('Departamento', max_length=60)
province = models.CharField('Provincia', max_length=60, blank=True)
district = models.CharField('Distrito', max_length=60, blank=True)
shipping_cost = models.DecimalField('Costo de envío', max_digits=12
, decimal_places=2, default=0)
shipping_delivery_time = models.PositiveIntegerField('Tiempo de entrega'
, default=0)
class Meta:
""" ."""
verbose_name = u'Ubigeo'
verbose_name_plural = u'Ubigeo'
def __unicode__(self):
return self.short_name
def save(self, *args, **kwargs):
""" ."""
# Genera slug
self.short_name = '%s' % self.ubigeo_full()
super(Ubigeo, self).save(*args, **kwargs)
def ubigeo_full(self):
full = u''
full += self.state or ''
full += ' | %s' % self.province if self.province else ''
full += ' | %s' % self.district if self.district else ''
return full
class Video(AuditableModel):
title = models.CharField("Título", max_length=120)
url = models.CharField("URL", max_length=250)
descrip = models.TextField("Descripción", blank=True)
def __unicode__(self):
return self.title
def get_video_id(self):
url = self.url
url_data = urlparse.urlparse(url)
query = urlparse.parse_qs(url_data.query)
video_id = None
if "v" in query:
video_id = query["v"][0]
return video_id
def get_video_image_url(self, hq=False):
url = self.url
video_id = self.get_video_id()
quality = 'default'
if hq:
quality = 'hqdefault'
return "http://img.youtube.com/vi/%s/%s.jpg" % (video_id, quality)
def get_video_image_url_hq(self):
return self.get_video_image_url(True)
def create_video_thumb(self):
# TODO
pass
def product_image_create_thumbs(sender, **kwargs):
img = kwargs['instance']
img_path = str(img.name)
basename = "prod_%s.png" % str(img.id).rjust(6, '0')
img_file = "{0}/{1}".format(settings.MEDIA_ROOT, img_path)
if os.path.exists(img_file) == False:
img.product.update_main_image()
return True
img_thumb = "{0}/products/thumb/{1}".format(settings.MEDIA_ROOT, basename)
img_normal = "{0}/products/normal/{1}".format(settings.MEDIA_ROOT, basename)
img_large = "{0}/products/large/{1}".format(settings.MEDIA_ROOT, basename)
try:
img1 = Image.open(img_file)
img1.thumbnail(settings.IMG_SIZE_THUMB, True)
img1.save(img_thumb)
img2 = Image.open(img_file)
img2.thumbnail(settings.IMG_SIZE_NORMAL, True)
img2.save(img_normal)
img3 = Image.open(img_file)
img3.thumbnail(settings.IMG_SIZE_LARGE, True)
img3.save(img_large)
ProductImage.objects.filter(id=img.id).update(name=basename)
os.unlink(img_file)
except Exception as ex:
img.delete()
return False
img.product.update_main_image()
def banner_image_create_thumbs(sender, **kwargs):
img = kwargs['instance']
img_path = str(img.image)
basename = "banner_%s.png" % str(img.id).rjust(6, '0')
img_file = "{0}/{1}".format(settings.MEDIA_ROOT, img_path)
if os.path.exists(img_file) == False:
return True
img_normal = "{0}/banner/normal/{1}".format(settings.MEDIA_ROOT, basename)
try:
img2 = Image.open(img_file)
img2.thumbnail(settings.BANNER_SIZE_NORMAL, True)
img2.save(img_normal)
Banner.objects.filter(id=img.id).update(image=basename)
os.unlink(img_file)
except Exception as ex:
img.delete()
return False
post_save.connect(product_image_create_thumbs, ProductImage)
post_save.connect(banner_image_create_thumbs, Banner)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment