ENV LANGUAGE fr_FR:fr
ENV LC_ALL fr_FR.UTF-8
-RUN mkdir /code
+RUN mkdir /opt/app
RUN mkdir /opt/src
+WORKDIR /opt/app
-WORKDIR /code
-
-ADD requirements.txt /code/
+ADD requirements.txt /opt/app/
RUN pip install -r requirements.txt
-ADD requirements-dev.txt /code/
+ADD requirements-dev.txt /opt/app/
RUN pip install -r requirements-dev.txt --src /opt/src
-ADD . /code/
+ADD app /opt/app/
--- /dev/null
+# Poll Twitter every 5 minutes
+# Comment-out if you don't use Mezzanine's Twitter app
+*/5 * * * * %(user)s %(manage)s poll_twitter
--- /dev/null
+from __future__ import unicode_literals
+import multiprocessing
+
+bind = "unix:%(proj_path)s/gunicorn.sock"
+workers = %(num_workers)s
+errorlog = "/home/%(user)s/logs/%(proj_name)s_error.log"
+loglevel = "error"
+proc_name = "%(proj_name)s"
--- /dev/null
+from __future__ import unicode_literals
+
+SECRET_KEY = "%(secret_key)s"
+NEVERCACHE_KEY = "%(nevercache_key)s"
+ALLOWED_HOSTS = [%(domains_python)s]
+
+DATABASES = {
+ "default": {
+ # Ends with "postgresql_psycopg2", "mysql", "sqlite3" or "oracle".
+ "ENGINE": "django.db.backends.postgresql_psycopg2",
+ # DB name or path to database file if using sqlite3.
+ "NAME": "%(proj_name)s",
+ # Not used with sqlite3.
+ "USER": "%(proj_name)s",
+ # Not used with sqlite3.
+ "PASSWORD": "%(db_pass)s",
+ # Set to empty string for localhost. Not used with sqlite3.
+ "HOST": "127.0.0.1",
+ # Set to empty string for default. Not used with sqlite3.
+ "PORT": "",
+ }
+}
+
+SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTOCOL", "https")
+
+CACHE_MIDDLEWARE_SECONDS = 60
+
+CACHE_MIDDLEWARE_KEY_PREFIX = "%(proj_name)s"
+
+CACHES = {
+ "default": {
+ "BACKEND": "django.core.cache.backends.memcached.MemcachedCache",
+ "LOCATION": "127.0.0.1:11211",
+ }
+}
+
+SESSION_ENGINE = "django.contrib.sessions.backends.cache"
--- /dev/null
+server_tokens off;
+
+server {
+ listen 80;
+ server_name nginx;
+ charset utf-8;
+
+ access_log /var/log/nginx/app-access.log;
+ error_log /var/log/nginx/app-error.log;
+
+ # max upload size
+ client_max_body_size 4096M; # adjust to taste
+
+ # Django media
+ location /media {
+ alias /opt/media; # your Django project's media files - amend as required
+ autoindex on;
+ }
+ # Django static
+ location /static {
+ alias /opt/static; # your Django project's static files - amend as required
+ autoindex on;
+ }
+
+ location / {
+ uwsgi_pass app:8000;
+ include /etc/nginx/uwsgi_params;
+ }
+}
--- /dev/null
+
+upstream %(proj_name)s {
+ server unix:%(proj_path)s/gunicorn.sock fail_timeout=0;
+}
+
+server {
+
+ listen 80;
+ %(ssl_disabled)s listen 443 ssl;
+ server_name %(domains_nginx)s;
+ client_max_body_size 10M;
+ keepalive_timeout 15;
+ error_log /home/%(user)s/logs/%(proj_name)s_error_nginx.log info;
+
+ %(ssl_disabled)s ssl_certificate conf/%(proj_name)s.crt;
+ %(ssl_disabled)s ssl_certificate_key conf/%(proj_name)s.key;
+ %(ssl_disabled)s ssl_session_cache shared:SSL:10m;
+ %(ssl_disabled)s ssl_session_timeout 10m;
+ %(ssl_disabled)s ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA;
+ %(ssl_disabled)s ssl_prefer_server_ciphers on;
+
+ # Deny illegal Host headers
+ if ($host !~* ^(%(domains_regex)s)$) {
+ return 444;
+ }
+
+ location / {
+ proxy_redirect off;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Protocol $scheme;
+ proxy_pass http://%(proj_name)s;
+ }
+
+ location /static/ {
+ root %(proj_path)s;
+ access_log off;
+ log_not_found off;
+ expires 30d;
+ }
+
+ location /robots.txt {
+ root %(proj_path)s/static;
+ access_log off;
+ log_not_found off;
+ }
+
+ location /favicon.ico {
+ root %(proj_path)s/static/img;
+ access_log off;
+ log_not_found off;
+ }
+
+}
--- /dev/null
+#!/bin/sh
+
+# paths
+root='/opt'
+sandbox=$root'/app/app'
+manage=$sandbox'/manage.py'
+wsgi=$sandbox'/wsgi.py'
+static=$root'/static/'
+media=$root'/media/'
+
+# waiting for other services
+sh $sandbox/deploy/wait.sh
+
+# django init
+python $manage migrate --noinput
+python $manage collectstatic --noinput
+
+# static files auto update
+watchmedo shell-command --patterns="*.js;*.css" --recursive \
+ --command='python '$manage' collectstatic --noinput' $static &
+
+# app start
+uwsgi --socket :8000 --wsgi-file $wsgi --chdir $sandbox --master --processes 4 --threads 2 --py-autoreload 3
+
+#python $manage runserver 0.0.0.0:8000
--- /dev/null
+[program:gunicorn_%(proj_name)s]
+command=%(venv_path)s/bin/gunicorn -c gunicorn.conf.py -p gunicorn.pid %(proj_app)s.wsgi:application
+directory=%(proj_path)s
+user=%(user)s
+autostart=true
+stdout_logfile = /home/%(user)s/logs/%(proj_name)s_supervisor
+autorestart=true
+redirect_stderr=true
+environment=LANG="%(locale)s",LC_ALL="%(locale)s",LC_LANG="%(locale)s"
--- /dev/null
+#!/bin/sh
+
+apt-get install -y --force-yes netcat
+
+set -e
+
+host=$(env | grep _TCP_ADDR | cut -d = -f 2)
+port=$(env | grep _TCP_PORT | cut -d = -f 2)
+
+echo -n "waiting for TCP connection to $host:$port..."
+
+while ! nc -w 1 $host $port 2>/dev/null
+do
+ echo -n .
+ sleep 1
+done
+
+echo 'ok'
\ No newline at end of file
--- /dev/null
+
+DEBUG = True
+
+# Make these unique, and don't share it with anybody.
+SECRET_KEY = "+3b01&_6_m@@yb4f06$s0zno8vkybh81nbuj_q(xzk+xeih1+s"
+NEVERCACHE_KEY = "l11tr%#!uc@+%$51(&+%=&z6h9yrw42(jpcj$3_&6evtu6hl%z"
+
+DATABASES = {
+ 'default': {
+ 'ENGINE': 'django.db.backends.mysql',
+ 'NAME': 'diggersdigest',
+ 'USER': 'digger',
+ 'PASSWORD': 'admin',
+ 'HOST': 'db',
+ 'PORT': 3306,
+ }
+}
+
+# EXTENSIONS AND FORMATS
+# Allowed Extensions for File Upload. Lower case is important.
+FILEBROWSER_EXTENSIONS = {
+ 'Folder': [''],
+ 'Image': ['.jpg', '.jpeg', '.gif', '.png', '.tif', '.tiff'],
+ 'Document': ['.pdf', '.doc', '.rtf', '.txt', '.xls', '.csv', '.docx'],
+ 'Video': ['.mov', '.wmv', '.mpeg', '.mpg', '.avi', '.rm'],
+ 'Audio': ['.mp3', '.mp4', '.wav', '.aiff', '.midi', '.m4p']
+ }
+# Define different formats for allowed selections.
+# This has to be a subset of EXTENSIONS.
+# e.g., add ?type=image to the browse-URL ...
+FILEBROWSER_SELECT_FORMATS = {
+ 'File': ['Folder', 'Document'],
+ 'Image': ['Image'],
+ 'Media': ['Video', 'Audio'],
+ 'Audio': ['Audio'],
+ 'Document': ['Document'],
+ # for TinyMCE we can also define lower-case items
+ 'image': ['Image'],
+ 'file': ['Folder', 'Image', 'Document'],
+ 'media': ['Video', 'Audio'],
+ 'audio': ['Audio'],
+}
+
+###################
+# DEPLOY SETTINGS #
+###################
+
+# Domains for public site
+# ALLOWED_HOSTS = [""]
+
+# These settings are used by the default fabfile.py provided.
+# Check fabfile.py for defaults.
+
+# FABRIC = {
+# "DEPLOY_TOOL": "rsync", # Deploy with "git", "hg", or "rsync"
+# "SSH_USER": "", # VPS SSH username
+# "HOSTS": [""], # The IP address of your VPS
+# "DOMAINS": ALLOWED_HOSTS, # Edit domains in ALLOWED_HOSTS
+# "REQUIREMENTS_PATH": "requirements.txt", # Project's pip requirements
+# "LOCALE": "en_US.UTF-8", # Should end with ".UTF-8"
+# "DB_PASS": "", # Live database password
+# "ADMIN_PASS": "", # Live admin user password
+# "SECRET_KEY": SECRET_KEY,
+# "NEVERCACHE_KEY": NEVERCACHE_KEY,
+# }
--- /dev/null
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+import mezzanine.core.fields
+import mezzanine.utils.models
+from django.conf import settings
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('sites', '0001_initial'),
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='BlogCategory',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('title', models.CharField(max_length=500, verbose_name='Title')),
+ ('slug', models.CharField(help_text='Leave blank to have the URL auto-generated from the title.', max_length=2000, null=True, verbose_name='URL', blank=True)),
+ ('site', models.ForeignKey(editable=False, to='sites.Site')),
+ ],
+ options={
+ 'ordering': ('title',),
+ 'verbose_name': 'Blog Category',
+ 'verbose_name_plural': 'Blog Categories',
+ },
+ bases=(models.Model,),
+ ),
+ migrations.CreateModel(
+ name='BlogPost',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('comments_count', models.IntegerField(default=0, editable=False)),
+ ('keywords_string', models.CharField(max_length=500, editable=False, blank=True)),
+ ('rating_count', models.IntegerField(default=0, editable=False)),
+ ('rating_sum', models.IntegerField(default=0, editable=False)),
+ ('rating_average', models.FloatField(default=0, editable=False)),
+ ('title', models.CharField(max_length=500, verbose_name='Title')),
+ ('slug', models.CharField(help_text='Leave blank to have the URL auto-generated from the title.', max_length=2000, null=True, verbose_name='URL', blank=True)),
+ ('_meta_title', models.CharField(help_text='Optional title to be used in the HTML title tag. If left blank, the main title field will be used.', max_length=500, null=True, verbose_name='Title', blank=True)),
+ ('description', models.TextField(verbose_name='Description', blank=True)),
+ ('gen_description', models.BooleanField(default=True, help_text='If checked, the description will be automatically generated from content. Uncheck if you want to manually set a custom description.', verbose_name='Generate description')),
+ ('created', models.DateTimeField(null=True, editable=False)),
+ ('updated', models.DateTimeField(null=True, editable=False)),
+ ('status', models.IntegerField(default=2, help_text='With Draft chosen, will only be shown for admin users on the site.', verbose_name='Status', choices=[(1, 'Draft'), (2, 'Published')])),
+ ('publish_date', models.DateTimeField(help_text="With Published chosen, won't be shown until this time", null=True, verbose_name='Published from', blank=True)),
+ ('expiry_date', models.DateTimeField(help_text="With Published chosen, won't be shown after this time", null=True, verbose_name='Expires on', blank=True)),
+ ('short_url', models.URLField(null=True, blank=True)),
+ ('in_sitemap', models.BooleanField(default=True, verbose_name='Show in sitemap')),
+ ('content', mezzanine.core.fields.RichTextField(verbose_name='Content')),
+ ('allow_comments', models.BooleanField(default=True, verbose_name='Allow comments')),
+ ('featured_image', mezzanine.core.fields.FileField(max_length=255, null=True, verbose_name='Featured Image', blank=True)),
+ ('categories', models.ManyToManyField(related_name='blogposts', verbose_name='Categories', to='blog.BlogCategory', blank=True)),
+ ('related_posts', models.ManyToManyField(related_name='related_posts_rel_+', verbose_name='Related posts', to='blog.BlogPost', blank=True)),
+ ('site', models.ForeignKey(editable=False, to='sites.Site')),
+ ('user', models.ForeignKey(related_name='blogposts', verbose_name='Author', to=settings.AUTH_USER_MODEL)),
+ ],
+ options={
+ 'ordering': ('-publish_date',),
+ 'verbose_name': 'Blog post',
+ 'verbose_name_plural': 'Blog posts',
+ },
+ bases=(models.Model, mezzanine.utils.models.AdminThumbMixin),
+ ),
+ ]
--- /dev/null
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('blog', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='blogpost',
+ name='publish_date',
+ field=models.DateTimeField(help_text="With Published chosen, won't be shown until this time", null=True, verbose_name='Published from', db_index=True, blank=True),
+ ),
+ ]
--- /dev/null
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('shop', '0003_auto_20150906_1911'),
+ ('blog', '0002_auto_20150527_1555'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='blogpost',
+ name='related_products',
+ field=models.ManyToManyField(to='shop.Product', verbose_name=b'Related products', blank=True),
+ ),
+ ]
--- /dev/null
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+from decimal import Decimal
+import mezzanine.utils.models
+import django.db.models.deletion
+import mezzanine.core.fields
+import cartridge.shop.fields
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('pages', '0003_auto_20150527_1555'),
+ ('sites', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Cart',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('last_updated', models.DateTimeField(null=True, verbose_name='Last updated')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='CartItem',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('sku', cartridge.shop.fields.SKUField(max_length=20, verbose_name='SKU')),
+ ('description', models.CharField(max_length=2000, verbose_name='Description')),
+ ('quantity', models.IntegerField(default=0, verbose_name='Quantity')),
+ ('unit_price', cartridge.shop.fields.MoneyField(decimal_places=2, default=Decimal('0'), max_digits=10, blank=True, null=True, verbose_name='Unit price')),
+ ('total_price', cartridge.shop.fields.MoneyField(decimal_places=2, default=Decimal('0'), max_digits=10, blank=True, null=True, verbose_name='Total price')),
+ ('url', models.CharField(max_length=2000)),
+ ('image', models.CharField(max_length=200, null=True)),
+ ('cart', models.ForeignKey(related_name='items', to='shop.Cart')),
+ ],
+ options={
+ 'abstract': False,
+ },
+ ),
+ migrations.CreateModel(
+ name='Category',
+ fields=[
+ ('page_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='pages.Page')),
+ ('content', mezzanine.core.fields.RichTextField(verbose_name='Content')),
+ ('featured_image', mezzanine.core.fields.FileField(max_length=255, null=True, verbose_name='Featured Image', blank=True)),
+ ('price_min', cartridge.shop.fields.MoneyField(null=True, verbose_name='Minimum price', max_digits=10, decimal_places=2, blank=True)),
+ ('price_max', cartridge.shop.fields.MoneyField(null=True, verbose_name='Maximum price', max_digits=10, decimal_places=2, blank=True)),
+ ('combined', models.BooleanField(default=True, help_text='If checked, products must match all specified filters, otherwise products can match any specified filter.', verbose_name='Combined')),
+ ],
+ options={
+ 'ordering': ('_order',),
+ 'verbose_name': 'Product category',
+ 'verbose_name_plural': 'Product categories',
+ },
+ bases=('pages.page', models.Model),
+ ),
+ migrations.CreateModel(
+ name='DiscountCode',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('title', models.CharField(max_length=100, verbose_name='Title')),
+ ('active', models.BooleanField(default=False, verbose_name='Active')),
+ ('discount_deduct', cartridge.shop.fields.MoneyField(null=True, verbose_name='Reduce by amount', max_digits=10, decimal_places=2, blank=True)),
+ ('discount_percent', cartridge.shop.fields.PercentageField(null=True, verbose_name='Reduce by percent', max_digits=5, decimal_places=2, blank=True)),
+ ('discount_exact', cartridge.shop.fields.MoneyField(null=True, verbose_name='Reduce to amount', max_digits=10, decimal_places=2, blank=True)),
+ ('valid_from', models.DateTimeField(null=True, verbose_name='Valid from', blank=True)),
+ ('valid_to', models.DateTimeField(null=True, verbose_name='Valid to', blank=True)),
+ ('code', cartridge.shop.fields.DiscountCodeField(unique=True, max_length=20, verbose_name='Code')),
+ ('min_purchase', cartridge.shop.fields.MoneyField(null=True, verbose_name='Minimum total purchase', max_digits=10, decimal_places=2, blank=True)),
+ ('free_shipping', models.BooleanField(default=False, verbose_name='Free shipping')),
+ ('uses_remaining', models.IntegerField(help_text='If you wish to limit the number of times a code may be used, set this value. It will be decremented upon each use.', null=True, verbose_name='Uses remaining', blank=True)),
+ ('categories', models.ManyToManyField(related_name='discountcode_related', verbose_name='Categories', to='shop.Category', blank=True)),
+ ],
+ options={
+ 'verbose_name': 'Discount code',
+ 'verbose_name_plural': 'Discount codes',
+ },
+ ),
+ migrations.CreateModel(
+ name='Order',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('billing_detail_first_name', models.CharField(max_length=100, verbose_name='First name')),
+ ('billing_detail_last_name', models.CharField(max_length=100, verbose_name='Last name')),
+ ('billing_detail_street', models.CharField(max_length=100, verbose_name='Street')),
+ ('billing_detail_city', models.CharField(max_length=100, verbose_name='City/Suburb')),
+ ('billing_detail_state', models.CharField(max_length=100, verbose_name='State/Region')),
+ ('billing_detail_postcode', models.CharField(max_length=10, verbose_name='Zip/Postcode')),
+ ('billing_detail_country', models.CharField(max_length=100, verbose_name='Country')),
+ ('billing_detail_phone', models.CharField(max_length=20, verbose_name='Phone')),
+ ('billing_detail_email', models.EmailField(max_length=254, verbose_name='Email')),
+ ('shipping_detail_first_name', models.CharField(max_length=100, verbose_name='First name')),
+ ('shipping_detail_last_name', models.CharField(max_length=100, verbose_name='Last name')),
+ ('shipping_detail_street', models.CharField(max_length=100, verbose_name='Street')),
+ ('shipping_detail_city', models.CharField(max_length=100, verbose_name='City/Suburb')),
+ ('shipping_detail_state', models.CharField(max_length=100, verbose_name='State/Region')),
+ ('shipping_detail_postcode', models.CharField(max_length=10, verbose_name='Zip/Postcode')),
+ ('shipping_detail_country', models.CharField(max_length=100, verbose_name='Country')),
+ ('shipping_detail_phone', models.CharField(max_length=20, verbose_name='Phone')),
+ ('additional_instructions', models.TextField(verbose_name='Additional instructions', blank=True)),
+ ('time', models.DateTimeField(auto_now_add=True, verbose_name='Time', null=True)),
+ ('key', models.CharField(max_length=40)),
+ ('user_id', models.IntegerField(null=True, blank=True)),
+ ('shipping_type', models.CharField(max_length=50, verbose_name='Shipping type', blank=True)),
+ ('shipping_total', cartridge.shop.fields.MoneyField(null=True, verbose_name='Shipping total', max_digits=10, decimal_places=2, blank=True)),
+ ('tax_type', models.CharField(max_length=50, verbose_name='Tax type', blank=True)),
+ ('tax_total', cartridge.shop.fields.MoneyField(null=True, verbose_name='Tax total', max_digits=10, decimal_places=2, blank=True)),
+ ('item_total', cartridge.shop.fields.MoneyField(null=True, verbose_name='Item total', max_digits=10, decimal_places=2, blank=True)),
+ ('discount_code', cartridge.shop.fields.DiscountCodeField(max_length=20, verbose_name='Discount code', blank=True)),
+ ('discount_total', cartridge.shop.fields.MoneyField(null=True, verbose_name='Discount total', max_digits=10, decimal_places=2, blank=True)),
+ ('total', cartridge.shop.fields.MoneyField(null=True, verbose_name='Order total', max_digits=10, decimal_places=2, blank=True)),
+ ('transaction_id', models.CharField(max_length=255, null=True, verbose_name='Transaction ID', blank=True)),
+ ('status', models.IntegerField(default=1, verbose_name='Status', choices=[(1, 'Unprocessed'), (2, 'Processed')])),
+ ('site', models.ForeignKey(editable=False, to='sites.Site')),
+ ],
+ options={
+ 'ordering': ('-id',),
+ 'verbose_name': 'Order',
+ 'verbose_name_plural': 'Orders',
+ },
+ ),
+ migrations.CreateModel(
+ name='OrderItem',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('sku', cartridge.shop.fields.SKUField(max_length=20, verbose_name='SKU')),
+ ('description', models.CharField(max_length=2000, verbose_name='Description')),
+ ('quantity', models.IntegerField(default=0, verbose_name='Quantity')),
+ ('unit_price', cartridge.shop.fields.MoneyField(decimal_places=2, default=Decimal('0'), max_digits=10, blank=True, null=True, verbose_name='Unit price')),
+ ('total_price', cartridge.shop.fields.MoneyField(decimal_places=2, default=Decimal('0'), max_digits=10, blank=True, null=True, verbose_name='Total price')),
+ ('order', models.ForeignKey(related_name='items', to='shop.Order')),
+ ],
+ options={
+ 'abstract': False,
+ },
+ ),
+ migrations.CreateModel(
+ name='Product',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('keywords_string', models.CharField(max_length=500, editable=False, blank=True)),
+ ('rating_count', models.IntegerField(default=0, editable=False)),
+ ('rating_sum', models.IntegerField(default=0, editable=False)),
+ ('rating_average', models.FloatField(default=0, editable=False)),
+ ('title', models.CharField(max_length=500, verbose_name='Title')),
+ ('slug', models.CharField(help_text='Leave blank to have the URL auto-generated from the title.', max_length=2000, null=True, verbose_name='URL', blank=True)),
+ ('_meta_title', models.CharField(help_text='Optional title to be used in the HTML title tag. If left blank, the main title field will be used.', max_length=500, null=True, verbose_name='Title', blank=True)),
+ ('description', models.TextField(verbose_name='Description', blank=True)),
+ ('gen_description', models.BooleanField(default=True, help_text='If checked, the description will be automatically generated from content. Uncheck if you want to manually set a custom description.', verbose_name='Generate description')),
+ ('created', models.DateTimeField(null=True, editable=False)),
+ ('updated', models.DateTimeField(null=True, editable=False)),
+ ('status', models.IntegerField(default=2, help_text='With Draft chosen, will only be shown for admin users on the site.', verbose_name='Status', choices=[(1, 'Draft'), (2, 'Published')])),
+ ('publish_date', models.DateTimeField(help_text="With Published chosen, won't be shown until this time", null=True, verbose_name='Published from', db_index=True, blank=True)),
+ ('expiry_date', models.DateTimeField(help_text="With Published chosen, won't be shown after this time", null=True, verbose_name='Expires on', blank=True)),
+ ('short_url', models.URLField(null=True, blank=True)),
+ ('in_sitemap', models.BooleanField(default=True, verbose_name='Show in sitemap')),
+ ('content', mezzanine.core.fields.RichTextField(verbose_name='Content')),
+ ('unit_price', cartridge.shop.fields.MoneyField(null=True, verbose_name='Unit price', max_digits=10, decimal_places=2, blank=True)),
+ ('sale_id', models.IntegerField(null=True)),
+ ('sale_price', cartridge.shop.fields.MoneyField(null=True, verbose_name='Sale price', max_digits=10, decimal_places=2, blank=True)),
+ ('sale_from', models.DateTimeField(null=True, verbose_name='Sale start', blank=True)),
+ ('sale_to', models.DateTimeField(null=True, verbose_name='Sale end', blank=True)),
+ ('sku', cartridge.shop.fields.SKUField(max_length=20, unique=True, null=True, verbose_name='SKU', blank=True)),
+ ('num_in_stock', models.IntegerField(null=True, verbose_name='Number in stock', blank=True)),
+ ('available', models.BooleanField(default=False, verbose_name='Available for purchase')),
+ ('image', models.CharField(max_length=100, null=True, verbose_name='Image', blank=True)),
+ ('date_added', models.DateTimeField(auto_now_add=True, verbose_name='Date added', null=True)),
+ ('categories', models.ManyToManyField(to='shop.Category', verbose_name='Product categories', blank=True)),
+ ('related_products', models.ManyToManyField(related_name='related_products_rel_+', verbose_name='Related products', to='shop.Product', blank=True)),
+ ('site', models.ForeignKey(editable=False, to='sites.Site')),
+ ('upsell_products', models.ManyToManyField(related_name='upsell_products_rel_+', verbose_name='Upsell products', to='shop.Product', blank=True)),
+ ],
+ options={
+ 'verbose_name': 'Product',
+ 'verbose_name_plural': 'Products',
+ },
+ bases=(models.Model, mezzanine.utils.models.AdminThumbMixin),
+ ),
+ migrations.CreateModel(
+ name='ProductAction',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('timestamp', models.IntegerField()),
+ ('total_cart', models.IntegerField(default=0)),
+ ('total_purchase', models.IntegerField(default=0)),
+ ('product', models.ForeignKey(related_name='actions', to='shop.Product')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='ProductImage',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('_order', mezzanine.core.fields.OrderField(null=True, verbose_name='Order')),
+ ('file', mezzanine.core.fields.FileField(max_length=255, verbose_name='Image')),
+ ('description', models.CharField(max_length=100, verbose_name='Description', blank=True)),
+ ('product', models.ForeignKey(related_name='images', to='shop.Product')),
+ ],
+ options={
+ 'ordering': ('_order',),
+ 'verbose_name': 'Image',
+ 'verbose_name_plural': 'Images',
+ },
+ ),
+ migrations.CreateModel(
+ name='ProductOption',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('type', models.IntegerField(verbose_name='Type', choices=[(1, 'Cover condition'), (2, 'Vinyl condition')])),
+ ('name', cartridge.shop.fields.OptionField(max_length=50, null=True, verbose_name='Name')),
+ ],
+ options={
+ 'verbose_name': 'Product option',
+ 'verbose_name_plural': 'Product options',
+ },
+ ),
+ migrations.CreateModel(
+ name='ProductVariation',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('unit_price', cartridge.shop.fields.MoneyField(null=True, verbose_name='Unit price', max_digits=10, decimal_places=2, blank=True)),
+ ('sale_id', models.IntegerField(null=True)),
+ ('sale_price', cartridge.shop.fields.MoneyField(null=True, verbose_name='Sale price', max_digits=10, decimal_places=2, blank=True)),
+ ('sale_from', models.DateTimeField(null=True, verbose_name='Sale start', blank=True)),
+ ('sale_to', models.DateTimeField(null=True, verbose_name='Sale end', blank=True)),
+ ('sku', cartridge.shop.fields.SKUField(max_length=20, unique=True, null=True, verbose_name='SKU', blank=True)),
+ ('num_in_stock', models.IntegerField(null=True, verbose_name='Number in stock', blank=True)),
+ ('default', models.BooleanField(default=False, verbose_name='Default')),
+ ('option1', cartridge.shop.fields.OptionField(max_length=50, null=True, verbose_name='Cover condition')),
+ ('option2', cartridge.shop.fields.OptionField(max_length=50, null=True, verbose_name='Vinyl condition')),
+ ('image', models.ForeignKey(on_delete=django.db.models.deletion.SET_NULL, verbose_name='Image', blank=True, to='shop.ProductImage', null=True)),
+ ('product', models.ForeignKey(related_name='variations', to='shop.Product')),
+ ],
+ options={
+ 'ordering': ('-default',),
+ },
+ ),
+ migrations.CreateModel(
+ name='Sale',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('title', models.CharField(max_length=100, verbose_name='Title')),
+ ('active', models.BooleanField(default=False, verbose_name='Active')),
+ ('discount_deduct', cartridge.shop.fields.MoneyField(null=True, verbose_name='Reduce by amount', max_digits=10, decimal_places=2, blank=True)),
+ ('discount_percent', cartridge.shop.fields.PercentageField(null=True, verbose_name='Reduce by percent', max_digits=5, decimal_places=2, blank=True)),
+ ('discount_exact', cartridge.shop.fields.MoneyField(null=True, verbose_name='Reduce to amount', max_digits=10, decimal_places=2, blank=True)),
+ ('valid_from', models.DateTimeField(null=True, verbose_name='Valid from', blank=True)),
+ ('valid_to', models.DateTimeField(null=True, verbose_name='Valid to', blank=True)),
+ ('categories', models.ManyToManyField(related_name='sale_related', verbose_name='Categories', to='shop.Category', blank=True)),
+ ('products', models.ManyToManyField(to='shop.Product', verbose_name='Products', blank=True)),
+ ],
+ options={
+ 'verbose_name': 'Sale',
+ 'verbose_name_plural': 'Sales',
+ },
+ ),
+ migrations.AddField(
+ model_name='discountcode',
+ name='products',
+ field=models.ManyToManyField(to='shop.Product', verbose_name='Products', blank=True),
+ ),
+ migrations.AddField(
+ model_name='category',
+ name='options',
+ field=models.ManyToManyField(related_name='product_options', verbose_name='Product options', to='shop.ProductOption', blank=True),
+ ),
+ migrations.AddField(
+ model_name='category',
+ name='products',
+ field=models.ManyToManyField(to='shop.Product', verbose_name='Products', blank=True),
+ ),
+ migrations.AddField(
+ model_name='category',
+ name='sale',
+ field=models.ForeignKey(verbose_name='Sale', blank=True, to='shop.Sale', null=True),
+ ),
+ migrations.AlterUniqueTogether(
+ name='productaction',
+ unique_together=set([('product', 'timestamp')]),
+ ),
+ ]
--- /dev/null
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('shop', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='order',
+ name='callback_uuid',
+ field=models.CharField(default=0, max_length=36),
+ preserve_default=False,
+ ),
+ ]
--- /dev/null
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+import cartridge.shop.fields
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('shop', '0002_order_callback_uuid'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='productoption',
+ name='type',
+ field=models.IntegerField(verbose_name='Type', choices=[(1, 'Size'), (2, 'Colour')]),
+ ),
+ migrations.AlterField(
+ model_name='productvariation',
+ name='option1',
+ field=cartridge.shop.fields.OptionField(max_length=50, null=True, verbose_name='Size'),
+ ),
+ migrations.AlterField(
+ model_name='productvariation',
+ name='option2',
+ field=cartridge.shop.fields.OptionField(max_length=50, null=True, verbose_name='Colour'),
+ ),
+ ]
--- /dev/null
+
+from __future__ import absolute_import, unicode_literals
+import os
+from django.utils.translation import ugettext_lazy as _
+
+
+######################
+# MEZZANINE SETTINGS #
+######################
+
+# The following settings are already defined with default values in
+# the ``defaults.py`` module within each of Mezzanine's apps, but are
+# common enough to be put here, commented out, for conveniently
+# overriding. Please consult the settings documentation for a full list
+# of settings Mezzanine implements:
+# http://mezzanine.jupo.org/docs/configuration.html#default-settings
+
+# Controls the ordering and grouping of the admin menu.
+#
+# ADMIN_MENU_ORDER = (
+# ("Content", ("pages.Page", "blog.BlogPost",
+# "generic.ThreadedComment", (_("Media Library"), "fb_browse"),)),
+# (_("Shop"), ("shop.Product", "shop.ProductOption", "shop.DiscountCode",
+# "shop.Sale", "shop.Order")),
+# ("Site", ("sites.Site", "redirects.Redirect", "conf.Setting")),
+# ("Users", ("auth.User", "auth.Group",)),
+# )
+
+# A three item sequence, each containing a sequence of template tags
+# used to render the admin dashboard.
+#
+# DASHBOARD_TAGS = (
+# ("blog_tags.quick_blog", "mezzanine_tags.app_list"),
+# ("comment_tags.recent_comments",),
+# ("mezzanine_tags.recent_actions",),
+# )
+
+# A sequence of templates used by the ``page_menu`` template tag. Each
+# item in the sequence is a three item sequence, containing a unique ID
+# for the template, a label for the template, and the template path.
+# These templates are then available for selection when editing which
+# menus a page should appear in. Note that if a menu template is used
+# that doesn't appear in this setting, all pages will appear in it.
+
+PAGE_MENU_TEMPLATES = (
+ (1, _("Top navigation bar"), "pages/menus/dropdown.html"),
+ # (2, _("Left-hand tree"), "pages/menus/tree.html"),
+ # (3, _("Footer"), "pages/menus/footer.html"),
+)
+
+# A sequence of fields that will be injected into Mezzanine's (or any
+# library's) models. Each item in the sequence is a four item sequence.
+# The first two items are the dotted path to the model and its field
+# name to be added, and the dotted path to the field class to use for
+# the field. The third and fourth items are a sequence of positional
+# args and a dictionary of keyword args, to use when creating the
+# field instance. When specifying the field class, the path
+# ``django.models.db.`` can be omitted for regular Django model fields.
+#
+
+EXTRA_MODEL_FIELDS = (
+ (
+ # Dotted path to field.# Dotted path to field.
+ "mezzanine.blog.models.BlogPost.related_products",
+ # Dotted path to field class.
+ "django.db.models.ManyToManyField",
+ # Positional args for field class.
+ ("shop.Product",),
+ # Keyword args for field class.
+ {"verbose_name": ("Related products"), "blank": True},
+ ),
+ # Add the callback_uuid field to orders. This field is helpful for identifying
+ # orders being checked out.
+ (
+ "cartridge.shop.models.Order.callback_uuid",
+ "django.db.models.CharField",
+ (),
+ {"blank" : False, "max_length" : 36},
+ ),
+ # ...
+ # # Example of adding a field to *all* of Mezzanine's content types:
+ # (
+ # "mezzanine.pages.models.Page.another_field",
+ # "IntegerField", # 'django.db.models.' is implied if path is omitted.
+ # (_("Another name"),),
+ # {"blank": True, "default": 1},
+ # ),
+ )
+
+# Setting to turn on featured images for blog posts. Defaults to False.
+#
+BLOG_USE_FEATURED_IMAGE = True
+
+# If True, the django-modeltranslation will be added to the
+# INSTALLED_APPS setting.
+USE_MODELTRANSLATION = False
+
+SEARCH_MODEL_CHOICES = ('shop.Product',)
+
+
+######################
+# CARTRIDGE SETTINGS #
+######################
+
+# The following settings are already defined in cartridge.shop.defaults
+# with default values, but are common enough to be put here, commented
+# out, for conveniently overriding. Please consult the settings
+# documentation for a full list of settings Cartridge implements:
+# http://cartridge.jupo.org/configuration.html#default-settings
+
+# Sequence of available credit card types for payment.
+# SHOP_CARD_TYPES = ("Mastercard", "Visa", "Diners", "Amex")
+
+# Setting to turn on featured images for shop categories. Defaults to False.
+# SHOP_CATEGORY_USE_FEATURED_IMAGE = True
+
+# Set an alternative OrderForm class for the checkout process.
+# SHOP_CHECKOUT_FORM_CLASS = 'cartridge.shop.forms.OrderForm'
+
+# If True, the checkout process is split into separate
+# billing/shipping and payment steps.
+# SHOP_CHECKOUT_STEPS_SPLIT = True
+
+# If True, the checkout process has a final confirmation step before
+# completion.
+# SHOP_CHECKOUT_STEPS_CONFIRMATION = True
+
+# Controls the formatting of monetary values accord to the locale
+# module in the python standard library. If an empty string is
+# used, will fall back to the system's locale.
+#SHOP_CURRENCY_LOCALE = ''
+
+# Dotted package path and name of the function that
+# is called on submit of the billing/shipping checkout step. This
+# is where shipping calculation can be performed and set using the
+# function ``cartridge.shop.utils.set_shipping``.
+# SHOP_HANDLER_BILLING_SHIPPING = \
+# "cartridge.shop.checkout.default_billship_handler"
+
+# Dotted package path and name of the function that
+# is called once an order is successful and all of the order
+# object's data has been created. This is where any custom order
+# processing should be implemented.
+# SHOP_HANDLER_ORDER = "cartridge.shop.checkout.default_order_handler"
+
+# Dotted package path and name of the function that
+# is called on submit of the payment checkout step. This is where
+# integration with a payment gateway should be implemented.
+# SHOP_HANDLER_PAYMENT = "cartridge.shop.checkout.default_payment_handler"
+
+# Sequence of value/name pairs for order statuses.
+# SHOP_ORDER_STATUS_CHOICES = (
+# (1, "Unprocessed"),
+# (2, "Processed"),
+# )
+
+# Sequence of value/name pairs for types of product options,
+# eg Size, Colour. NOTE: Increasing the number of these will
+# require database migrations!
+#SHOP_OPTION_TYPE_CHOICES = (
+# (1, "Cover condition"),
+# (2, "Vinyl condition"),
+# )
+
+SHOP_USE_VARIATIONS = False
+
+# Sequence of indexes from the SHOP_OPTION_TYPE_CHOICES setting that
+# control how the options should be ordered in the admin,
+# SHOP_OPTION_ADMIN_ORDER = (1, 2)
+
+SHOP_USE_RATINGS = False
+
+# Add Migration Module path see : https://github.com/stephenmcd/mezzanine/blob/master/docs/model-customization.rst#field-injection-caveats
+MIGRATION_MODULES = {
+ "shop": "diggersdigest.migrations.shop",
+ "blog": "diggersdigest.migrations.blog"
+}
+
+# USE or EXTEND the custom callback-uuid form
+SHOP_CHECKOUT_FORM_CLASS = 'payments.multipayments.forms.base.CallbackUUIDOrderForm'
+
+PRIMARY_PAYMENT_PROCESSOR_IN_USE = False
+
+SECONDARY_PAYMENT_PROCESSORS = (
+ ('paypal', {
+ 'name' : 'Pay With Pay-Pal',
+ 'form' : 'payments.multipayments.forms.paypal.PaypalSubmissionForm'
+ }),
+)
+
+
+# Currency type.
+PAYPAL_CURRENCY = "EUR"
+
+# Business account email. Sandbox emails look like this.
+PAYPAL_BUSINESS = 'pellerin@parisson.com'
+PAYPAL_RECEIVER_EMAIL = PAYPAL_BUSINESS
+
+# Use this to enable https on return URLs. This is strongly recommended! (Except for sandbox)
+PAYPAL_RETURN_WITH_HTTPS = False
+
+# Function that returns args for `reverse`.
+# URL is sent to PayPal as the for returning to a 'complete' landing page.
+PAYPAL_RETURN_URL = lambda cart, uuid, order_form: ('shop_complete', None, None)
+
+# Function that returns args for `reverse`.
+# URL is sent to PayPal as the URL to callback to for PayPal IPN.
+# Set to None if you do not wish to use IPN.
+PAYPAL_IPN_URL = lambda cart, uuid, order_form: ('paypal.standard.ipn.views.ipn', None, {})
+
+
+# URL the secondary-payment-form is submitted to
+# Dev example
+PAYPAL_SUBMIT_URL = 'https://www.sandbox.paypal.com/cgi-bin/webscr'
+# Prod example
+# PAYPAL_SUBMIT_URL = 'https://www.paypal.com/cgi-bin/webscr'
+
+# For real use set to False
+PAYPAL_TEST = True
+
+########################
+# MAIN DJANGO SETTINGS #
+########################
+
+# Hosts/domain names that are valid for this site; required if DEBUG is False
+# See https://docs.djangoproject.com/en/dev/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.
+# On Unix systems, a value of None will cause Django to use the same
+# timezone as the operating system.
+# If running in a Windows environment this must be set to the same as your
+# system time zone.
+TIME_ZONE = 'UTC'
+
+# If you set this to True, Django will use timezone-aware datetimes.
+USE_TZ = True
+
+# Language code for this installation. All choices can be found here:
+# http://www.i18nguy.com/unicode/language-identifiers.html
+LANGUAGE_CODE = "fr"
+
+# Supported languages
+LANGUAGES = (
+ ('fr', _('French')),
+ ('en', _('English')),
+)
+
+# A boolean that turns on/off debug mode. When set to ``True``, stack traces
+# are displayed for error pages. Should always be set to ``False`` in
+# production. Best set to ``True`` in local_settings.py
+DEBUG = False
+
+# Whether a user's session cookie expires when the Web browser is closed.
+SESSION_EXPIRE_AT_BROWSER_CLOSE = True
+
+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
+
+AUTHENTICATION_BACKENDS = ("mezzanine.core.auth_backends.MezzanineBackend",)
+
+# The numeric mode to set newly-uploaded files to. The value should be
+# a mode you'd pass directly to os.chmod.
+FILE_UPLOAD_PERMISSIONS = 0o644
+
+
+
+#############
+# DATABASES #
+#############
+
+DATABASES = {
+ "default": {
+ # Ends with "postgresql_psycopg2", "mysql", "sqlite3" or "oracle".
+ "ENGINE": "django.db.backends.sqlite3",
+ # DB name or path to database file if using sqlite3.
+ "NAME": "dev.db",
+ # Not used with sqlite3.
+ "USER": "",
+ # Not used with sqlite3.
+ "PASSWORD": "",
+ # Set to empty string for localhost. Not used with sqlite3.
+ "HOST": "",
+ # Set to empty string for default. Not used with sqlite3.
+ "PORT": "",
+ }
+}
+
+#########
+# PATHS #
+#########
+
+# Full filesystem path to the project.
+PROJECT_APP_PATH = os.path.dirname(os.path.abspath(__file__))
+PROJECT_APP = os.path.basename(PROJECT_APP_PATH)
+PROJECT_ROOT = BASE_DIR = os.path.dirname(PROJECT_APP_PATH)
+
+# Every cache key will get prefixed with this value - here we set it to
+# the name of the directory the project is in to try and use something
+# project specific.
+CACHE_MIDDLEWARE_KEY_PREFIX = PROJECT_APP
+
+# URL prefix for static files.
+# Example: "http://media.lawrence.com/static/"
+STATIC_URL = "/static/"
+
+# 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 = os.path.join(PROJECT_ROOT, STATIC_URL.strip("/"))
+STATIC_ROOT = '/opt/static/'
+
+# 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 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.strip("/").split("/"))
+MEDIA_ROOT = '/opt/media/'
+
+# Package/module name to import the root urlpatterns from for the project.
+ROOT_URLCONF = "%s.urls" % PROJECT_APP
+
+# 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.
+TEMPLATE_DIRS = (os.path.join(PROJECT_ROOT, "templates"),)
+
+
+################
+# APPLICATIONS #
+################
+
+INSTALLED_APPS = (
+ "django.contrib.admin",
+ "django.contrib.auth",
+ "django.contrib.contenttypes",
+ "django.contrib.redirects",
+ "django.contrib.sessions",
+ "django.contrib.sites",
+ "django.contrib.sitemaps",
+ "django.contrib.staticfiles",
+ "mezzanine.boot",
+ "mezzanine.conf",
+ "mezzanine.core",
+ "mezzanine.generic",
+ "mezzanine.pages",
+ "cartridge.shop",
+ "mezzanine.blog",
+ "mezzanine.forms",
+ "mezzanine.galleries",
+ "mezzanine.twitter",
+ "mezzanine.accounts",
+ # "mezzanine.mobile",
+ "records",
+ "payments.multipayments",
+ 'paypal.standard.ipn',
+)
+
+# List of processors used by RequestContext to populate the context.
+# Each one should be a callable that takes the request object as its
+# only parameter and returns a dictionary to add to the context.
+TEMPLATE_CONTEXT_PROCESSORS = (
+ "django.contrib.auth.context_processors.auth",
+ "django.contrib.messages.context_processors.messages",
+ "django.core.context_processors.debug",
+ "django.core.context_processors.i18n",
+ "django.core.context_processors.static",
+ "django.core.context_processors.media",
+ "django.core.context_processors.request",
+ "django.core.context_processors.tz",
+ "mezzanine.conf.context_processors.settings",
+ "mezzanine.pages.context_processors.page",
+ "payments.multipayments.context_processors.settings",
+)
+
+# List of middleware classes to use. Order is important; in the request phase,
+# these middleware classes will be applied in the order given, and in the
+# response phase the middleware will be applied in reverse order.
+MIDDLEWARE_CLASSES = (
+ "mezzanine.core.middleware.UpdateCacheMiddleware",
+
+ 'django.contrib.sessions.middleware.SessionMiddleware',
+ # Uncomment if using internationalisation or localisation
+ # 'django.middleware.locale.LocaleMiddleware',
+ 'django.middleware.common.CommonMiddleware',
+ 'django.middleware.csrf.CsrfViewMiddleware',
+ 'django.contrib.auth.middleware.AuthenticationMiddleware',
+ 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
+ 'django.contrib.messages.middleware.MessageMiddleware',
+ 'django.middleware.clickjacking.XFrameOptionsMiddleware',
+
+ "cartridge.shop.middleware.ShopMiddleware",
+ "mezzanine.core.request.CurrentRequestMiddleware",
+ "mezzanine.core.middleware.RedirectFallbackMiddleware",
+ "mezzanine.core.middleware.TemplateForDeviceMiddleware",
+ "mezzanine.core.middleware.TemplateForHostMiddleware",
+ "mezzanine.core.middleware.AdminLoginInterfaceSelectorMiddleware",
+ "mezzanine.core.middleware.SitePermissionMiddleware",
+ # Uncomment the following if using any of the SSL settings:
+ # "mezzanine.core.middleware.SSLRedirectMiddleware",
+ "mezzanine.pages.middleware.PageMiddleware",
+ "mezzanine.core.middleware.FetchFromCacheMiddleware",
+)
+
+# Store these package names here as they may change in the future since
+# at the moment we are using custom forks of them.
+PACKAGE_NAME_FILEBROWSER = "filebrowser_safe"
+PACKAGE_NAME_GRAPPELLI = "grappelli_safe"
+
+#########################
+# OPTIONAL APPLICATIONS #
+#########################
+
+# These will be added to ``INSTALLED_APPS``, only if available.
+OPTIONAL_APPS = (
+ "debug_toolbar",
+ "django_extensions",
+ "compressor",
+ PACKAGE_NAME_FILEBROWSER,
+ PACKAGE_NAME_GRAPPELLI,
+)
+
+##################
+# LOCAL SETTINGS #
+##################
+
+# Allow any settings to be defined in local_settings.py which should be
+# ignored in your version control system allowing for settings to be
+# defined per machine.
+try:
+ from .local_settings import *
+except ImportError as e:
+ if "local_settings" not in str(e):
+ raise e
+
+
+####################
+# DYNAMIC SETTINGS #
+####################
+
+# set_dynamic_settings() will rewrite globals based on what has been
+# defined so far, in order to provide some better defaults where
+# applicable. We also allow this settings module to be imported
+# without Mezzanine installed, as the case may be when using the
+# fabfile, where setting the dynamic settings below isn't strictly
+# required.
+try:
+ from mezzanine.utils.conf import set_dynamic_settings
+except ImportError:
+ pass
+else:
+ set_dynamic_settings(globals())
--- /dev/null
+from __future__ import unicode_literals
+
+from django.conf.urls import patterns, include, url
+from django.conf.urls.i18n import i18n_patterns
+from django.contrib import admin
+
+from mezzanine.core.views import direct_to_template
+from mezzanine.conf import settings
+
+
+admin.autodiscover()
+
+# Add the urlpatterns for any custom Django applications here.
+# You can also change the ``home`` view to add your own functionality
+# to the project's homepage.
+
+urlpatterns = i18n_patterns("",
+ # Change the admin prefix here to use an alternate URL for the
+ # admin interface, which would be marginally more secure.
+ ("^admin/", include(admin.site.urls)),
+)
+
+if settings.USE_MODELTRANSLATION:
+ urlpatterns += patterns('',
+ url('^i18n/$', 'django.views.i18n.set_language', name='set_language'),
+ )
+
+urlpatterns += patterns('',
+
+ # Cartridge URLs.
+ ("^shop/", include("cartridge.shop.urls")),
+ url("^account/orders/$", "cartridge.shop.views.order_history",
+ name="shop_order_history"),
+
+ # We don't want to presume how your homepage works, so here are a
+ # few patterns you can use to set it up.
+
+ # HOMEPAGE AS STATIC TEMPLATE
+ # ---------------------------
+ # This pattern simply loads the index.html template. It isn't
+ # commented out like the others, so it's the default. You only need
+ # one homepage pattern, so if you use a different one, comment this
+ # one out.
+
+ url("^$", direct_to_template, {"template": "index.html"}, name="home"),
+
+ # HOMEPAGE AS AN EDITABLE PAGE IN THE PAGE TREE
+ # ---------------------------------------------
+ # This pattern gives us a normal ``Page`` object, so that your
+ # homepage can be managed via the page tree in the admin. If you
+ # use this pattern, you'll need to create a page in the page tree,
+ # and specify its URL (in the Meta Data section) as "/", which
+ # is the value used below in the ``{"slug": "/"}`` part. Make
+ # sure to uncheck all templates for the "show in menus" field
+ # when you create the page, since the link to the homepage is
+ # always hard-coded into all the page menus that display navigation
+ # on the site. Also note that the normal rule of adding a custom
+ # template per page with the template name using the page's slug
+ # doesn't apply here, since we can't have a template called
+ # "/.html" - so for this case, the template "pages/index.html" can
+ # be used.
+
+ # url("^$", "mezzanine.pages.views.page", {"slug": "/"}, name="home"),
+
+ # HOMEPAGE FOR A BLOG-ONLY SITE
+ # -----------------------------
+ # This pattern points the homepage to the blog post listing page,
+ # and is useful for sites that are primarily blogs. If you use this
+ # pattern, you'll also need to set BLOG_SLUG = "" in your
+ # ``settings.py`` module, and delete the blog page object from the
+ # page tree in the admin if it was installed.
+
+ # url("^$", "mezzanine.blog.views.blog_post_list", name="home"),
+
+ # MEZZANINE'S URLS
+ # ----------------
+ # ADD YOUR OWN URLPATTERNS *ABOVE* THE LINE BELOW.
+ # ``mezzanine.urls`` INCLUDES A *CATCH ALL* PATTERN
+ # FOR PAGES, SO URLPATTERNS ADDED BELOW ``mezzanine.urls``
+ # WILL NEVER BE MATCHED!
+
+ # If you'd like more granular control over the patterns in
+ # ``mezzanine.urls``, go right ahead and take the parts you want
+ # from it, and use them directly below instead of using
+ # ``mezzanine.urls``.
+ ("^", include("mezzanine.urls")),
+
+ # MOUNTING MEZZANINE UNDER A PREFIX
+ # ---------------------------------
+ # You can also mount all of Mezzanine's urlpatterns under a
+ # URL prefix if desired. When doing this, you need to define the
+ # ``SITE_PREFIX`` setting, which will contain the prefix. Eg:
+ # SITE_PREFIX = "my/site/prefix"
+ # For convenience, and to avoid repeating the prefix, use the
+ # commented out pattern below (commenting out the one above of course)
+ # which will make use of the ``SITE_PREFIX`` setting. Make sure to
+ # add the import ``from django.conf import settings`` to the top
+ # of this file as well.
+ # Note that for any of the various homepage patterns above, you'll
+ # need to use the ``SITE_PREFIX`` setting as well.
+
+ # ("^%s/" % settings.SITE_PREFIX, include("mezzanine.urls"))
+
+ (r'^paypal-ipn-8c5erc9ye49ia51rn655mi4xs7/', include('paypal.standard.ipn.urls')),
+
+)
+
+# Adds ``STATIC_URL`` to the context of error pages, so that error
+# pages can use JS, CSS and images.
+handler404 = "mezzanine.core.views.page_not_found"
+handler500 = "mezzanine.core.views.server_error"
--- /dev/null
+#!/usr/bin/env python
+import os
+import sys
+
+if __name__ == "__main__":
+
+ from mezzanine.utils.conf import real_project_name
+
+ settings_module = "%s.settings" % real_project_name("diggersdigest")
+ os.environ.setdefault("DJANGO_SETTINGS_MODULE", settings_module)
+
+ from django.core.management import execute_from_command_line
+
+ execute_from_command_line(sys.argv)
--- /dev/null
+from copy import deepcopy
+
+from django.contrib import admin
+from django.utils.translation import ugettext_lazy as _
+
+from cartridge.shop.models import Product, ProductImage, ProductVariation
+from cartridge.shop.admin import ProductAdmin, ProductImageAdmin, ProductVariationAdmin
+
+from mezzanine.blog.admin import BlogPostAdmin
+from mezzanine.blog.models import BlogPost
+
+# Register your models here.
+from .models import Gallery
+from .models import Grading
+from .models import Link
+from .models import Mix
+from .models import News
+from .models import Shop
+from .models import Theme
+from .models import User
+from .models import Artist
+from .models import Label
+from .models import Country
+from .models import Record
+from .models import Podcast
+from .models import ConditionGrading
+
+class RecordInline(admin.StackedInline):
+ model = Record
+ extra = 0
+ max_num = 0
+
+list_display = ProductAdmin.list_display
+list_display.remove("sale_price")
+list_editable = ProductAdmin.list_editable
+list_editable.remove("sale_price")
+
+class RecordProductAdmin(ProductAdmin):
+ inlines = [ProductImageAdmin, ProductVariationAdmin, RecordInline]
+
+class RecordAdmin(admin.ModelAdmin):
+ search_fields = ["title", "artist__name", "label__name"]
+ filter_horizontal = ["performers"]
+
+
+sale_fields = ("sale_price", "sale_from", "sale_to")
+variation_fields = ProductVariationAdmin.fields
+for field in sale_fields:
+ variation_fields.remove(field)
+
+
+class myProductVariationAdmin(ProductVariationAdmin):
+ fields = variation_fields
+
+blog_fieldsets = deepcopy(BlogPostAdmin.fieldsets)
+blog_fieldsets.insert(1, (_("Related products"), {
+ "classes": ("collapse-closed",),
+ "fields": ("related_products",)}))
+blog_filter_horizontal = BlogPostAdmin.filter_horizontal
+blog_filter_horizontal += ("related_products", )
+
+
+class MyBlogPostAdmin(BlogPostAdmin):
+ fieldsets = blog_fieldsets
+ filter_horizontal = blog_filter_horizontal
+
+admin.site.unregister(BlogPost)
+admin.site.register(BlogPost, MyBlogPostAdmin)
+
+
+admin.site.unregister(Product)
+admin.site.register(Product, RecordProductAdmin)
+
+admin.site.register(Gallery)
+admin.site.register(Grading)
+admin.site.register(Link)
+admin.site.register(Mix)
+admin.site.register(News)
+admin.site.register(Shop)
+admin.site.register(Theme)
+admin.site.register(User)
+admin.site.register(Artist)
+admin.site.register(Label)
+admin.site.register(Country)
+admin.site.register(Record, RecordAdmin)
+admin.site.register(Podcast)
+admin.site.register(ConditionGrading)
--- /dev/null
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from django.core.management.base import BaseCommand, CommandError
+
+# MYSQL command to restore the old SQL DB
+# chown -R mysql:mysql /var/lib/mysql/
+# mysqld_safe &
+# mysql -u digger -p diggersdigest < /var/lib/mysql/diggersdigest.sql
+
+
+import os
+from records import models as rec_models
+from cartridge.shop.models import Product, ProductVariation, Category, ProductImage
+import datetime
+from diggersdigest import settings
+
+
+import HTMLParser
+parser = HTMLParser.HTMLParser()
+import string
+
+import mezzanine.blog.models as blog_models
+from mezzanine.pages.models import Page
+
+
+# Clean Up DB
+try:
+ obj = rec_models.Shop.objects.get(titre='nkvbhbjh')
+ obj.delete()
+except rec_models.Shop.DoesNotExist:
+ pass
+
+DOLLAR_TO_EURO = 0.898642152 # 04/09/2015
+
+RECORDS_TO_SKIP = [2734, 1006, 1393] # Doublons
+RECORDS_TO_SKIP.append(3323) # old Fake records = "We buy records" page
+
+OLD_SHOP_LIST = rec_models.Shop.objects.exclude(pk__in = RECORDS_TO_SKIP)
+
+
+# Check mp3 in media upload path
+def check_mp3(file_list, file_path):
+ abs_file_path = os.path.join(settings.MEDIA_ROOT, file_path)
+ file_exists = [os.path.exists(os.path.join(abs_file_path, file_name))
+ for file_name in file_list]
+
+ missing_files = [file_name for (file_name, ok) in zip(file_list, file_exists) if not ok]
+ if missing_files:
+ print "Missing files in path : %s\n" % file_path
+ print '\n'.join(missing_files)
+ else:
+ print "No missing MP3 Mix files"
+ return missing_files
+
+# Get year and decade for record metadata
+def get_year(date):
+ if date == '197':
+ date = date + '?'
+ try:
+ year = int(date)
+ decade = (year // 10 ) * 10
+ except ValueError:
+ if (date == '196?') | (string.find(date, '60')>-1):
+ year = None
+ decade = '1960'
+ elif (date == '197?') | (date=='197.') | (string.find(date, '70')>-1):
+ year = None
+ decade = '1970'
+ elif (date == '198?') | (date == 'late 198') | (string.find(date, '80')>-1):
+ year = None
+ decade = 1980
+ elif (date == '199?') | (string.find(date, '90')>-1):
+ year = None
+ decade = 1990
+ else:
+ year, decade = None, None
+ return (year, decade)
+
+
+class Command(BaseCommand):
+ help = 'Populate the new database from the original backup'
+
+ ## def add_arguments(self, parser):
+ ## parser.add_argument('poll_id', nargs='+', type=int)
+
+ # Label
+ def populate_label(self):
+ old_labels = set([shop.label for shop in OLD_SHOP_LIST])
+ count = 0
+ for lab in old_labels:
+ obj, created = rec_models.Label.objects.get_or_create(name = lab)
+ if created:
+ count += 1
+
+ self.stdout.write('Labels\n------\n')
+ self.stdout.write("\t%d new label objects" % count)
+ self.stdout.write("\t%d labels in DB ( %d in old DB)" % (len(rec_models.Label.objects.all()), len(old_labels)))
+
+ # Artist
+ def populate_artist(self):
+ Artist = rec_models.Artist
+ old_artist = set([shop.artiste for shop in OLD_SHOP_LIST])
+ count = 0
+ for artist in old_artist:
+ obj, created = Artist.objects.get_or_create(name = artist)
+ if created:
+ count += 1
+ self.stdout.write('Artist\n------\n')
+ self.stdout.write("\t%d new artist objects" % count)
+ self.stdout.write("\t%d artists in DB ( %d in old DB)" % (len(Artist.objects.all()), len(old_artist)))
+
+ # Country
+ def populate_country(self):
+ Country = rec_models.Country
+ old_country = set([shop.pays for shop in OLD_SHOP_LIST])
+ count = 0
+ for country in old_country:
+ obj, created = Country.objects.get_or_create(name = country)
+ if created:
+ count += 1
+
+ self.stdout.write('Country\n------\n')
+ self.stdout.write("\t%d new country objects" % count)
+ self.stdout.write("\t%d countries in DB ( %d in old DB)" % (len(Country.objects.all()), len(old_country)))
+
+
+
+
+ # PODCAST FROM MIX
+ def populate_podcast(self, user):
+ MIX_CATEGORY = 'Podcast'
+ blog_models.BlogCategory.objects.get_or_create(title=MIX_CATEGORY)
+
+ PODCAST_IMG_PATH = os.path.join('uploads/blog/mixes')
+ PODCAST_AUDIO_PATH = os.path.join('uploads/audio/mixes')
+
+ self.stdout.write('Podcast\n-------\n')
+
+ # MP3 for mix
+ mp3_mix_list = [mix.mp3 for mix in rec_models.Mix.objects.all()]
+
+ check_mp3(mp3_mix_list, os.path.join(PODCAST_AUDIO_PATH))
+
+ ordered_mix_list = sorted(rec_models.Mix.objects.all(), key=lambda mix: mix.ordre)
+ count = 0
+ for mix in ordered_mix_list:
+ if mix.visu1:
+ img_file = str(mix.id) + '.jpg'
+ img_path = os.path.join(PODCAST_IMG_PATH, img_file)
+ else:
+ img_path = ''
+
+ audio_path = os.path.join(PODCAST_AUDIO_PATH, mix.mp3)
+ #status=mix.published+1,
+ #featured_image=img_path,
+ #user=digger)
+ if mix.titre:
+ obj, created = rec_models.Podcast.objects.get_or_create(pk=mix.pk,
+ title=parser.unescape(mix.titre),
+ user=user)
+ if created:
+ count += 1
+ obj.audio=audio_path
+ obj.genre=mix.genre
+ obj.old_date=mix.date
+ desc = parser.unescape(mix.desc)
+ obj.description=desc
+ obj.content=desc # duplicate description in content
+ obj.status=mix.published+1
+ obj.featured_image=img_path
+ obj.save()
+
+ self.stdout.write("\t%d new Podcast objects" % count)
+ self.stdout.write("\t%d Podcast in DB ( %d in old DB)" % (len(rec_models.Podcast.objects.all()), len(ordered_mix_list)))
+
+ ## audio = FileField(verbose_name=_("Audio File"), max_length=200, format="audio",
+ ## upload_to=upload_to("records.Podcast.audio", "audio/mixes"))
+ ## genre = models.CharField(max_length=128)
+ ## # titre --> title
+ ## date = models.CharField(max_length=64)
+ ## # desc --> description
+ ## # mp3 --> audio
+ ## #visu1 = models.IntegerField() si 1 --> featured_image
+ ## # ordre : on laisse tombé ?
+ ## # published --> status / 0 --> CONTENT_STATUS_DRAFT = 1 / 1 CONTENT_STATUS_PUBLISHED = 2
+
+ ## def populate_pages(self):
+ ## obj, created = Page.objects.get_or_create(status=2,
+ ## #"_order"= 3,
+ ## title="Contact",
+ ## titles= "Contact",
+ ## content_model="form",
+ ## in_menus=[1, 2, 3],
+ ## slug="contact",
+ ## description= "Fill in the form below to get in touch with us."
+ ## )
+ ## #obj.delete()
+ ## #obj.description= "Fill in the form below to get in touch with us."
+
+ # NEWS
+ def populate_news(self):
+ ## news fields :
+ ## 'texte' --> content
+ ## 'nomlien'
+ ## 'ordre' --> _order, doublons à gérer
+ ## 'id' --> pk
+ ## 'titre' --> title
+ ## 'typelien',
+ ## 'position',
+ ## 'adresslien',
+ ## 'visu1',
+ ## 'published']
+ self.stdout.write('News\n-------\n')
+
+ news_date = {
+ 3: datetime.datetime(2007, 11, 8, 19, 21, 39),
+ 5: datetime.datetime(2007, 12, 31, 0, 19, 13),
+ 6: datetime.datetime(2008, 1, 17, 12, 44, 50),
+ 7: datetime.datetime(2008, 2, 13, 13, 21, 19),
+ 12: datetime.datetime(2008, 4, 16, 0, 14, 23),
+ 13: datetime.datetime(2013, 6, 26, 1, 55, 4, 1817),
+ 14: datetime.datetime(2008, 6, 12, 21, 43, 46),
+ 16: datetime.datetime(2008, 6, 17, 17, 23, 36),
+ 18: datetime.datetime(2008, 7, 15, 23, 7, 42),
+ 19: datetime.datetime(2008, 8, 21, 15, 44, 30),
+ 20: datetime.datetime(2013, 3, 8, 17, 51, 12, 601338),
+ 28: datetime.datetime(2009, 2, 14, 0, 8, 36),
+ 33: datetime.datetime(2009, 3, 26, 22, 21, 2),
+ 35: datetime.datetime(2013, 11, 2, 22, 4, 45, 618265),
+ 40: datetime.datetime(2010, 7, 6, 1, 44, 38, 980145),
+ 41: datetime.datetime(2009, 7, 28, 13, 7, 52),
+ 42: datetime.datetime(2009, 7, 28, 1, 58, 32),
+ 43: datetime.datetime(2009, 8, 30, 13, 9, 53),
+ 46: datetime.datetime(2009, 10, 12, 16, 35, 14),
+ 50: datetime.datetime(2009, 11, 26, 14, 38, 49, 257703),
+ 54: datetime.datetime(2010, 1, 7, 18, 3, 1, 864172),
+ 56: datetime.datetime(2010, 2, 4, 16, 16, 32, 203171),
+ 59: datetime.datetime(2010, 2, 26, 3, 16, 22, 23171),
+ 61: datetime.datetime(2010, 3, 11, 1, 23, 19, 667171),
+ 63: datetime.datetime(2010, 3, 24, 23, 23, 55, 850107),
+ 65: datetime.datetime(2010, 6, 7, 22, 5, 40, 604645),
+ 67: datetime.datetime(2010, 6, 23, 11, 24, 18, 44646),
+ 70: datetime.datetime(2010, 9, 23, 8, 13, 3, 448061),
+ 71: datetime.datetime(2010, 10, 21, 12, 19, 52, 648562),
+ 72: datetime.datetime(2010, 11, 29, 10, 7, 31, 680399),
+ 73: datetime.datetime(2010, 12, 1, 11, 54, 59, 408399),
+ 75: datetime.datetime(2010, 12, 31, 12, 38, 46, 636398),
+ 77: datetime.datetime(2011, 5, 9, 0, 58, 42, 968596),
+ 78: datetime.datetime(2011, 1, 25, 17, 6, 58, 312900),
+ 79: datetime.datetime(2011, 2, 6, 14, 23, 57, 556399),
+ 80: datetime.datetime(2011, 3, 3, 1, 36, 13, 28095),
+ 81: datetime.datetime(2011, 3, 3, 1, 38, 52, 756095),
+ 82: datetime.datetime(2011, 4, 1, 22, 40, 39, 912095),
+ 83: datetime.datetime(2011, 3, 25, 1, 17, 34, 408096),
+ 84: datetime.datetime(2011, 4, 22, 18, 24, 10, 581095),
+ 85: datetime.datetime(2011, 5, 16, 20, 46, 34, 176095),
+ 86: datetime.datetime(2011, 6, 6, 21, 26, 10, 496720),
+ 87: datetime.datetime(2011, 6, 17, 20, 8, 51, 122313),
+ 88: datetime.datetime(2011, 7, 7, 21, 4, 15, 230314),
+ 90: datetime.datetime(2011, 8, 19, 21, 46, 36, 158814),
+ 92: datetime.datetime(2011, 9, 18, 23, 27, 12, 858075),
+ 94: datetime.datetime(2011, 11, 9, 15, 16, 30, 512660),
+ 96: datetime.datetime(2011, 12, 10, 20, 25, 45, 36660),
+ 97: datetime.datetime(2012, 1, 7, 23, 9, 25, 836659),
+ 98: datetime.datetime(2012, 1, 16, 7, 41, 1, 792660),
+ 100: datetime.datetime(2012, 1, 26, 15, 6, 12, 256660),
+ 101: datetime.datetime(2012, 2, 6, 13, 18, 23, 84660),
+ 102: datetime.datetime(2012, 2, 18, 12, 31, 46, 536660),
+ 103: datetime.datetime(2012, 3, 1, 13, 29, 11, 816662),
+ 106: datetime.datetime(2012, 4, 2, 19, 35, 33, 540661),
+ 107: datetime.datetime(2012, 4, 6, 20, 6, 14, 972661),
+ 108: datetime.datetime(2012, 4, 18, 21, 6, 9, 708893),
+ 109: datetime.datetime(2012, 5, 2, 23, 39, 54, 489173),
+ 110: datetime.datetime(2012, 5, 12, 3, 29, 56, 220660),
+ 111: datetime.datetime(2012, 5, 22, 13, 57, 14, 244660),
+ 112: datetime.datetime(2013, 2, 28, 14, 45, 6, 540838),
+ 113: datetime.datetime(2012, 6, 1, 1, 53, 31, 32661),
+ 114: datetime.datetime(2012, 6, 14, 20, 10, 54, 108660),
+ 115: datetime.datetime(2012, 7, 2, 14, 26, 30, 896721),
+ 116: datetime.datetime(2012, 7, 18, 16, 35, 42, 440661),
+ 117: datetime.datetime(2012, 8, 8, 10, 24, 52, 653338),
+ 119: datetime.datetime(2012, 9, 12, 1, 23, 55, 604838),
+ 120: datetime.datetime(2012, 10, 2, 0, 35, 16, 192839),
+ 121: datetime.datetime(2012, 10, 23, 2, 2, 26, 948838),
+ 122: datetime.datetime(2012, 11, 3, 15, 44, 35, 205838),
+ 123: datetime.datetime(2012, 11, 16, 2, 1, 20, 904838),
+ 124: datetime.datetime(2012, 11, 29, 11, 0, 21, 732838),
+ 125: datetime.datetime(2012, 12, 15, 23, 32, 42, 336838),
+ 126: datetime.datetime(2013, 1, 6, 2, 3, 38, 88839),
+ 127: datetime.datetime(2013, 1, 15, 18, 43, 30, 624838),
+ 128: datetime.datetime(2013, 1, 22, 12, 46, 44, 540839),
+ 129: datetime.datetime(2013, 1, 29, 19, 24, 57, 692838),
+ 130: datetime.datetime(2013, 2, 21, 23, 39, 9, 552838),
+ 131: datetime.datetime(2013, 3, 7, 0, 42, 0, 20838),
+ 132: datetime.datetime(2013, 3, 12, 11, 36, 25, 840838),
+ 133: datetime.datetime(2013, 3, 27, 10, 46, 48, 676838),
+ 134: datetime.datetime(2013, 4, 11, 5, 42, 2, 812839),
+ 135: datetime.datetime(2013, 4, 21, 10, 42, 31, 628838),
+ 136: datetime.datetime(2013, 5, 15, 23, 15, 54, 164838),
+ 137: datetime.datetime(2013, 6, 4, 15, 34, 36, 68817),
+ 138: datetime.datetime(2013, 6, 21, 14, 1, 29, 596317),
+ 139: datetime.datetime(2013, 7, 3, 1, 6, 11, 880319),
+ 140: datetime.datetime(2013, 7, 23, 15, 38, 2, 64317),
+ 141: datetime.datetime(2013, 8, 27, 3, 41, 39, 824317),
+ 142: datetime.datetime(2013, 9, 3, 7, 6, 29, 456317),
+ 143: datetime.datetime(2013, 9, 26, 13, 48, 21, 418265),
+ 144: datetime.datetime(2013, 10, 4, 14, 4, 13, 950265),
+ 147: datetime.datetime(2013, 11, 5, 1, 46, 33, 818265),
+ 148: datetime.datetime(2014, 1, 23, 8, 57, 4, 434265),
+ 149: datetime.datetime(2013, 11, 28, 15, 40, 41, 6265),
+ 150: datetime.datetime(2014, 1, 9, 12, 42, 44, 706265),
+ 151: datetime.datetime(2014, 1, 23, 8, 46, 25, 882265),
+ 152: datetime.datetime(2014, 2, 7, 23, 20, 0, 882265),
+ 153: datetime.datetime(2014, 2, 27, 20, 17, 38, 938266),
+ 154: datetime.datetime(2014, 3, 26, 9, 19, 12, 450265),
+ 155: datetime.datetime(2014, 4, 21, 18, 46, 11, 314265),
+ 156: datetime.datetime(2014, 5, 1, 18, 26, 7, 50265),
+ 158: datetime.datetime(2014, 5, 26, 11, 42, 36, 783265),
+ 159: datetime.datetime(2014, 6, 13, 21, 48, 29, 214265),
+ 160: datetime.datetime(2014, 6, 30, 21, 20, 7, 518265),
+ 161: datetime.datetime(2014, 7, 14, 19, 24, 40, 278265),
+ 162: datetime.datetime(2014, 8, 20, 2, 38, 41, 39946),
+ 163: datetime.datetime(2014, 9, 5, 19, 24, 46, 661639),
+ 164: datetime.datetime(2014, 9, 15, 22, 50, 48, 370368),
+ 165: datetime.datetime(2014, 10, 1, 12, 48, 31, 897806),
+ 166: datetime.datetime(2014, 10, 16, 16, 50, 59, 149418),
+ 167: datetime.datetime(2014, 11, 8, 20, 36, 14, 584649),
+ 168: datetime.datetime(2014, 11, 18, 2, 40, 48, 864752),
+ 169: datetime.datetime(2014, 12, 3, 11, 45, 31, 643276),
+ 170: datetime.datetime(2014, 12, 20, 0, 8, 48, 732320),
+ 171: datetime.datetime(2015, 1, 11, 11, 34, 36, 966855),
+ 172: datetime.datetime(2015, 1, 23, 1, 22, 51, 954981),
+ 173: datetime.datetime(2015, 2, 10, 9, 6, 39, 92265),
+ 174: datetime.datetime(2015, 2, 22, 3, 50, 50, 127304),
+ 175: datetime.datetime(2015, 3, 11, 12, 52, 56, 176986),
+ 176: datetime.datetime(2015, 4, 22, 16, 10, 44, 140259),
+ 177: datetime.datetime(2015, 4, 22, 16, 22, 47, 672255),
+ 178: datetime.datetime(2015, 5, 22, 10, 18, 45, 146728),
+ 179: datetime.datetime(2015, 6, 26, 1, 11, 8, 869148),
+ 180: datetime.datetime(2015, 7, 7, 23, 30, 46, 789683)
+ }
+
+ ordered_news_list = sorted(rec_models.News.objects.all(), key=lambda news: news.ordre)
+ blog_models.BlogCategory.objects.get_or_create(title='News')
+ import parsedatetime
+ cal = parsedatetime.Calendar()
+ for n in ordered_news_list:
+ if n.position==1:
+ try:
+ d = cal.parseDateText(n.titre)
+ except AttributeError:
+ d = ''
+ print n.titre, ' - ', d
+
+
+ # Theme -> Category
+ def populate_category(self):
+ # This has to be run once as category are mezzanine Pages
+ # they would then be handle by a fixture for 'mezzanine pages' app
+
+
+
+ shop_cat, created = Category.objects.get_or_create(title="Shop")
+ unclassified_cat, created = Category.objects.get_or_create(
+ title="Unclassified",
+ content="Unclassified records",
+ parent = shop_cat,
+ in_menus = [1,2])
+ showcase, created = Category.objects.get_or_create(
+ title="Showcase",
+ content="Category for product to be placed on the HomePage",
+ parent = shop_cat,
+ in_menus = [])
+
+
+ theme_list = [theme for theme in rec_models.Theme.objects.all()
+ if (theme.published==1) and not(theme.id==39)]
+ count = 0
+ for theme in theme_list:
+ category, create = Category.objects.get_or_create(pk=theme.id)
+ category.title = theme.nom
+ category.parent = shop_cat
+ category.in_menus = [1, 2] # Show only in header and left panel
+ category.save()
+ if create:
+ count +=1
+
+ self.stdout.write('Category\n-------\n')
+ self.stdout.write("\t%d new Category objects" % count)
+
+
+ # SHOPS TO RECORDS
+ def populate_record(self):
+ self.stdout.write('Records\n-------\n')
+
+ AUDIO_PATH = 'uploads/audio/'
+ RECORDS_PATH = os.path.join(AUDIO_PATH, "records")
+ IMG_PATH = os.path.join('uploads/product')
+
+ unclassified_cat, created = Category.objects.get(title="Unclassified")
+ UNCLASS_ID = unclassified_cat.pk
+
+ THEME_TO_CATEGORY = {
+ # Published
+ 1: 1, # Jazz
+ 2: 2, # Prog / Psych / Rock
+ 37: 37, # Antilles / West Indies
+ 6: 6, # Experimental / Avant
+ 7: 7, # Soundtracks
+ 10: 10, # Electronic / Cosmic
+ 13: 13, # Middle East & Oriental
+ 15: 15, # Afro / Latin
+ 19: 19, # Library / Euro Grooves
+ 29: 29, # Prog / Psych / Pop 7
+ 22: 22, # Jazz Funk / Fusion
+ 24: 24, # French Sounds
+ 28: 28, # Breaks & Samples
+ 30: 30, # Selected Reissues
+ 33: 33, # Soul / Funk
+ 38: 38, # OUR PRODUCTION
+ # Unpublished categories classified above
+ 42: 37, # SOLD OUT ANTILLES WEST INDIES
+ 16: 19, # SOLD OUT LIBRARY 0
+ 41:1, # SOLD OUT JAZZ 0
+ 25: 10, # SOLD OUT ELECTRO COSMIC
+ # New category for old sold-out and unclass records
+ UNCLASS_ID: UNCLASS_ID,
+ # Unpublished and unclassified categories
+ 17: UNCLASS_ID, #Â IN STOCK ->> UNCLASSIFIED
+ 18: UNCLASS_ID, #Â SOLD OUT ->> UNCLASSIFIED
+ 9: UNCLASS_ID, # Stuffs->> UNCLASSIFIED
+ 27: UNCLASS_ID, # SOLD OUT DEPOT->> UNCLASSIFIED
+ 40: UNCLASS_ID, # Brazilian Music->> UNCLASSIFIED
+ 31: UNCLASS_ID, # NEW ! 20 € & UNDER->> UNCLASSIFIED
+ # Fake records category --> turn into a Page in fixture
+ #Â 39 WE BUY RECORDS
+ }
+
+ for shop in OLD_SHOP_LIST:
+
+ # Get or Create record
+ record, created = rec_models.Record.objects.get_or_create(pk=shop.id)
+ # Set record metadata
+ record.title = parser.unescape(shop.titre)
+ record.country = rec_models.Country.objects.get(name = shop.pays)
+ record.audio_file = os.path.join(RECORDS_PATH, shop.mp3)
+ # product_id --> FK
+
+ record.release_year , record.release_decade = get_year(shop.date)
+ record.date_text = shop.date # To be deleted later ?
+ record.record_status = shop.new
+ record.cover_condition_id = shop.cover
+ record.vinyl_condition_id = shop.vinyl
+ record.label = rec_models.Label.objects.get(name = shop.label)
+ record.artist = rec_models.Artist.objects.get(name = shop.artiste)
+ record.save()
+
+ self.stdout.write('------')
+ self.stdout.write('Record %d - %d' % (record.pk,len(OLD_SHOP_LIST)))
+
+ # --------------------------
+ # Create associated Product
+ # --------------------------
+ if isinstance(record.product, Product):
+ product = record.product
+ else:
+ product = Product.objects.create()
+ # Fill records ForeignKey to Product
+ record.product = product
+ record.save()
+
+
+ product.variations.manage_empty()
+
+ # Metadata
+ product.title = record.title
+ product.content = shop.desc
+
+ # Category
+ theme = rec_models.Theme.objects.get(id=shop.theme)
+ category_id = THEME_TO_CATEGORY[theme.pk]
+ category = Category.objects.get(pk=category_id)
+ product.categories.add(category)
+
+ # Manage price / availability
+ product.available = (theme.published == 1) & (shop.published==1)
+ product.num_in_stock = int(product.available)
+
+ if shop.devise == 3: #Euros
+ product.unit_price = shop.prix
+ elif shop.devise == 1: # Dollar
+ product.price = round(shop.prix * DOLLAR_TO_EURO)
+ product.sale_price = None # No sale / pas de soldes
+
+ product.save() # Needed to copy the price fields to the default variation
+
+ # Cover image
+ img_file = os.path.join(IMG_PATH, str(shop.pk)+'.jpg')
+ abs_img_file = os.path.join(settings.MEDIA_ROOT, img_file)
+ if os.path.exists(abs_img_file):
+ image, created = ProductImage.objects.get_or_create(
+ file=img_file,
+ product=product)
+ product.variations.set_default_images([])
+
+ product.copy_default_variation()
+ product.save()
+
+ default_variation = product.variations.get(default=True)
+ default_variation.sku = "DD_REC_" + str(record.pk)
+ default_variation.save()
+
+ self.stdout.write('Product %d / %d --> %s' % (product.pk,len(OLD_SHOP_LIST), product.available))
+
+ #self.stdout.write('\b\b\b\b%.4d' % record.pk)
+ #print record.__dict__
+
+ ## class Shop(models.Model):
+ ## theme = models.IntegerField()
+ ## artiste = models.CharField(max_length=128)
+ ## new = models.IntegerField()
+ ## titre = models.CharField(max_length=128)
+ ## label = models.CharField(max_length=128)
+ ## date = models.CharField(max_length=8)
+ ## pays = models.CharField(max_length=128)
+ ## desc = models.TextField()
+ ## cover = models.IntegerField()
+ ## vinyl = models.IntegerField()
+ ## prix = models.IntegerField()
+ ## devise = models.IntegerField()
+ ## mp3 = models.CharField(max_length=128)
+ ## visu1 = models.IntegerField()
+ ## ordre = models.IntegerField()
+ ## published = models.IntegerField()
+
+ ## class Record(Product):
+ ## """
+ ## Model for Record
+ ## """
+
+
+ def handle(self, *args, **options):
+ ## for poll_id in options['poll_id']:
+ ## try:
+ ## poll = Poll.objects.get(pk=poll_id)
+ ## except Poll.DoesNotExist:
+ ## raise CommandError('Poll "%s" does not exist' % poll_id)
+
+ ## poll.opened = False
+ ## poll.save()
+
+ ## self.stdout.write('Successfully closed poll "%s"' % poll_id)
+ from django.contrib.auth import models as auth_models
+ digger, created = auth_models.User.objects.get_or_create(username=u'digger',
+ password=u'admin',
+ is_staff=True,
+ email=u'')
+
+ self.populate_category()
+ self.populate_label()
+ self.populate_artist()
+ self.populate_country()
+ #self.populate_podcast(user=digger)
+ #self.populate_pages()
+ #self.populate_news()
+
+ self.populate_record()
+
+
+
+# MP3
+mp3_shop_list = [shop.mp3 for shop in OLD_SHOP_LIST]
+
+
+AUDIO_PATH = os.path.join(settings.MEDIA_ROOT, 'uploads/audio/')
+MIX_PATH = os.path.join(AUDIO_PATH, 'mixes')
+RECORDS_PATH = os.path.join(AUDIO_PATH, "records")
+
+
+
+
+
+# check_mp3(mp3_shop_list, RECORDS_PATH)
+
+
+# GRADING
+
+Grading_Dict = {
+ 'SS': {
+ 'name': "Still Sealed",
+ 'description': "in perfect condition, no wear"},
+ 'M' : {
+ 'name': "Mint" ,
+ 'description': "Still in new condition, no imperfections, a Perfect Copy !"},
+ 'NM' : {
+ 'name': "Near mint" ,
+ 'description': "Imperceptible wear, full vinyl gloss"},
+ 'EX' : {
+ 'name': "Excellent",
+ 'description': "Only very slight wear and paper scuffs, vinyl still glossy with very rare noise"},
+ 'VG++' : {
+ 'name': "Near Excellent",
+ 'description': "Light surface noise and wear but fairly minor, vinyl still plays nicely"},
+ 'VG+' : {
+ 'name': "Very Very Good",
+ 'description': "Evident groove wear or minor scuff marks, surface noise noticeable but does not really affect the playing"},
+ 'VG' : {
+ 'name': "Very Good",
+ 'description': "Wear and scuffs are more evident and many surface noises are noticeable"},
+ 'VG-' : {
+ 'name': "Good to Very Good",
+ 'description': "Heavy groove wear or scuffing, plays noisily"}
+ }
+
+
+count = 0
+for grade in rec_models.Grading.objects.all():
+ name = Grading_Dict[grade.nom]['name']
+ desc = Grading_Dict[grade.nom]['description']
+ obj, created = rec_models.ConditionGrading.objects.get_or_create(id=grade.id,
+ abbr=grade.nom,
+ name=name,
+ description=desc)
+
+ if created:
+ print "Create new GradingCondition : %s" % obj.name
+ count += 1
+
+
+print "%d fiches GradingCondition crées" % count
--- /dev/null
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+import django.db.models.deletion
+import mezzanine.core.fields
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('blog', '0002_auto_20150527_1555'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Gallery',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('titre', models.CharField(max_length=124)),
+ ('visu1', models.IntegerField()),
+ ('visu2', models.IntegerField()),
+ ('visu3', models.IntegerField()),
+ ('visu4', models.IntegerField()),
+ ('visu5', models.IntegerField()),
+ ('visu6', models.IntegerField()),
+ ('visu7', models.IntegerField()),
+ ('visu8', models.IntegerField()),
+ ('visu9', models.IntegerField()),
+ ('ordre', models.IntegerField()),
+ ('published', models.IntegerField()),
+ ],
+ options={
+ 'verbose_name': 'OLD_Gallery',
+ 'db_table': 'gallery',
+ 'managed': False,
+ },
+ ),
+ migrations.CreateModel(
+ name='Grading',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('nom', models.CharField(max_length=5)),
+ ],
+ options={
+ 'verbose_name': 'OLD_Grading',
+ 'db_table': 'grading',
+ 'managed': False,
+ },
+ ),
+ migrations.CreateModel(
+ name='Link',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('section', models.IntegerField()),
+ ('adress', models.CharField(max_length=124)),
+ ('desc', models.TextField()),
+ ('ordre', models.IntegerField()),
+ ('published', models.IntegerField()),
+ ],
+ options={
+ 'verbose_name': 'OLD_Link',
+ 'db_table': 'links',
+ 'managed': False,
+ },
+ ),
+ migrations.CreateModel(
+ name='Mix',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('genre', models.CharField(max_length=128)),
+ ('titre', models.CharField(max_length=128)),
+ ('date', models.CharField(max_length=64)),
+ ('desc', models.TextField()),
+ ('mp3', models.CharField(max_length=128)),
+ ('visu1', models.IntegerField()),
+ ('ordre', models.IntegerField()),
+ ('published', models.IntegerField()),
+ ],
+ options={
+ 'verbose_name': 'OLD_Mix',
+ 'db_table': 'mix',
+ 'managed': False,
+ 'verbose_name_plural': 'OLD_Mixes',
+ },
+ ),
+ migrations.CreateModel(
+ name='News',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('titre', models.CharField(max_length=128)),
+ ('texte', models.TextField()),
+ ('visu1', models.IntegerField()),
+ ('position', models.IntegerField()),
+ ('nomlien', models.CharField(max_length=128)),
+ ('adresslien', models.CharField(max_length=255)),
+ ('typelien', models.IntegerField()),
+ ('ordre', models.IntegerField()),
+ ('published', models.IntegerField()),
+ ],
+ options={
+ 'verbose_name': 'OLD_News',
+ 'db_table': 'news',
+ 'managed': False,
+ 'verbose_name_plural': 'OLD_News',
+ },
+ ),
+ migrations.CreateModel(
+ name='Shop',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('theme', models.IntegerField()),
+ ('artiste', models.CharField(max_length=128)),
+ ('new', models.IntegerField()),
+ ('titre', models.CharField(max_length=128)),
+ ('label', models.CharField(max_length=128)),
+ ('date', models.CharField(max_length=8)),
+ ('pays', models.CharField(max_length=128)),
+ ('desc', models.TextField()),
+ ('cover', models.IntegerField()),
+ ('vinyl', models.IntegerField()),
+ ('prix', models.IntegerField()),
+ ('devise', models.IntegerField()),
+ ('mp3', models.CharField(max_length=128)),
+ ('visu1', models.IntegerField()),
+ ('ordre', models.IntegerField()),
+ ('published', models.IntegerField()),
+ ],
+ options={
+ 'verbose_name': 'OLD_Shop',
+ 'db_table': 'shop',
+ 'managed': False,
+ },
+ ),
+ migrations.CreateModel(
+ name='Theme',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('nom', models.CharField(max_length=124)),
+ ('ordre', models.IntegerField()),
+ ('published', models.IntegerField()),
+ ],
+ options={
+ 'verbose_name': 'OLD_Theme',
+ 'db_table': 'theme',
+ 'managed': False,
+ },
+ ),
+ migrations.CreateModel(
+ name='User',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('username', models.CharField(max_length=10)),
+ ('password', models.CharField(max_length=10)),
+ ('type', models.IntegerField()),
+ ],
+ options={
+ 'db_table': 'user',
+ 'managed': False,
+ 'verbose_name_plural': 'OLD_User',
+ },
+ ),
+ migrations.CreateModel(
+ name='Artist',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('name', models.CharField(max_length=128)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='ConditionGrading',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('abbr', models.CharField(unique=True, max_length=5, verbose_name='abbreviation')),
+ ('name', models.CharField(max_length=128, verbose_name='name')),
+ ('description', models.TextField(verbose_name='description')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Country',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('name', models.CharField(max_length=128)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Label',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('name', models.CharField(max_length=128)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Podcast',
+ fields=[
+ ('blogpost_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='blog.BlogPost')),
+ ('audio', mezzanine.core.fields.FileField(max_length=200, verbose_name='Audio File')),
+ ('genre', models.CharField(max_length=128, null=True)),
+ ('old_date', models.CharField(max_length=64, null=True)),
+ ('mix_cloud_url', models.URLField(null=True)),
+ ],
+ options={
+ 'abstract': False,
+ },
+ bases=('blog.blogpost',),
+ ),
+ migrations.CreateModel(
+ name='Record',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('title', models.CharField(max_length=128)),
+ ('record_status', models.IntegerField(default=1, verbose_name='record status', choices=[(0, ''), (1, 'New'), (2, 'On Hold'), (3, 'Just Sold')])),
+ ('release_date', models.DateField(null=True, verbose_name='release date')),
+ ('audio_file', mezzanine.core.fields.FileField(max_length=1024, null=True, verbose_name='audio file')),
+ ('artist', models.ForeignKey(related_name='records_artists', on_delete=django.db.models.deletion.SET_NULL, verbose_name='artist', to='records.Artist', null=True)),
+ ('country', models.ForeignKey(related_name='records', on_delete=django.db.models.deletion.SET_NULL, verbose_name='country', to='records.Country', null=True)),
+ ('label', models.ForeignKey(related_name='records', on_delete=django.db.models.deletion.SET_NULL, verbose_name='label', to='records.Label', null=True)),
+ ('performers', models.ManyToManyField(related_name='records_performers', verbose_name='performer', to='records.Artist')),
+ ],
+ ),
+ ]
--- /dev/null
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('shop', '0001_initial'),
+ ('records', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='record',
+ name='product',
+ field=models.ForeignKey(related_name='records', on_delete=django.db.models.deletion.SET_NULL, verbose_name='product', to='shop.Product', null=True),
+ ),
+ migrations.AlterField(
+ model_name='record',
+ name='performers',
+ field=models.ManyToManyField(related_name='records_performers', verbose_name='performers', to='records.Artist'),
+ ),
+ ]
--- /dev/null
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('records', '0002_auto_20150831_1518'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='record',
+ name='date_text',
+ field=models.CharField(max_length=8, null=True, verbose_name='date text'),
+ ),
+ ]
--- /dev/null
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('records', '0003_record_date_text'),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name='record',
+ name='release_date',
+ ),
+ migrations.AddField(
+ model_name='record',
+ name='release_decade',
+ field=models.CharField(max_length=8, null=True, verbose_name='release decade', choices=[(1920, '1920s'), (1930, '1930s'), (1940, '1940s'), (1950, '1950s'), (1960, '1960s'), (1970, '1970s'), (1980, '1980s'), (1990, '1990s'), (2000, '2000s'), (2010, '2010s'), (2020, '2020s')]),
+ ),
+ migrations.AddField(
+ model_name='record',
+ name='release_year',
+ field=models.IntegerField(null=True, verbose_name='release year', choices=[(1920, 1920), (1921, 1921), (1922, 1922), (1923, 1923), (1924, 1924), (1925, 1925), (1926, 1926), (1927, 1927), (1928, 1928), (1929, 1929), (1930, 1930), (1931, 1931), (1932, 1932), (1933, 1933), (1934, 1934), (1935, 1935), (1936, 1936), (1937, 1937), (1938, 1938), (1939, 1939), (1940, 1940), (1941, 1941), (1942, 1942), (1943, 1943), (1944, 1944), (1945, 1945), (1946, 1946), (1947, 1947), (1948, 1948), (1949, 1949), (1950, 1950), (1951, 1951), (1952, 1952), (1953, 1953), (1954, 1954), (1955, 1955), (1956, 1956), (1957, 1957), (1958, 1958), (1959, 1959), (1960, 1960), (1961, 1961), (1962, 1962), (1963, 1963), (1964, 1964), (1965, 1965), (1966, 1966), (1967, 1967), (1968, 1968), (1969, 1969), (1970, 1970), (1971, 1971), (1972, 1972), (1973, 1973), (1974, 1974), (1975, 1975), (1976, 1976), (1977, 1977), (1978, 1978), (1979, 1979), (1980, 1980), (1981, 1981), (1982, 1982), (1983, 1983), (1984, 1984), (1985, 1985), (1986, 1986), (1987, 1987), (1988, 1988), (1989, 1989), (1990, 1990), (1991, 1991), (1992, 1992), (1993, 1993), (1994, 1994), (1995, 1995), (1996, 1996), (1997, 1997), (1998, 1998), (1999, 1999), (2000, 2000), (2001, 2001), (2002, 2002), (2003, 2003), (2004, 2004), (2005, 2005), (2006, 2006), (2007, 2007), (2008, 2008), (2009, 2009), (2010, 2010), (2011, 2011), (2012, 2012), (2013, 2013), (2014, 2014), (2015, 2015), (2016, 2016), (2017, 2017), (2018, 2018), (2019, 2019), (2020, 2020), (2021, 2021), (2022, 2022), (2023, 2023), (2024, 2024)]),
+ ),
+ ]
--- /dev/null
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('records', '0004_auto_20150904_0733'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='record',
+ name='release_decade',
+ field=models.IntegerField(null=True, verbose_name='release decade', choices=[(1920, '1920s'), (1930, '1930s'), (1940, '1940s'), (1950, '1950s'), (1960, '1960s'), (1970, '1970s'), (1980, '1980s'), (1990, '1990s'), (2000, '2000s'), (2010, '2010s'), (2020, '2020s')]),
+ ),
+ ]
--- /dev/null
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('records', '0005_auto_20150904_1309'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='record',
+ name='cover_condition',
+ field=models.ForeignKey(related_name='records_cover_condition', on_delete=django.db.models.deletion.SET_NULL, verbose_name='cover condition', to='records.ConditionGrading', null=True),
+ ),
+ migrations.AddField(
+ model_name='record',
+ name='vinyl_condition',
+ field=models.ForeignKey(related_name='records_vinyl_condition', on_delete=django.db.models.deletion.SET_NULL, verbose_name='vinyl condition', to='records.ConditionGrading', null=True),
+ ),
+ ]
--- /dev/null
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('shop', '0003_auto_20150906_1911'),
+ ('records', '0006_auto_20150907_0835'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='record',
+ name='image',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.SET_NULL, verbose_name='Image', blank=True, to='shop.ProductImage', null=True),
+ ),
+ ]
--- /dev/null
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('records', '0007_record_image'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='record',
+ name='performers',
+ field=models.ManyToManyField(related_name='records_performers', verbose_name='performers', to='records.Artist', blank=True),
+ ),
+ migrations.AlterField(
+ model_name='record',
+ name='product',
+ field=models.OneToOneField(related_name='record', null=True, on_delete=django.db.models.deletion.SET_NULL, verbose_name='product', to='shop.Product'),
+ ),
+ ]
--- /dev/null
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('records', '0008_auto_20150909_0818'),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name='record',
+ name='image',
+ ),
+ ]
--- /dev/null
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('records', '0009_remove_record_image'),
+ ]
+
+ operations = [
+ migrations.AlterModelOptions(
+ name='artist',
+ options={'ordering': ['name']},
+ ),
+ ]
--- /dev/null
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from __future__ import unicode_literals
+
+from django.db import models
+from django.utils.translation import ugettext_lazy as _
+
+import datetime
+import os
+import fnmatch
+from importlib import import_module
+from diggersdigest import settings
+# from mezzanine.conf import settings
+
+from mezzanine.core.fields import FileField
+from mezzanine.core.models import CONTENT_STATUS_DRAFT, CONTENT_STATUS_PUBLISHED
+from mezzanine.blog.models import BlogPost
+from mezzanine.utils.models import upload_to
+
+from cartridge.shop.models import Product, Category, Cart, Order, ProductVariation, DiscountCode
+from paypal.standard.ipn.signals import payment_was_successful
+from paypal.standard.models import ST_PP_COMPLETED
+from paypal.standard.ipn.signals import valid_ipn_received
+
+
+# Auto-generated Django models with manage.py inspectdb on the old database
+# You'll have to do the following manually to clean this up:
+# * Make sure each model has one field with primary_key=True
+# * Remove `managed = False` lines if you wish to allow Django to create, modify, and delete the table
+# Feel free to rename the models, but don't rename db_table values or field names.
+
+class Gallery(models.Model):
+ titre = models.CharField(max_length=124)
+ visu1 = models.IntegerField()
+ visu2 = models.IntegerField()
+ visu3 = models.IntegerField()
+ visu4 = models.IntegerField()
+ visu5 = models.IntegerField()
+ visu6 = models.IntegerField()
+ visu7 = models.IntegerField()
+ visu8 = models.IntegerField()
+ visu9 = models.IntegerField()
+ ordre = models.IntegerField()
+ published = models.IntegerField()
+
+ class Meta:
+ verbose_name = 'OLD_Gallery'
+ managed = False
+ db_table = 'gallery'
+
+ def __unicode__(self):
+ return self.titre
+
+
+
+class Grading(models.Model):
+ nom = models.CharField(max_length=5)
+
+ class Meta:
+ verbose_name = 'OLD_Grading'
+ managed = False
+ db_table = 'grading'
+
+ def __unicode__(self):
+ return self.nom
+
+
+
+class Link(models.Model):
+ section = models.IntegerField()
+ adress = models.CharField(max_length=124)
+ desc = models.TextField()
+ ordre = models.IntegerField()
+ published = models.IntegerField()
+
+ class Meta:
+ verbose_name = 'OLD_Link'
+ managed = False
+ db_table = 'links'
+
+ def __unicode__(self):
+ return self.adress
+
+
+class Mix(models.Model):
+ genre = models.CharField(max_length=128)
+ titre = models.CharField(max_length=128)
+ date = models.CharField(max_length=64)
+ desc = models.TextField()
+ mp3 = models.CharField(max_length=128)
+ visu1 = models.IntegerField()
+ ordre = models.IntegerField()
+ published = models.IntegerField()
+
+ class Meta:
+ verbose_name = 'OLD_Mix'
+ verbose_name_plural = 'OLD_Mixes'
+ managed = False
+ db_table = 'mix'
+
+ def __unicode__(self):
+ return self.titre
+
+
+class News(models.Model):
+ titre = models.CharField(max_length=128)
+ texte = models.TextField()
+ visu1 = models.IntegerField()
+ position = models.IntegerField()
+ nomlien = models.CharField(max_length=128)
+ adresslien = models.CharField(max_length=255)
+ typelien = models.IntegerField()
+ ordre = models.IntegerField()
+ published = models.IntegerField()
+
+ class Meta:
+ verbose_name = 'OLD_News'
+ verbose_name_plural = 'OLD_News'
+ managed = False
+ db_table = 'news'
+
+ def __unicode__(self):
+ return self.titre
+
+
+class Shop(models.Model):
+ theme = models.IntegerField()
+ artiste = models.CharField(max_length=128)
+ new = models.IntegerField()
+ titre = models.CharField(max_length=128)
+ label = models.CharField(max_length=128)
+ date = models.CharField(max_length=8)
+ pays = models.CharField(max_length=128)
+ desc = models.TextField()
+ cover = models.IntegerField()
+ vinyl = models.IntegerField()
+ prix = models.IntegerField()
+ devise = models.IntegerField()
+ mp3 = models.CharField(max_length=128)
+ visu1 = models.IntegerField()
+ ordre = models.IntegerField()
+ published = models.IntegerField()
+
+ class Meta:
+ verbose_name = 'OLD_Shop'
+ managed = False
+ db_table = 'shop'
+
+ def __unicode__(self):
+ return self.titre
+
+
+class Theme(models.Model):
+ nom = models.CharField(max_length=124)
+ ordre = models.IntegerField()
+ published = models.IntegerField()
+
+ class Meta:
+ verbose_name = 'OLD_Theme'
+ managed = False
+ db_table = 'theme'
+
+ def __unicode__(self):
+ return self.nom
+
+
+class User(models.Model):
+ username = models.CharField(max_length=10)
+ password = models.CharField(max_length=10)
+ type = models.IntegerField()
+
+ class Meta:
+ verbose_name_plural = 'OLD_User'
+ managed = False
+ db_table = 'user'
+
+ def __unicode__(self):
+ return self.username
+
+
+# New models for the 'records' app
+
+class Artist(models.Model):
+ name = models.CharField(max_length=128)
+ def __unicode__(self):
+ return self.name
+
+ class Meta:
+ ordering = ['name']
+
+class Label(models.Model):
+ name = models.CharField(max_length=128)
+ def __unicode__(self):
+ return self.name
+
+ class Meta:
+ ordering = ['name']
+
+class Country(models.Model):
+ name = models.CharField(max_length=128)
+ def __unicode__(self):
+ return self.name
+
+ class Meta:
+ ordering = ['name']
+
+
+class ConditionGrading(models.Model):
+
+ abbr = models.CharField(_('abbreviation'), max_length=5, unique=True)
+ name = models.CharField(_('name'), max_length=128)
+ description = models.TextField(_('description'))
+
+ def __unicode__(self):
+ return " = ".join([self.abbr, self.name])
+
+class Record(models.Model):
+ """
+ Model for Record
+ """
+## # herited fields (from Product):
+## # title --> shop.titre
+## # categories --> shop.theme
+## # price --> shop.prix
+## # status --> shop.published
+ NEW = 1
+ ON_HOLD = 2
+ JUST_SOLD = 3
+ NOVELTY_CHOICES = (
+ (0, ''),
+ (NEW, 'New'),
+ (ON_HOLD, 'On Hold'),
+ (JUST_SOLD, 'Just Sold')
+ )
+
+ YEAR_START = 1920
+
+ YEAR_STOP = datetime.datetime.now().year + 10
+ DECADE_START = (YEAR_START // 10) * 10
+ YEAR_CHOICES = [(y, y) for y in range(YEAR_START, YEAR_STOP)]
+ DECADE_CHOICES = [(d, str(d)+'s') for d in range (DECADE_START, YEAR_STOP, 10)]
+
+ title = models.CharField(max_length=128)
+ artist = models.ForeignKey(Artist, verbose_name=_('artist'), related_name='records_artists', null=True, on_delete=models.SET_NULL)
+ performers = models.ManyToManyField(Artist, verbose_name=_('performers'), related_name='records_performers', blank=True)
+ record_status = models.IntegerField(_('record status'), choices=NOVELTY_CHOICES, default=NEW)
+ label = models.ForeignKey(Label, verbose_name=_('label'), related_name='records', null=True, on_delete=models.SET_NULL)
+ release_year = models.IntegerField(_('release year'), null=True, choices=YEAR_CHOICES)
+ release_decade = models.IntegerField(_('release decade'), null=True, choices=DECADE_CHOICES)
+ date_text = models.CharField(_('date text'), max_length=8, null=True)
+ country = models.ForeignKey(Country, verbose_name=_('country'), related_name='records', null=True, on_delete=models.SET_NULL)
+ cover_condition = models.ForeignKey(ConditionGrading, verbose_name=_('cover condition'), related_name='records_cover_condition', null=True, on_delete=models.SET_NULL)
+ vinyl_condition = models.ForeignKey(ConditionGrading, verbose_name=_('vinyl condition'), related_name='records_vinyl_condition', null=True, on_delete=models.SET_NULL)
+ audio_file = FileField(_("audio file"), max_length=1024, format="audio",
+ upload_to=upload_to("records.Record.audio", "audio/records"), null=True)
+ product = models.OneToOneField(Product, verbose_name=_('product'), related_name='record', null=True, on_delete=models.SET_NULL)
+
+ def __unicode__(self):
+ return " - ".join([self.artist.name, self.title])
+
+ def get_candidate_images(self):
+ candidates = []
+ img_path = os.path.join(settings.MEDIA_ROOT, 'backup_images')
+ patterns = []
+ if self.artist:
+ patterns.append(self.artist.name.strip().lower().replace(' ',''))
+ if self.title:
+ patterns.append(self.title.strip().lower().replace(' ',''))
+ for root, dirnames, filenames in os.walk(img_path):
+ for pattern in patterns:
+ for filename in filenames:
+ if fnmatch.fnmatch(filename.lower(), '*' + pattern + '*.jpg'):
+ candidates.append(os.path.join(root, filename))
+ return candidates
+
+
+class Podcast(BlogPost):
+ audio = FileField(verbose_name=_("Audio File"), max_length=200, format="Audio",
+ upload_to=upload_to("records.Podcast.audio", "audio/mixes"))
+ genre = models.CharField(max_length=128, null=True)
+ # titre --> title
+ old_date = models.CharField(max_length=64, null=True)
+ mix_cloud_url = models.URLField(null=True)
+ # desc --> description
+ # mp3 --> audio
+ #visu1 = models.IntegerField()
+ # ordre : on laisse tombé ?
+ #Â published --> status / 0 --> CONTENT_STATUS_DRAFT = 1 / 1 CONTENT_STATUS_PUBLISHED = 2
+
+
+def payment_complete(sender, **kwargs):
+ """Performs the same logic as the code in
+ cartridge.shop.models.Order.complete(), but fetches the session,
+ order, and cart objects from storage, rather than relying on the
+ request object being passed in (which it isn't, since this is
+ triggered on PayPal IPN callback)."""
+
+ ipn_obj = sender
+
+ if ipn_obj.custom and ipn_obj.invoice and ipn_obj.payment_status == ST_PP_COMPLETED:
+ s_key, cart_pk = ipn_obj.custom.split(',')
+ SessionStore = import_module(settings.SESSION_ENGINE) \
+ .SessionStore
+ session = SessionStore(s_key)
+
+ try:
+ cart = Cart.objects.get(id=cart_pk)
+ try:
+ order = Order.objects.get(
+ transaction_id=ipn_obj.invoice)
+ for field in order.session_fields:
+ if field in session:
+ del session[field]
+ try:
+ del session["order"]
+ except KeyError:
+ pass
+
+ # Since we're manually changing session data outside of
+ # a normal request, need to force the session object to
+ # save after modifying its data.
+ session.save()
+
+ for item in cart:
+ try:
+ variation = ProductVariation.objects.get(
+ sku=item.sku)
+ except ProductVariation.DoesNotExist:
+ pass
+ else:
+ variation.update_stock(item.quantity * -1)
+ variation.product.actions.purchased()
+
+ code = session.get('discount_code')
+ if code:
+ DiscountCode.objects.active().filter(code=code) \
+ .update(uses_remaining=F('uses_remaining') - 1)
+ cart.delete()
+ except Order.DoesNotExist:
+ pass
+ except Cart.DoesNotExist:
+ pass
+
+payment_was_successful.connect(payment_complete)
+valid_ipn_received.connect(payment_complete)
--- /dev/null
+# This is an auto-generated Django model module.\r
+# You'll have to do the following manually to clean this up:\r
+# * Rearrange models' order\r
+# * Make sure each model has one field with primary_key=True\r
+# * Remove `managed = False` lines if you wish to allow Django to create, modify, and delete the table\r
+# Feel free to rename the models, but don't rename db_table values or field names.\r
+#\r
+# Also note: You'll have to insert the output of 'django-admin sqlcustom [app_label]'\r
+# into your database.\r
+from __future__ import unicode_literals\r
+\r
+from django.db import models\r
+\r
+\r
+class Gallery(models.Model):\r
+ titre = models.CharField(max_length=124)\r
+ visu1 = models.IntegerField()\r
+ visu2 = models.IntegerField()\r
+ visu3 = models.IntegerField()\r
+ visu4 = models.IntegerField()\r
+ visu5 = models.IntegerField()\r
+ visu6 = models.IntegerField()\r
+ visu7 = models.IntegerField()\r
+ visu8 = models.IntegerField()\r
+ visu9 = models.IntegerField()\r
+ ordre = models.IntegerField()\r
+ published = models.IntegerField()\r
+\r
+ class Meta:\r
+ managed = False\r
+ db_table = 'gallery'\r
+\r
+\r
+class Grading(models.Model):\r
+ nom = models.CharField(max_length=5)\r
+\r
+ class Meta:\r
+ managed = False\r
+ db_table = 'grading'\r
+\r
+\r
+class Links(models.Model):\r
+ section = models.IntegerField()\r
+ adress = models.CharField(max_length=124)\r
+ desc = models.TextField()\r
+ ordre = models.IntegerField()\r
+ published = models.IntegerField()\r
+\r
+ class Meta:\r
+ managed = False\r
+ db_table = 'links'\r
+\r
+\r
+class Mix(models.Model):\r
+ genre = models.CharField(max_length=128)\r
+ titre = models.CharField(max_length=128)\r
+ date = models.CharField(max_length=64)\r
+ desc = models.TextField()\r
+ mp3 = models.CharField(max_length=128)\r
+ visu1 = models.IntegerField()\r
+ ordre = models.IntegerField()\r
+ published = models.IntegerField()\r
+\r
+ class Meta:\r
+ managed = False\r
+ db_table = 'mix'\r
+\r
+\r
+class News(models.Model):\r
+ titre = models.CharField(max_length=128)\r
+ texte = models.TextField()\r
+ visu1 = models.IntegerField()\r
+ position = models.IntegerField()\r
+ nomlien = models.CharField(max_length=128)\r
+ adresslien = models.CharField(max_length=255)\r
+ typelien = models.IntegerField()\r
+ ordre = models.IntegerField()\r
+ published = models.IntegerField()\r
+\r
+ class Meta:\r
+ managed = False\r
+ db_table = 'news'\r
+\r
+\r
+class Shop(models.Model):\r
+ theme = models.IntegerField()\r
+ artiste = models.CharField(max_length=128)\r
+ new = models.IntegerField()\r
+ titre = models.CharField(max_length=128)\r
+ label = models.CharField(max_length=128)\r
+ date = models.CharField(max_length=8)\r
+ pays = models.CharField(max_length=128)\r
+ desc = models.TextField()\r
+ cover = models.IntegerField()\r
+ vinyl = models.IntegerField()\r
+ prix = models.IntegerField()\r
+ devise = models.IntegerField()\r
+ mp3 = models.CharField(max_length=128)\r
+ visu1 = models.IntegerField()\r
+ ordre = models.IntegerField()\r
+ published = models.IntegerField()\r
+\r
+ class Meta:\r
+ managed = False\r
+ db_table = 'shop'\r
+\r
+\r
+class Theme(models.Model):\r
+ nom = models.CharField(max_length=124)\r
+ ordre = models.IntegerField()\r
+ published = models.IntegerField()\r
+\r
+ class Meta:\r
+ managed = False\r
+ db_table = 'theme'\r
+\r
+\r
+class User(models.Model):\r
+ username = models.CharField(max_length=10)\r
+ password = models.CharField(max_length=10)\r
+ type = models.IntegerField()\r
+\r
+ class Meta:\r
+ managed = False\r
+ db_table = 'user'\r
--- /dev/null
+.container{
+ background:url("../img/dotted_background.png"
+ ) repeat;
+}
+
+.slim_margins{
+ padding-right:1px;
+ padding-left:1px;
+}
+
+body {
+ padding-top: 182px;
+}
+
+hr {
+ display: block;
+ height: 2px;
+ border: 0;
+ border-top: 2px solid #000;
+ margin: 1em 0;
+ padding: 0;
+}
+
+.bg-white {
+ background-color: white;
+ padding: 5px;
+}
+
+.description {
+ background-color: white;
+ padding: 1em 1em 1em 2em;
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
+ border: 1px solid #dddddd;
+ border-radius: 4px;
+}
+
+.navbar-default {
+ background: white;
+ margin-bottom: 30px;
+}
+
+.price:only-child, .coming-soon {
+ margin-top: 3px;
+ display: block;
+ font-weight: bold;
+}
+
+.navbar-collapse {
+ margin-top: 50px;
+}
+
+#logo {
+ float: left;
+}
+
+#user_panel_header {
+ float: right;
+ margin-top: -90px;
+}
+
+.audio {
+ margin-top: 2em;
+}
--- /dev/null
+from django.db.models import Q
+
+from mezzanine import template
+from cartridge.shop.models import Product, Category
+
+register = template.Library()
+
+
+@register.as_tag
+def shop_recent_products(limit=5, category=None):
+ """
+ Put a list of recently published products into the template
+ context. A tag title or slug, category title or slug or author's
+ username can also be specified to filter the recent posts returned.
+ Usage::
+ {% blog_recent_posts 5 as recent_posts %}
+ {% blog_recent_posts limit=5 tag="django" as recent_posts %}
+ {% blog_recent_posts limit=5 category="python" as recent_posts %}
+ """
+ products = Product.objects.published().filter(available=True).order_by("-publish_date")
+ title_or_slug = lambda s: Q(title=s) | Q(slug=s)
+
+ if category is not None:
+ try:
+ category = Category.objects.get(title_or_slug(category))
+ products = products.filter(categories=category)
+ except Category.DoesNotExist:
+ return []
+
+ return list(products[:limit])
--- /dev/null
+from django.test import TestCase
+
+# Create your tests here.
--- /dev/null
+from django.shortcuts import render
+
+# Create your views here.
--- /dev/null
+{% extends "accounts/account_form.html" %}
+{% load i18n %}
+
+{% block account_form_actions %}
+{{ block.super }}
+<a class="btn btn-default btn-lg pull-left" href="{% url "shop_order_history" %}">{% trans "View past orders" %}</a>
+{% endblock %}
--- /dev/null
+<!doctype html>
+<html lang="{{ LANGUAGE_CODE }}"{% if LANGUAGE_BIDI %} dir="rtl"{% endif %}>
+{% load pages_tags mezzanine_tags i18n staticfiles %}
+
+<head>
+<meta http-equiv="Content-type" content="text/html; charset=utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<meta name="keywords" content="{% block meta_keywords %}{% endblock %}">
+<meta name="description" content="{% block meta_description %}{% endblock %}">
+<title>{% block meta_title %}{% endblock %}{% if settings.SITE_TITLE %} | {{ settings.SITE_TITLE }}{% endif %}</title>
+<link rel="shortcut icon" href="{% static "img/favicon.ico" %}">
+
+{% ifinstalled mezzanine.blog %}
+<link rel="alternate" type="application/rss+xml" title="RSS" href="{% url "blog_post_feed" "rss" %}">
+<link rel="alternate" type="application/atom+xml" title="Atom" href="{% url "blog_post_feed" "atom" %}">
+{% endifinstalled %}
+
+{% compress css %}
+<link rel="stylesheet" href="{% static "css/bootstrap.css" %}">
+<link rel="stylesheet" href="{% static "css/mezzanine.css" %}">
+<link rel="stylesheet" href="{% static "css/bootstrap-theme.css" %}">
+{% if LANGUAGE_BIDI %}
+<link rel="stylesheet" href="{% static "css/bootstrap-rtl.css" %}">
+{% endif %}
+{% ifinstalled cartridge.shop %}
+<link rel="stylesheet" href="{% static "css/cartridge.css" %}">
+{% if LANGUAGE_BIDI %}
+<link rel="stylesheet" href="{% static "css/cartridge.rtl.css" %}">
+{% endif %}
+<link rel="stylesheet" href="{% static "css/dig2.css" %}">
+{% endifinstalled %}
+{% block extra_css %}{% endblock %}
+{% endcompress %}
+
+{% compress js %}
+<script src="{% static "mezzanine/js/"|add:settings.JQUERY_FILENAME %}"></script>
+<script src="{% static "js/bootstrap.js" %}"></script>
+<script src="{% static "js/bootstrap-extras.js" %}"></script>
+{% block extra_js %}{% endblock %}
+{% endcompress %}
+
+<!--[if lt IE 9]>
+<script src="{% static "js/html5shiv.js" %}"></script>
+<script src="{% static "js/respond.min.js" %}"></script>
+<![endif]-->
+
+<script>(function(d, s, id) {
+ var js, fjs = d.getElementsByTagName(s)[0];
+ if (d.getElementById(id)) return;
+ js = d.createElement(s); js.id = id;
+ js.src = "//connect.facebook.net/fr_FR/sdk.js#xfbml=1&version=v2.4&appId=348560078520326";
+ fjs.parentNode.insertBefore(js, fjs);
+ }(document, 'script', 'facebook-jssdk'));
+</script>
+
+{% block extra_head %}{% endblock %}
+</head>
+
+<body id="{% block body_id %}body{% endblock %}">
+<div class="navbar navbar-default navbar-fixed-top" role="navigation">
+ <div class="container ">
+ <div class="navbar-header">
+ <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
+ <span class="sr-only">{% trans "Toggle Navigation" %}</span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ </button>
+ <div id="logo">
+ {% if settings.SITE_TITLE %}<a class="navbar-brand" href="/"><img class="pull-left" width="180" src="{% static "img/diggersdigest_400.png" %}"alt={{ settings.SITE_TITLE }} ></a>{% endif %}
+ {% if settings.SITE_TAGLINE %}<p class="navbar-text visible-lg">{{ settings.SITE_TAGLINE }}</p>{% endif %}
+ </div>
+ </div>
+ <div>
+ {% search_form "all" %}
+ </div>
+ <div class="navbar-collapse collapse">
+ {% page_menu "pages/menus/dropdown.html" %}
+ </div>
+ <div id="user_panel_header">
+ {% nevercache %}
+ {% include "includes/language_selector.html" %}
+ {% include "includes/user_panel_header.html" %}
+ {% endnevercache %}
+ </div>
+ <hr>
+</div>
+
+</div>
+
+<div class="container">
+
+{% nevercache %}
+{% if messages %}
+<div class="messages">
+{% for message in messages %}
+<div class="alert alert-dismissable alert-{{ message.tags }}" data-alert="alert">
+ <button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
+ {{ message }}
+</div>
+{% endfor %}
+</div>
+{% endif %}
+{% endnevercache %}
+
+<h1>{% block title %}{% endblock %}</h1>
+
+{% comment - Remove breadcrumbs %}
+<ul class="breadcrumb">
+{% spaceless %}
+{% block breadcrumb_menu %}{% page_menu "pages/menus/breadcrumb.html" %}{% endblock %}
+{% endspaceless %}
+</ul>
+{% endcomment %}
+
+</div>
+
+<div class="container">
+<div class="row">
+
+{% comment - Remove left panel %}
+<div class="col-md-2 left">
+ {% block left_panel %}
+ <div class="panel panel-default tree">{% page_menu "pages/menus/tree.html" %}</div>
+ {% endblock %}
+</div>
+{% endcomment %}
+
+<div class="col-md-12 middle">
+ {% block main %}{% endblock %}
+</div>
+
+{% comment %}
+<div class="col-md-3 right">
+ <div class="panel panel-default">
+ <div class="panel-body">
+ {% block right_panel %}
+ {% ifinstalled mezzanine.twitter %}
+ {% include "twitter/tweets.html" %}
+ {% endifinstalled %}
+ {% endblock %}
+ </div>
+ </div>
+</div>
+{% endcomment %}
+
+</div>
+</div>
+
+<footer>
+<div>
+<!-- {% page_menu "pages/menus/footer.html" %} -->
+
+<div>
+<p class="site-info text-center">
+ {% trans "Coded by" %}
+ <a href="http://www.parisson.com">Parisson</a>
+ <span class="separator">|</span>
+ {% trans "Powered by" %}
+ <a href="http://mezzanine.jupo.org">Mezzanine</a>{% ifinstalled cartridge.shop %},
+ <a href="http://cartridge.jupo.org">Cartridge</a>{% endifinstalled %}
+ {% trans "and" %}
+ <a href="http://www.djangoproject.com">Django</a>
+ <span class="separator">|</span>
+ {% trans "Theme by" %} <a target="_blank" href="http://getbootstrap.com">Bootstrap</a>
+ {% ifinstalled mezzanine.mobile %}
+ <span class="separator">|</span>
+ <a href="{% url "set_device" "mobile" %}?next={{ request.path }}">{% trans "View Mobile Site" %}</a>
+ {% endifinstalled %}
+</p>
+</div>
+<div class="fb-follow"></div>
+</div>
+
+</footer>
+
+{% include "includes/footer_scripts.html" %}
+
+</body>
+</html>
--- /dev/null
+{% extends "blog/blog_post_list.html" %}
+{% load mezzanine_tags comment_tags keyword_tags rating_tags i18n disqus_tags %}
+
+{% block meta_title %}{{ blog_post.meta_title }}{% endblock %}
+
+{% block meta_keywords %}{% metablock %}
+{% keywords_for blog_post as tags %}
+{% for tag in tags %}{% if not forloop.first %}, {% endif %}{{ tag }}{% endfor %}
+{% endmetablock %}{% endblock %}
+
+{% block meta_description %}{% metablock %}
+{{ blog_post.description }}
+{% endmetablock %}{% endblock %}
+
+{% block title %}
+{% editable blog_post.title %}{{ blog_post.title }}{% endeditable %}
+{% endblock %}
+
+{% block breadcrumb_menu %}
+{{ block.super }}
+<li class="active">{{ blog_post.title }}</li>
+{% endblock %}
+
+{% block main %}
+
+{% block blog_post_detail_postedby %}
+{% editable blog_post.publish_date %}
+<h6 class="post-meta">
+ {% trans "Posted by" %}:
+ {% with blog_post.user as author %}
+ <a href="{% url "blog_post_list_author" author %}">{{ author.get_full_name|default:author.username }}</a>
+ {% endwith %}
+ {% blocktrans with sometime=blog_post.publish_date|timesince %}{{ sometime }} ago{% endblocktrans %}
+</h6>
+{% endeditable %}
+{% endblock %}
+{% block blog_post_detail_commentlink %}
+<p>
+ {% if blog_post.allow_comments %}
+ {% if settings.COMMENTS_DISQUS_SHORTNAME %}
+ (<a href="{{ blog_post.get_absolute_url }}#disqus_thread"
+ data-disqus-identifier="{% disqus_id_for blog_post %}">{% spaceless %}
+ {% trans "Comments" %}
+ {% endspaceless %}</a>)
+ {% else %}(<a href="#comments">{% spaceless %}
+ {% blocktrans count comments_count=blog_post.comments_count %}{{ comments_count }} comment{% plural %}{{ comments_count }} comments{% endblocktrans %}
+ {% endspaceless %}</a>)
+ {% endif %}
+ {% endif %}
+</p>
+{% endblock %}
+
+{% block blog_post_detail_featured_image %}
+{% if settings.BLOG_USE_FEATURED_IMAGE and blog_post.featured_image %}
+<p><img class="img-responsive" src="{{ MEDIA_URL }}{% thumbnail blog_post.featured_image 600 0 %}"></p>
+{% endif %}
+{% endblock %}
+
+{% if settings.COMMENTS_DISQUS_SHORTNAME %}
+{% include "generic/includes/disqus_counts.html" %}
+{% endif %}
+
+{% block blog_post_detail_content %}
+{% editable blog_post.content %}
+{{ blog_post.content|richtext_filters|safe }}
+{% endeditable %}
+{% endblock %}
+
+{% block blog_post_detail_keywords %}
+{% keywords_for blog_post as tags %}
+{% if tags %}
+{% spaceless %}
+<ul class="list-inline tags">
+ <li>{% trans "Tags" %}:</li>
+ {% for tag in tags %}
+ <li><a href="{% url "blog_post_list_tag" tag.slug %}">{{ tag }}</a>{% if not forloop.last %}, {% endif %}</li>
+ {% endfor %}
+</ul>
+{% endspaceless %}
+{% endif %}
+{% endblock %}
+
+<br/><br/>
+{% comment %}
+{% block blog_post_detail_rating %}
+<div class="panel panel-default rating">
+ <div class="panel-body">
+ {% rating_for blog_post %}
+ </div>
+</div>
+{% endblock %}
+{% endcomment %}
+
+{% block blog_post_detail_sharebuttons %}
+{% set_short_url_for blog_post %}
+<a class="btn btn-sm share-twitter" target="_blank" href="http://twitter.com/home?status={{ blog_post.short_url|urlencode }}%20{{ blog_post.title|urlencode }}">{% trans "Share on Twitter" %}</a>
+<a class="btn btn-sm share-facebook" target="_blank" href="http://facebook.com/sharer.php?u={{ request.build_absolute_uri }}&t={{ blog_post.title|urlencode }}">{% trans "Share on Facebook" %}</a>
+{% endblock %}
+
+{% block blog_post_previous_next %}
+<ul class="pager">
+{% with blog_post.get_previous_by_publish_date as previous %}
+{% if previous %}
+<li class="previous">
+ <a href="{{ previous.get_absolute_url }}">← {{ previous }}</a>
+</li>
+{% endif %}
+{% endwith %}
+{% with blog_post.get_next_by_publish_date as next %}
+{% if next %}
+<li class="next">
+ <a href="{{ next.get_absolute_url }}">{{ next }} →</a>
+</li>
+{% endif %}
+{% endwith %}
+</ul>
+{% endblock %}
+
+{% block blog_post_detail_related_posts %}
+{% if related_posts %}
+<div id="related-posts">
+<h3>{% trans 'Related posts' %}</h3>
+<ul class="list-unstyled">
+{% for post in related_posts %}
+ <li><a href="{{ post.get_absolute_url }}">{{ post.title }}</a></li>
+{% endfor %}
+</ul>
+</div>
+{% endif %}
+{% endblock %}
+
+{% block blog_post_detail_comments %}
+{% if blog_post.allow_comments %}{% comments_for blog_post %}{% endif %}
+{% endblock %}
+
+{% endblock %}
--- /dev/null
+{% extends "base.html" %}
+{% load i18n mezzanine_tags blog_tags keyword_tags disqus_tags %}
+
+{% block meta_title %}{% if page %}{{ page.meta_title }}{% else %}{% trans "Blog" %}{% endif %}{% endblock %}
+
+{% block meta_keywords %}{% metablock %}
+{% keywords_for page as keywords %}
+{% for keyword in keywords %}
+ {% if not forloop.first %}, {% endif %}
+ {{ keyword }}
+{% endfor %}
+{% endmetablock %}{% endblock %}
+
+{% block meta_description %}{% metablock %}
+{{ page.description }}
+{% endmetablock %}{% endblock %}
+
+{% block title %}
+{% if page %}
+{% editable page.title %}{{ page.title }}{% endeditable %}
+{% else %}
+{% trans "Blog" %}
+{% endif %}
+{% endblock %}
+
+{% block breadcrumb_menu %}
+{{ block.super }}
+{% if tag or category or year or month or author %}
+<li>{% spaceless %}
+{% if tag %}
+ {% trans "Tag:" %} {{ tag }}
+{% else %}{% if category %}
+ {% trans "Category:" %} {{ category }}
+{% else %}{% if year or month %}
+ {% if month %}{{ month }}, {% endif %}{{ year }}
+{% else %}{% if author %}
+ {% trans "Author:" %} {{ author.get_full_name|default:author.username }}
+{% endif %}{% endif %}{% endif %}{% endif %}
+{% endspaceless %}
+</li>
+{% endif %}
+{% endblock %}
+
+{% block main %}
+
+{% if tag or category or year or month or author %}
+ {% block blog_post_list_filterinfo %}
+ <p>
+ {% if tag %}
+ {% trans "Viewing posts tagged" %} {{ tag }}
+ {% else %}{% if category %}
+ {% trans "Viewing posts for the category" %} {{ category }}
+ {% else %}{% if year or month %}
+ {% trans "Viewing posts from" %} {% if month %}{{ month }}, {% endif %}
+ {{ year }}
+ {% else %}{% if author %}
+ {% trans "Viewing posts by" %}
+ {{ author.get_full_name|default:author.username }}
+ {% endif %}{% endif %}{% endif %}{% endif %}
+ {% endblock %}
+ </p>
+{% else %}
+ {% if page %}
+ {% block blog_post_list_pagecontent %}
+ {% if page.get_content_model.content %}
+ {% editable page.get_content_model.content %}
+ {{ page.get_content_model.content|richtext_filters|safe }}
+ {% endeditable %}
+ {% endif %}
+ {% endblock %}
+ {% endif %}
+{% endif %}
+
+{% for blog_post in blog_posts.object_list %}
+{% block blog_post_list_post_title %}
+{% editable blog_post.title %}
+<h2>
+ <a href="{{ blog_post.get_absolute_url }}">{{ blog_post.title }}</a>
+</h2>
+{% endeditable %}
+{% endblock %}
+{% block blog_post_list_post_metainfo %}
+{% editable blog_post.publish_date %}
+<h6 class="post-meta">
+ {% trans "Posted by" %}:
+ {% with blog_post.user as author %}
+ <a href="{% url "blog_post_list_author" author %}">{{ author.get_full_name|default:author.username }}</a>
+ {% endwith %}
+ {% with blog_post.categories.all as categories %}
+ {% if categories %}
+ {% trans "in" %}
+ {% for category in categories %}
+ <a href="{% url "blog_post_list_category" category.slug %}">{{ category }}</a>{% if not forloop.last %}, {% endif %}
+ {% endfor %}
+ {% endif %}
+ {% endwith %}
+ {% blocktrans with sometime=blog_post.publish_date|timesince %}{{ sometime }} ago{% endblocktrans %}
+</h6>
+{% endeditable %}
+{% endblock %}
+
+{% if settings.BLOG_USE_FEATURED_IMAGE and blog_post.featured_image %}
+{% block blog_post_list_post_featured_image %}
+<a href="{{ blog_post.get_absolute_url }}">
+ <img class="img-thumbnail pull-left" src="{{ MEDIA_URL }}{% thumbnail blog_post.featured_image 90 90 %}">
+</a>
+{% endblock %}
+{% endif %}
+
+{% block blog_post_list_post_content %}
+{% editable blog_post.content %}
+{{ blog_post.description_from_content|safe }}
+{% endeditable %}
+{% endblock %}
+
+{% block blog_post_list_post_links %}
+<div class="blog-list-detail">
+ {% keywords_for blog_post as tags %}
+ {% if tags %}
+ <ul class="list-inline tags">
+ {% trans "Tags" %}:
+ {% spaceless %}
+ {% for tag in tags %}
+ <li><a href="{% url "blog_post_list_tag" tag.slug %}" class="tag">{{ tag }}</a>{% if not forloop.last %}, {% endif %}</li>
+ {% endfor %}
+ {% endspaceless %}
+ </ul>
+ {% endif %}
+ <p>
+ <a href="{{ blog_post.get_absolute_url }}">{% trans "read more" %}</a>
+ {% if blog_post.allow_comments %}
+ /
+ {% if settings.COMMENTS_DISQUS_SHORTNAME %}
+ <a href="{{ blog_post.get_absolute_url }}#disqus_thread"
+ data-disqus-identifier="{% disqus_id_for blog_post %}">
+ {% trans "Comments" %}
+ </a>
+ {% else %}
+ <a href="{{ blog_post.get_absolute_url }}#comments">
+ {% blocktrans count comments_count=blog_post.comments_count %}{{ comments_count }} comment{% plural %}{{ comments_count }} comments{% endblocktrans %}
+ </a>
+ {% endif %}
+ {% endif %}
+ </p>
+</div>
+{% endblock %}
+{% endfor %}
+
+{% pagination_for blog_posts %}
+
+{% if settings.COMMENTS_DISQUS_SHORTNAME %}
+{% include "generic/includes/disqus_counts.html" %}
+{% endif %}
+
+{% endblock %}
+
+{% block right_panel %}
+{% include "blog/includes/filter_panel.html" %}
+{% endblock %}
--- /dev/null
+{% load blog_tags keyword_tags mezzanine_tags i18n %}
+
+{% block blog_recent_posts %}
+{% blog_recent_posts 5 as recent_posts %}
+{% if recent_posts %}
+<h3>{% trans "Recent Posts" %}</h3>
+<ul class="list-unstyled recent-posts">
+{% for recent_post in recent_posts %}
+<li>
+ {% spaceless %}
+ <a href="{{ recent_post.get_absolute_url }}">
+ {% if settings.BLOG_USE_FEATURED_IMAGE and recent_post.featured_image %}
+ <img src="{{ MEDIA_URL }}{% thumbnail recent_post.featured_image 24 24 %}">
+ {% endif %}
+ {{ recent_post.title }}
+ </a>
+ {% endspaceless %}
+</li>
+{% endfor %}
+</ul>
+{% endif %}
+{% endblock %}
+
+{% block blog_months %}
+{% blog_months as months %}
+{% if months %}
+<h3>{% trans "Archive" %}</h3>
+{% for month in months %}
+ {% ifchanged month.date.year %}
+ {% if not forloop.first %}</ul>{% endif %}
+ <h6>{{ month.date.year }}</h6><ul class="list-unstyled">
+ {% endifchanged %}
+ <li><a href="{% url "blog_post_list_month" year=month.date.year month=month.date.month %}"
+ >{{ month.date|date:"F" }}</a> ({{ month.post_count }})</li>
+{% endfor %}
+</ul>
+{% endif %}
+{% endblock %}
+
+{% block blog_categories %}
+{% blog_categories as categories %}
+{% if categories %}
+<h3>{% trans "Categories" %}</h3>
+<ul class="list-unstyled">
+{% for category in categories %}
+<li><a href="{% url "blog_post_list_category" category.slug %}"
+ >{{ category }}</a> ({{ category.post_count }})</li>
+{% endfor %}
+</ul>
+{% endif %}
+{% endblock %}
+
+{% block blog_keywords %}
+{% keywords_for blog.blogpost as tags %}
+{% if tags %}
+<h3>{% trans "Tags" %}</h3>
+<ul class="list-inline tag-cloud">
+{% for tag in tags %}
+<li>
+ <a href="{% url "blog_post_list_tag" tag.slug %}"
+ class="tag-weight-{{ tag.weight }}">{{ tag }}</a>
+ ({{ tag.item_count }})
+</li>
+{% endfor %}
+</ul>
+{% endif %}
+{% endblock %}
+
+{% block blog_authors %}
+{% blog_authors as authors %}
+{% if authors %}
+<h3>{% trans "Authors" %}</h3>
+<ul class="list-unstyled">
+{% for author in authors %}
+ <li><a href="{% url "blog_post_list_author" author.username %}"
+ >{{ author.get_full_name|default:author.username }}</a>
+ ({{ author.post_count }})</li>
+{% endfor %}
+</ul>
+{% endif %}
+{% endblock %}
+
+{% block blog_feeds %}
+<h3>{% trans "Feeds" %}</h3>
+{% if tag %}
+ <a href="{% url "blog_post_feed_tag" tag.slug "rss" %}">{% trans "RSS" %}</a> /
+ <a href="{% url "blog_post_feed_tag" tag.slug "atom" %}">{% trans "Atom" %}</a>
+{% endif %}
+{% if category %}
+ <a href="{% url "blog_post_feed_category" category.slug "rss" %}">{% trans "RSS" %}</a> /
+ <a href="{% url "blog_post_feed_category" category.slug "atom" %}">{% trans "Atom" %}</a>
+{% endif %}
+{% if author %}
+ <a href="{% url "blog_post_feed_author" author.username "rss" %}">{% trans "RSS" %}</a> /
+ <a href="{% url "blog_post_feed_author" author.username "atom" %}">{% trans "Atom" %}</a>
+{% endif %}
+{% if not tag and not category and not author %}
+ <a href="{% url "blog_post_feed" "rss" %}">{% trans "RSS" %}</a> /
+ <a href="{% url "blog_post_feed" "atom" %}">{% trans "Atom" %}</a>
+{% endif %}
+{% endblock %}
--- /dev/null
+{% load i18n %}
+{% get_current_language_bidi as LANGUAGE_BIDI %}
+
+{% block main %}
+{% endblock %}
--- /dev/null
+{% block main %}{% endblock %}
+
+http://{{ request.get_host }}
--- /dev/null
+{% extends "email/base.html" %}
+{% load i18n %}
+
+
+{% block main %}
+
+{% if not LANGUAGE_BIDI %}
+ {% include "email/receipt.html" %}
+{% else %}
+ {% include "email/receipt_rtl.html" %}
+{% endif %}
+
+{% endblock %}
--- /dev/null
+{% extends "email/base.txt" %}
+{% load shop_tags i18n %}
+
+{% block main %}
+{% trans "Dear" %} {{ order.billing_detail_first_name }},
+
+{% trans "Your order has been successful, details are below." %}
+
+{% trans "Order ID:" %} #{{ order.id }}
+
+{% trans "Billing Details:" %}
+{% for field, value in order_billing_detail_fields %}
+{{ field }}: {{ value }}
+{% endfor %}
+
+{% trans "Shipping Details:" %}
+{% for field, value in order_shipping_detail_fields %}
+{{ field }}: {{ value }}
+{% endfor %}
+
+{% trans "Items Ordered:" %}
+{% for item in order_items %}
+{{ item.quantity }} x {{ item.description }} {{ item.unit_price|currency }} {% trans "each" %}
+{% endfor %}
+
+{% order_totals_text %}
+{% endblock %}
--- /dev/null
+{% load shop_tags i18n %}
+
+<p>{% trans "Dear" %} {{ order.billing_detail_first_name }},</p>
+<p>{% trans "Your order has been successful, details are below." %}</p>
+{% include "shop/includes/order_details.html" %}
+
--- /dev/null
+{% load shop_tags i18n %}
+
+<p align="right">,{% trans "Dear" %} {{ order.billing_detail_first_name }}</p>
+<p align="right">{% trans "Your order has been successful, details are below." %}</p>
+{% include "shop/includes/order_details_rtl.html" %}
+
--- /dev/null
+{% extends "base.html" %}
+
+{% load i18n %}
+
+{% block meta_title %}
+{% trans "Page not found" %}
+{% endblock %}
+
+{% block title %}
+{% trans "Page not found" %}
+{% endblock %}
+
+{% block main %}
+<div class="panel panel-danger">
+ <div class="panel-heading"><h3 class="panel-title">{% trans "Page not found" %}</h3></div>
+ <div class="panel-body">{% trans "The page you requested does not exist." %}</div>
+</div>
+{% endblock %}
--- /dev/null
+{% extends "base.html" %}
+
+{% load i18n %}
+
+{% block meta_title %}
+{% trans "Error" %}
+{% endblock %}
+
+{% block title %}
+{% trans "Error" %}
+{% endblock %}
+
+{% block main %}
+<div class="panel panel-danger">
+ <div class="panel-heading"><h3 class="panel-title">{% trans "Error" %}</h3></div>
+ <div class="panel-body">{% trans "Sorry, an error occurred." %}</div>
+</div>
+{% endblock %}
--- /dev/null
+{% load i18n %}
+
+{# Edit form #}
+<form style="display:none;" class="editable-form" method="post"
+ action="{% url "edit" %}" id="{{ editable_form.uuid }}"
+ {% if editable_form.is_multipart %} enctype="multipart/form-data"{% endif %}>
+ {% csrf_token %}
+ {% for field in editable_form %}
+ <p{% if field.is_hidden %} style="display:none;"{% endif %}>
+ {{ field.label_tag }}<br />{{ field }}{{ field.errors }}
+ {% if field.help_text %}
+ <span class="helptext">{{ field.help_text }}</span>
+ {% endif %}
+ </p>
+ {% endfor %}
+ <input type="submit" value="{% trans "Save" %}" class="btn btn-primary btn-lg">
+ <input type="button" value="{% trans "Cancel" %}" class="btn btn-default btn-lg">
+</form>
+
+{# Original content wrapped in span #}
+<div class="editable-original">{{ original }}</div>
+
+{# Edit link #}
+<a style="visibility:hidden;" class="editable-link" href="#"
+ rel="#{{ editable_form.uuid }}">{% trans "Edit" %}</a>
+
+{# Edit highlight #}
+<div style="visibility:hidden;" class="editable-highlight"></div>
--- /dev/null
+{% load i18n staticfiles %}
+
+{% if has_site_permission %}
+<link rel="stylesheet" href="{% static "mezzanine/css/editable.css" %}">
+{{ richtext_media|safe }}
+<script>
+{% url "fb_browse" as fb_browse_url %}
+{% url "static_proxy" as static_proxy_url %}
+{% get_current_language as LANGUAGE_CODE %}
+window.__filebrowser_url = '{{ fb_browse_url }}';
+window.__toolbar_html = '{{ toolbar|escapejs }}';
+window.__static_proxy = '{{ static_proxy_url }}';
+window.__language_code = '{{ LANGUAGE_CODE }}';
+window.__tinymce_css = '{% static "mezzanine/css/tinymce.css" %}';
+</script>
+<script src="{% static "mezzanine/js/jquery.tools.toolbox.expose.js" %}"></script>
+<script src="{% static "mezzanine/js/jquery.tools.overlay.js" %}"></script>
+<script src="{% static "mezzanine/js/jquery.form.js" %}"></script>
+<script src="{% static "mezzanine/js/editable.js" %}"></script>
+{% endif %}
--- /dev/null
+{% load i18n staticfiles %}
+
+<div id="editable-toolbar" method="POST" action="{% url "admin:logout" %}">
+ {% url "admin:index" as admin_index_url %}
+ {% url "admin:logout" as admin_logout_url %}
+ {% url "logout" as accounts_logout_url %}
+ <a id="editable-toolbar-toggle" href="#"></a>
+ <a href="{{ editable_obj.get_admin_url|default:admin_index_url }}">{% trans "Admin" %}</a>
+ <a href="{{ accounts_logout_url|default:admin_logout_url }}?{{ REDIRECT_FIELD_NAME }}={{ request.path }}">{% trans "Log out" %}</a>
+</div>
+
+<img id="editable-loading" src="{% static "mezzanine/img/loadingAnimation.gif" %}">
+
--- /dev/null
+{% load mezzanine_tags %}
+
+{% editable_loader %}
+
+<script>
+{% if settings.GOOGLE_ANALYTICS_ID and not request.user.is_staff %}
+var _gaq = _gaq || [['_trackPageview']];
+_gaq.unshift(['_setAccount', '{{ settings.GOOGLE_ANALYTICS_ID }}']);
+(function(d, t) {
+ var g = d.createElement(t),
+ s = d.getElementsByTagName(t)[0];
+ g.async = true;
+ g.src = '//www.google-analytics.com/ga.js';
+ s.parentNode.insertBefore(g, s);
+})(document, 'script');
+{% endif %}
+</script>
--- /dev/null
+{% load i18n %}
+
+{% if form.non_field_errors or form.errors %}
+<div class="form-errors">
+ {% for error in form.non_field_errors %}
+ <div class="alert alert-danger non-field-error">{{ error }}</div>
+ {% empty %}
+ <div class="alert alert-danger field-error">{% trans "Please correct the errors below." %}</div>
+ {% endfor %}
+</div>
+{% endif %}
--- /dev/null
+{% load mezzanine_tags %}
+
+{% nevercache %}
+<input type="hidden" name="referrer" value="{{ request.META.HTTP_REFERER }}">
+{% csrf_token %}
+{% endnevercache %}
+
+{% for field in form_for_fields %}
+{% if field.is_hidden %}
+{{ field }}
+{% else %}
+<div class="form-group input_{{ field.id_for_label }} {{ field.field.type }}
+ {% if field.errors %} has-error{% endif %}">
+ {% if field.label %}<label class="control-label" for="{{ field.auto_id }}">{{ field.label }}</label>{% endif %}
+ {{ field }}
+ {% if field.errors %}
+ <p class="help-block">
+ {% for e in field.errors %}
+ {% if not forloop.first %} / {% endif %}{{ e }}
+ {% endfor %}
+ </p>
+ {% elif field.help_text %}
+ <p class="help-block">{{ field.help_text }}</p>
+ {% endif %}
+</div>
+{% endif %}
+{% endfor %}
--- /dev/null
+{% load i18n %}
+{% get_language_info_list for LANGUAGES as languages %}
+{% if settings.USE_MODELTRANSLATION and languages|length > 1 %}
+{# hide submit button if browser has javascript support and can react to onchange event #}
+<script>$(document).ready(function(){$('#language_selector_form').change(function(){this.submit();});$('#language_selector_form input').hide();});</script>
+<div>
+<form action="{% url "set_language" %}" method="post" id="language_selector_form">
+ {% csrf_token %}
+ <div class="form-group">
+ <select name="language" class="form-control">
+ {% for language in languages %}
+ <option value="{{ language.code }}"
+ {% if language.code == LANGUAGE_CODE %}selected="selected"{% endif %}>
+ {{ language.name_local }}
+ </option>
+ {% endfor %}
+ </select>
+ </div>
+ <input type="submit" class="btn btn-default" value="{% trans "Change" %}" />
+</form>
+</div>
+{% endif %}
--- /dev/null
+{% load i18n %}
+
+{% if current_page.has_previous or current_page.has_next %}
+<ul class="pagination">
+
+<li class="page-info">
+ <span>{% trans "Page" %} {{ current_page.number }} {% trans "of" %} {{ current_page.paginator.num_pages }}</span>
+</li>
+<li class="prev previous{% if not current_page.has_previous %} disabled{% endif %}">
+ <a{% if current_page.has_previous %} href="?{{ page_var }}={{ current_page.previous_page_number }}{% if querystring %}&{{ querystring }}{% endif %}"{% endif %}>←</a>
+</li>
+{% for page in current_page.visible_page_range %}
+<li{% if page == current_page.number %} class="active"{% endif %}>
+ <a href="?{{ page_var }}={{ page }}{% if querystring %}&{{ querystring }}{% endif %}">{{ page }}</a>
+</li>
+{% endfor %}
+<li class="next{% if not current_page.has_next %} disabled{% endif %}">
+ <a{% if current_page.has_next %} href="?{{ page_var }}={{ current_page.next_page_number }}{% if querystring %}&{{ querystring }}{% endif %}"{% endif %}>→</a>
+</li>
+
+</ul>
+{% endif %}
--- /dev/null
+{% load mezzanine_tags i18n %}
+<form action="{% url "search" %}" class="navbar-form navbar-right" role="search">
+
+<div class="form-group">
+ <input class="form-control" placeholder="{% trans "Search" %}" type="text" name="q" value="{{ request.REQUEST.q }}">
+</div>
+
+{% if search_model_choices %}
+ {% if search_model_choices|length == 1 %}
+ <input type="hidden" name="type" value="{{ search_model_choices.0.1 }}">
+ {% else %}
+ <div class="form-group">
+ <select class="form-control" name="type">
+ <option value="">{% trans "Everything" %}</option>
+ {% for verbose_name, model in search_model_choices %}
+ <option value="{{ model }}"
+ {% if model == request.REQUEST.type %}selected{% endif %}>
+ {{ verbose_name }}
+ </option>
+ {% endfor %}
+ </select>
+ </div>
+ {% endif %}
+{% endif %}
+
+<input type="submit" class="btn btn-default" value="{% trans "Go" %}">
+
+</form>
--- /dev/null
+{% load mezzanine_tags %}
+<div class="panel panel-default user-panel">
+<div class="panel-body">
+{% ifinstalled cartridge.shop %}
+{% include "shop/includes/user_panel.html" %}
+{% endifinstalled %}
+{% ifinstalled mezzanine.accounts %}
+{% ifinstalled cartridge.shop %}<br>{% endifinstalled %}
+{% include "accounts/includes/user_panel.html" %}
+{% endifinstalled %}
+</div>
+</div>
--- /dev/null
+{% load mezzanine_tags %}
+<div class="">
+{% ifinstalled cartridge.shop %}
+{% include "shop/includes/user_panel_header.html" %}
+{% endifinstalled %}
+{% ifinstalled mezzanine.accounts %}
+{% ifinstalled cartridge.shop %}<br>{% endifinstalled %}
+{% include "accounts/includes/user_panel.html" %}
+{% endifinstalled %}
+</div>
--- /dev/null
+{% extends "base.html" %}
+{% load i18n %}
+{% load blog_tags records_tags keyword_tags i18n mezzanine_tags %}
+
+{% block meta_title %}{% trans "Home" %}{% endblock %}
+{% comment %}
+{% block title %}{% trans "Home" %}{% endblock %}
+{% endcomment %}
+
+{% block breadcrumb_menu %}
+<li class="active">{% trans "Home" %}</li>
+{% endblock %}
+
+{% block main %}
+
+<div class="col-xs-6 col-md-6"><!-- Showcase-->
+{% shop_recent_products limit=2 category="Showcase" as recent_products %}
+{% if recent_products %}
+<h2><span class="bg-white">{% trans "Featured" %}</span></h2>
+<div class="row">
+ {% for product in recent_products %}
+ <div class="col-xs-12 col-md-12 product-thumb ">
+ <a href="{{ product.get_absolute_url }}" class="thumbnail">
+ {% if product.image %}
+ <img src="{{ MEDIA_URL }}{% thumbnail product.image 512 512 %}">
+ {% else %}
+ <div class="placeholder"></div>
+ {% endif %}
+ <div class="caption">
+ <h6>{{ product }}</h6>
+ {% with product.variations.all as variations %}
+ {% include "shop/includes/price.html" %}
+ {% endwith %}
+ </div>
+ </a>
+ </div>
+{% endfor %}
+</div>
+{% endif %}
+
+</div><!-- /Showcase -->
+
+<div class="col-xs-6 col-md-6"><!-- Latest Releases -->
+{% shop_recent_products 9 as recent_products %}
+{% if recent_products %}
+<h2><span class="bg-white">{% trans "Latest Releases" %}</span></h2>
+<div class="row">
+ {% for product in recent_products %}
+ <div class="col-xs-4 col-md-4 product-thumb slim_margins">
+ <a href="{{ product.get_absolute_url }}" class="thumbnail">
+ {% if product.image %}
+ <img src="{{ MEDIA_URL }}{% thumbnail product.image 148 148 %}">
+ {% else %}
+ <div class="placeholder"></div>
+ {% endif %}
+ <div class="caption">
+ <h6>{{ product.record }}</h6>
+ </div>
+ </a>
+ </div>
+{% endfor %}
+</div>
+{% endif %}
+</div><!-- /Latest Releases -->
+
+<div><!-- Recent Posts -->
+{% blog_recent_posts 5 as recent_posts %}
+{% if recent_posts %}
+<h2>{% trans "Recent Posts" %}</h2>
+{% for recent_post in recent_posts %}
+{% if settings.BLOG_USE_FEATURED_IMAGE and recent_post.featured_image %}
+ {% block recent_post_list_post_featured_image %}
+ <a href="{{ recent_post.get_absolute_url }}">
+ <img class="img-thumbnail pull-left" src="{{ MEDIA_URL }}{% thumbnail recent_post.featured_image 90 90 %}">
+ </a>
+ {% endblock %}
+ {% endif %}
+<h3><a href="{{ recent_post.get_absolute_url }}"
+ >{{ recent_post.title }}</a></h3>
+
+ <h4>{{ recent_post.publish_date|timesince }} {% trans "ago" %}</h4>
+<div class="recent-summary">
+{{ recent_post.description_from_content|safe }}
+
+ <a href="{{ recent_post.get_absolute_url }}" class="btn btn-info btn-mini">{% trans "read more" %}</a>
+ <hr>
+ {% if recent_post.categories %}
+ {{ recent_post.categories. }}
+ {% endif %}
+
+</div><!-- /recent-summary -->
+{% endfor %}
+{% endif %}
+
+</div><!-- /Recent Posts -->
+
+
+{% endblock %}
--- /dev/null
+{% extends "pages/page.html" %}
+
+{% load mezzanine_tags shop_tags i18n %}
+{% block body_id %}category{% endblock %}
+
+{% block main %}{{ block.super }}
+
+{% editable page.category.content %}
+{{ page.category.content|safe }}
+{% endeditable %}
+
+{% if child_categories %}
+<div class="row shop-category-list">
+{% if settings.SHOP_CATEGORY_USE_FEATURED_IMAGE %}
+ {% for category in child_categories %}
+ <div class="col-xs-6 col-sm-4 col-lg-3">
+ <a href="{{ category.get_absolute_url }}" class="thumbnail">
+ {% if category.featured_image %}
+ <img src="{{ MEDIA_URL }}{% thumbnail category.featured_image 148 148 %}" />
+ {% else %}
+ <div class="placeholder"></div>
+ {% endif %}
+ <div class="caption">
+ <h4>{{ category.title }}</h4>
+ </div>
+ </a>
+ </div>
+ {% endfor %}
+{% else %}
+ {% for category in child_categories %}
+ <div class="col-xs-6 col-sm-4 col-lg-3">
+ <a href="{{ category.get_absolute_url }}" class="thumbnail">
+ <div class="caption"><h4>{{ category.title }}</h4></div>
+ </a>
+ </div>
+ {% endfor %}
+{% endif %}
+</div>
+{% endif %}
+
+{% if products.paginator.count != 0 %}
+
+<form class="product-sorting" role="form">
+ <div class="form-group">
+ <label class="control-label" for="sorting-select">{% trans "Sort by" %}</label>
+ <select onchange="location.href = this[this.selectedIndex].value;" class="form-control" id="sorting-select">
+ {% for name, option in settings.SHOP_PRODUCT_SORT_OPTIONS %}
+ {% if "rating" not in option or settings.SHOP_USE_RATINGS %}
+ <option{% if option == products.sort_by %} selected{% endif %}
+ value="{{ category.get_absolute_url }}?sort={{ option }}{{ querystring }}">
+ {{ name }}
+ </option>
+ {% endif %}
+ {% endfor %}
+ </select>
+ </div>
+</form>
+
+<div class="row product-list">
+{% for product in products.object_list %}
+ <div class="col-xs-6 col-sm-4 col-lg-3 product-thumb slim_margins">
+ <a href="{{ product.get_absolute_url }}" class="thumbnail">
+ {% if product.image %}
+ <img src="{{ MEDIA_URL }}{% thumbnail product.image 148 148 %}">
+ {% else %}
+ <div class="placeholder"></div>
+ {% endif %}
+ <div class="caption">
+ <h6>{{ product }}</h6>
+ <div class="price-info">
+ {% if product.has_price %}
+ {% if product.on_sale %}
+ <span class="old-price">{{ product.unit_price|currency }}</span>
+ {% trans "On sale:" %}
+ {% endif %}
+ <span class="price">{{ product.price|currency }}</span>
+ {% else %}
+ <span class="coming-soon">{% trans "Coming soon" %}</span>
+ {% endif %}
+ </div>
+ </div>
+ </a>
+ </div>
+{% endfor %}
+</div>
+
+{% pagination_for products %}
+
+{% endif %}
+
+{% endblock %}
--- /dev/null
+{% extends "pages/richtextpage.html" %}
+
+{% block main %}
+<!--
+This template is provided as a custom template for the homepage, for
+when it is configured as an editable page in the navigation tree. Feel
+free to modify it.
+-->
+{{ block.super }}
+{% endblock %}
--- /dev/null
+{% load pages_tags i18n staticfiles %}
+
+<ol>
+ {% for page in page_branch %}
+ <li id="ordering_{{ page.id }}">
+ <div class="{% cycle 'row1' 'row2' %}">
+ <a href="#" class="tree-toggle" id="page-{{ page.id }}"
+ {% if not page.has_children %}style="visibility:hidden;"{% endif %}>
+ <span class="icon open">+</span>
+ <span class="icon close">-</span>
+ </a>
+ {% set_page_permissions page %}
+ {% if page.perms.delete %}
+ <a href="{% url "admin:pages_page_delete" page.id %}?fromtree" class="delete"></a>
+ {% else %}
+ <span class="delete" style="background:none;"></span>
+ {% endif %}
+ {% if page.perms.change %}
+ <a href="{% url "admin:pages_page_change" page.id %}{% if not page.is_primary %}?parent={{ page.parent_id }}{% endif %}"
+ class="changelink">{{ page.title.strip|default:" " }}</a>
+ {% else %}
+ <span class="uneditable">{{ page.title }}</span>
+ {% endif %}
+ <span class="ordering"{% if not page.perms.change %}
+ style="visibility:hidden;"{% endif %}>
+ <img src="{% static settings.MEZZANINE_ADMIN_PREFIX|add:"img/admin/arrow-up.gif" %}">
+ <img src="{% static settings.MEZZANINE_ADMIN_PREFIX|add:"img/admin/arrow-down.gif" %}">
+ </span>
+ {% if page.perms.add %}
+ <select class="addlist" id="addlink-{{ page.id }}">
+ <option value="">{% trans "Add" %} ...</option>
+ {% for model in page_models %}
+ {% if model.perms.add %}
+ <option value="{{ model.add_url }}?parent={{ page.id }}"
+ >{{ model.meta_verbose_name|capfirst }}</option>
+ {% endif %}
+ {% endfor %}
+ </select>
+ {% endif %}
+
+ </div>
+ <br style="clear:both;">
+ {% if page.has_children %}{% page_menu page %}{% endif %}
+ </li>
+ {% endfor %}
+</ol>
--- /dev/null
+{% load i18n pages_tags %}
+
+{% if on_home %}
+<li>{% trans "Home" %}</li>
+{% else %}
+{% for page in page_branch %}
+
+ {% if not has_home and page.is_primary and forloop.first %}
+ <li id="breadcrumb-menu-home">
+ <a href="{% url "home" %}">{% trans "Home" %}</a>
+ </li>
+ {% endif %}
+
+ {% if page.is_current_or_ascendant %}
+ {% if page.is_current %}
+ <li id="breadcrumb-menu-{{ page.html_id }}"
+ class="active">{{ page.title }}</li>
+ {% else %}
+ <li id="breadcrumb-menu-{{ page.html_id }}">
+ <a href="{{ page.get_absolute_url }}">{{ page.title }}</a>
+ </li>
+ {% endif %}
+ {% if page.has_children %}{% page_menu page %}{% endif %}
+ {% endif %}
+
+{% endfor %}
+{% endif %}
--- /dev/null
+{% load i18n pages_tags %}
+{% spaceless %}
+{% if page_branch_in_menu %}
+
+{% if branch_level == 0 %}
+<ul class="nav navbar-nav">
+ {% for page in page_branch %}
+ {% if not has_home and page.is_primary and forloop.first %}
+ <li{% if on_home %} class="active"{% endif %} id="dropdown-menu-home">
+ <a href="{% url "home" %}">{% trans "Home" %}</a>
+ </li>
+ {% endif %}
+ {% if page.in_menu %}
+ <li class="{% if page.has_children_in_menu %}dropdown{% endif %}
+ {% if page.is_current_or_ascendant %}active{% endif %}"
+ id="{{ page.html_id }}">
+ <a href="{{ page.get_absolute_url }}"
+ {% if page.has_children_in_menu %}
+ class="dropdown-toggle disabled" data-toggle="dropdown"
+ {% endif %}>
+ {{ page.title }}
+ {% if page.has_children_in_menu %}<b class="caret"></b>{% endif %}
+ </a>
+ {% if page.has_children_in_menu %}{% page_menu page %}{% endif %}
+ </li>
+ {% endif %}
+ {% endfor %}
+</ul>
+
+{% else %}
+<ul class="dropdown-menu">
+ {% for page in page_branch %}
+ {% if page.in_menu %}
+ <li class="{% if page.has_children_in_menu %}dropdown-submenu{% endif %}
+ {% if page.is_current_or_ascendant %}active{% endif %}"
+ id="{{ page.html_id }}">
+ <a href="{{ page.get_absolute_url }}">{{ page.title }}</a>
+ {% if page.has_children_in_menu %}{% page_menu page %}{% endif %}
+ </li>
+ {% endif %}
+ {% endfor %}
+</ul>
+{% endif %}
+
+{% endif %}
+{% endspaceless %}
--- /dev/null
+{% load i18n pages_tags %}
+
+{% spaceless %}
+{% if page_branch_in_menu %}
+
+{% for page in page_branch %}
+ {% if page.is_primary %}
+ {% if forloop.first %}
+ <div class="nav-footer">
+ {% endif %}
+ {% if page.in_menu %}
+ <ul class="list-unstyled">
+ {% endif %}
+ {% endif %}
+
+ {% if page.in_menu %}
+ {% if forloop.first and not page.parent.in_menu and not page.is_primary %}
+ <ul class="list-unstyled">
+ {% endif %}
+ <li {% if page.is_current_or_ascendant %}class="active"{% endif %}
+ id="footer-menu-{{ page.html_id }}">
+ <a href="{{ page.get_absolute_url }}">{{ page.title }}</a></li>
+ {% endif %}
+
+ {% if page.in_menu and page.has_children_in_menu %}{% page_menu page %}{% endif %}
+
+ {% if page.in_menu %}
+ {% if forloop.first and not page.parent.in_menu and not page.is_primary %}
+ </li></ul>
+ {% endif %}
+ {% endif %}
+
+ {% if page.is_primary %}
+ {% if page.in_menu %}
+ </ul>
+ {% endif %}
+ {% if forloop.last %}
+ </div>
+ {% endif %}
+ {% endif %}
+
+{% endfor %}
+
+{% endif %}
+{% endspaceless %}
--- /dev/null
+{% load i18n pages_tags %}
+
+{% spaceless %}
+{% if page_branch_in_menu %}
+<ul class="footer-tree-menu-level-{{ branch_level }}">
+ {% for page in page_branch %}
+
+ {% if not has_home and page.is_primary and forloop.first %}
+ <li class="first{% if on_home %} active{% endif %}"
+ id="footer-tree-menu-home">
+ <a href="{% url "home" %}">{% trans "Home" %}</a>
+ </li>
+ {% endif %}
+
+ {% if page.in_menu %}
+ <li class="{% if page.is_current_or_ascendant %}active{% endif %}
+ {% if not top_level and forloop.first %} first{% endif %}
+ {% if forloop.last %} last{% endif %}"
+ id="footer-tree-menu-{{ page.html_id }}">
+ <a href="{{ page.get_absolute_url }}">{{ page.title }}</a>
+ {# remove this if tag to always show all nav items #}
+ {% if page.is_current_or_ascendant and page.has_children_in_menu %}
+ {% page_menu page %}
+ {% endif %}
+ </li>
+ {% endif %}
+
+ {% endfor %}
+</ul>
+{% endif %}
+{% endspaceless %}
--- /dev/null
+{% load i18n pages_tags %}
+
+{% spaceless %}
+{% if page_branch %}
+{% for page in page_branch %}
+
+ {% if not has_home and page.is_primary and forloop.first %}
+ <ul class="mobile-menu">
+ <li><a class="home" href="{% url "home" %}"
+ id="tree-menu-home">{% trans "Home" %}</a></li>
+ {% endif %}
+
+ {% if page.is_current_or_ascendant and not page.is_current_child %}
+ {% if page.has_children_in_menu %}{% page_menu page %}{% endif %}
+ {% endif %}
+
+ {% if page.is_current_child %}
+ <li class="
+ {% if forloop.first %} first{% endif %}
+ {% if forloop.last %} last{% endif %}"
+ id="mobile-menu-{{ page.html_id }}">
+ <a href="{{ page.get_absolute_url }}">{{ page.title }}</a>
+ </li>
+ {% endif %}
+
+ {% if page.is_primary and forloop.last %}
+ </ul>
+ {% endif %}
+
+{% endfor %}
+{% endif %}
+{% endspaceless %}
--- /dev/null
+{% load pages_tags i18n %}
+
+{% spaceless %}
+<ul id="primary-menu" class="nav pull-right">
+ {% for page in page_branch %}
+ {% if not has_home and page.is_primary and forloop.first %}
+ <li id="primary-menu-home" class="first{% if on_home %} active{% endif %}">
+ <a href="{% url "home" %}">{% trans "Home" %}</a>
+ </li>
+ {% endif %}
+ {% if page.in_menu %}
+ <li id="primary-menu-{{ page.html_id }}"
+ class="{% if page.is_current_or_ascendant %}active{% endif %}{% if forloop.last %} last{% endif %}">
+ <a href="{{ page.get_absolute_url }}">{{ page.title }}</a>
+ </li>
+ {% endif %}
+ {% endfor %}
+ <li class="divider-vertical"></li>
+</ul>
+{% endspaceless %}
--- /dev/null
+{% load i18n pages_tags %}
+
+{% spaceless %}
+{% if page_branch_in_menu %}
+<ul class="nav nav-list navlist-menu-level-{{ branch_level }}">
+ {% for page in page_branch %}
+ {% if not has_home and page.is_primary and forloop.first %}
+ <li{% if on_home %} class="active"{% endif %} id="tree-menu-home">
+ <a href="{% url "home" %}">{% trans "Home" %}</a>
+ </li>
+ {% endif %}
+ {% if page.in_menu %}
+ <li class="
+ {% if page.is_current %} active{% endif %}
+ {% if page.is_current_or_ascendant %} active-branch{% endif %}
+ " id="tree-menu-{{ page.html_id }}">
+ <a href="{{ page.get_absolute_url }}">{{ page.title }}</a>
+ {# wrap the next line with 'if page.is_current_or_ascendant' #}
+ {# to only show child pages in the menu for the current page #}
+ {% if page.is_current_or_ascendant %}{% page_menu page %}{% endif %}
+ </li>
+ {% endif %}
+ {% endfor %}
+</ul>
+{% endif %}
+{% endspaceless %}
--- /dev/null
+{% extends "base.html" %}
+{% load mezzanine_tags keyword_tags %}
+
+{% block meta_title %}{{ page.meta_title }}{% endblock %}
+
+{% block meta_keywords %}{% metablock %}
+{% keywords_for page as keywords %}
+{% for keyword in keywords %}
+ {% if not forloop.first %}, {% endif %}
+ {{ keyword }}
+{% endfor %}
+{% endmetablock %}{% endblock %}
+
+{% block meta_description %}{% metablock %}
+{{ page.description }}
+{% endmetablock %}{% endblock %}
+
+{% block title %}
+{% editable page.title %}{{ page.title }}{% endeditable %}
+{% endblock %}
+
+{% block main %}
+{% endblock %}
--- /dev/null
+{% extends "pages/page.html" %}
+
+{% load mezzanine_tags %}
+
+{% block main %}{{ block.super }}
+
+{% editable page.richtextpage.content %}
+{{ page.richtextpage.content|richtext_filters|safe }}
+{% endeditable %}
+
+{% endblock %}
--- /dev/null
+{% extends "base.html" %}
+
+{% load i18n mezzanine_tags %}
+
+{% block meta_title %}{% trans "Search Results" %}{% endblock %}
+{% block title %}{% trans "Search Results" %}{% endblock %}
+{% block extra_head %}
+<meta name="robots" content="noindex">
+{% endblock %}
+
+{% block breadcrumb_menu %}
+<li>
+ <a href="{% url "home" %}">{% trans "Home" %}</a>
+</li>
+<li class="active">{% trans "Search Results" %}</li>
+{% endblock %}
+
+{% block main %}
+
+<p>
+{% if results.paginator.count == 0 %}
+{% blocktrans %}
+No results were found in {{ search_type }} matching your query: {{ query }}
+{% endblocktrans %}
+{% else %}
+{% blocktrans with start=results.start_index end=results.end_index total=results.paginator.count %}
+Showing {{ start }} to {{ end }} of {{ total }} results in {{ search_type }} matching your query: {{ query }}
+{% endblocktrans %}
+{% endif %}
+</p>
+
+<div id="search-results">
+{% for result in results.object_list %}
+{% with result.get_absolute_url as result_url %}
+ <h5>
+ {{ forloop.counter0|add:results.start_index }})
+ {% if result_url %}
+ <a href="{{ result_url }}">{{ result }}</a>
+ {% else %}
+ {{ result }}
+ {% endif %}
+ </h5>
+ {% if result.description != result|stringformat:"s" %}
+ <p>{{ result.description|truncatewords_html:20|safe }}</p>
+ {% endif %}
+ {% if result_url %}
+ <a href="{{ result_url }}">{% trans "read more" %}</a>
+ {% endif %}
+{% endwith %}
+{% endfor %}
+</div>
+
+{% pagination_for results %}
+
+{% endblock %}
--- /dev/null
+{% extends "base.html" %}
--- /dev/null
+{% extends "shop/checkout.html" %}
+{% load staticfiles i18n mezzanine_tags %}
+
+{% block extra_head %}
+{{ block.super }}
+<script src="{% static "cartridge/js/shipping_fields.js" %}"></script>
+{% endblock %}
+
+{% block fields %}
+{% if request.cart.has_items %}
+{% if not request.user.is_authenticated %}
+{% ifinstalled mezzanine.accounts %}
+<p>
+{% url "login" as login_url %}
+{% url "signup" as signup_url %}
+{% with request.path as next %}
+{% blocktrans %}
+If you have an existing account or would like to create one, please
+<a href="{{ login_url }}?next={{ next }}">log in</a> or
+<a href="{{ signup_url }}?next={{ next }}">sign up</a>.
+{% endblocktrans %}
+{% endwith %}
+</p>
+{% endifinstalled %}
+{% endif %}
+
+{% errors_for form %}
+
+<fieldset>
+ <legend>{% trans "Billing Details" %}</legend>
+ {% fields_for form.billing_detail_fields %}
+</fieldset>
+
+<fieldset>
+ <legend>{% trans "Delivery Details" %}</legend>
+ {% fields_for form.same_billing_shipping_field %}
+ <div id="shipping_fields">{% fields_for form.shipping_detail_fields %}</div>
+ {% fields_for form.additional_instructions_field %}
+ {% fields_for form.remember_field %}
+</fieldset>
+
+{% if not settings.SHOP_CHECKOUT_STEPS_SPLIT and settings.SHOP_PAYMENT_STEP_ENABLED %}
+{% include "shop/includes/payment_fields.html" %}
+{% endif %}
+
+{% fields_for form.other_fields %}
+
+{% endif %}
+{% endblock %}
--- /dev/null
+{% extends "shop/base.html" %}
+{% load mezzanine_tags shop_tags i18n %}
+
+{% block meta_title %}{% trans "Your Cart" %}{% endblock %}
+{% block title %}{% trans "Your Cart" %}{% endblock %}
+{% block body_id %}cart{% endblock %}
+
+{% block breadcrumb_menu %}
+{{ block.super }}
+<li>{% trans "Your Cart" %}</li>
+{% endblock %}
+
+{% block main %}
+{% if cart_formset.forms %}
+<form method="post" class="cart-form">
+{% csrf_token %}
+{% if cart_formset.errors %}
+{% for error in cart_formset.errors %}
+{% if error.values.0 %}{{ error.values.0 }}{% endif %}
+{% endfor %}
+{% endif %}
+{{ cart_formset.management_form }}
+<table class="table table-striped">
+ <thead>
+ <tr>
+ <th colspan="2" class="left">{% trans "Item" %}</th>
+ <th>{% trans "Unit Price" %}</th>
+ <th class="center">{% trans "Qty" %}</th>
+ <th>{% trans "Price" %}</th>
+ <th class="center">{% trans "Remove?" %}</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for form in cart_formset.forms %}
+ {% with form.instance as item %}
+ <tr>
+ <td width="30">
+ {{ form.id }}
+ {% if item.image %}
+ <a href="{{ item.get_absolute_url }}">
+ <img alt="{{ item.description }}" src="{{ MEDIA_URL }}{% thumbnail item.image 30 30 %}">
+ </a>
+ {% endif %}
+ </td>
+ <td class="left">
+ <a href="{{ item.get_absolute_url }}">{{ item.description }}</a>
+ </td>
+ <td>{{ item.unit_price|currency }}</td>
+ <td class="quantity">{{ form.quantity }}</td>
+ <td>{{ item.total_price|currency }}</td>
+ <td class="center">{{ form.DELETE }}</td>
+ </tr>
+ {% endwith %}
+ {% endfor %}
+ <tr>
+ <td colspan="5">{% order_totals %}</td>
+ <td> </td>
+ </tr>
+ </tbody>
+</table>
+
+<div class="form-actions">
+ <a href="{% url "shop_checkout" %}" class="btn btn-primary btn-lg pull-right">
+ {% if request.session.order.step %}{% trans "Return to Checkout" %}{% else %}{% trans "Go to Checkout" %}{% endif %}
+ </a>
+ <input type="submit" name="update_cart" class="btn btn-default btn-lg pull-left" value="{% trans "Update Cart" %}">
+</div>
+</form>
+
+{% if discount_form %}
+<form method="post" class="discount-form col-md-12 text-right">
+ {% fields_for discount_form %}
+ <input type="submit" class="btn btn-default" value="{% trans "Apply" %}">
+</form>
+{% endif %}
+
+{% if settings.SHOP_USE_UPSELL_PRODUCTS %}
+{% with request.cart.upsell_products as upsell_products %}
+{% if upsell_products %}
+<h2>{% trans "You may also like:" %}</h2>
+<div class="row">
+ {% for product in upsell_products %}
+ <div class="col-xs-6 col-sm-4 col-md-3 product-thumb">
+ <a class="thumbnail" href="{{ product.get_absolute_url }}">
+ {% if product.image %}
+ <img src="{{ MEDIA_URL }}{% thumbnail product.image 90 90 %}">
+ {% endif %}
+ <div class="caption">
+ <h6>{{ product }}</h6>
+ <div class="price-info">
+ {% if product.has_price %}
+ {% if product.on_sale %}
+ <span class="old-price">{{ product.unit_price|currency }}</span>
+ {% trans "On sale:" %}
+ {% endif %}
+ <span class="price">{{ product.price|currency }}</span>
+ {% else %}
+ <span class="coming-soon">{% trans "Coming soon" %}</span>
+ {% endif %}
+ </div>
+ </div>
+ </a>
+ </div>
+ {% endfor %}
+</div>
+{% endif %}
+{% endwith %}
+{% endif %}
+
+{% else %}
+<p>{% trans "Your Cart is empty." %}</p>
+{% endif %}
+{% endblock %}
--- /dev/null
+{% extends "shop/base.html" %}
+{% load shop_tags mezzanine_tags i18n %}
+
+{% block meta_title %}{% trans "Checkout" %} - {{ step_title }}{% endblock %}
+{% block title %}{% trans "Checkout" %} - {% trans "Step" %} {{ step }} {% trans "of" %} {{ steps|length }}{% endblock %}
+{% block body_id %}checkout{% endblock %}
+
+{% block extra_head %}
+<script>
+var _gaq = [['_trackPageview', '{{ request.path }}{{ step_url }}/']];
+$(function() {$('.middle :input:visible:enabled:first').focus();});
+</script>
+{% endblock %}
+
+{% block breadcrumb_menu %}
+{% for step in steps %}
+<li>
+ {% if step.title == step_title %}
+ <strong>{{ step.title }}</strong>
+ {% else %}
+ {{ step.title }}
+ {% endif %}
+</li>
+{% endfor %}
+<li>{% trans "Complete" %}</li>
+{% endblock %}
+
+{% block main %}
+
+{% block before-form %}{% endblock %}
+<div class="row">
+<form method="post" class="col-md-8 checkout-form">
+ {% csrf_token %}
+
+ {% block fields %}{% endblock %}
+
+ {% block nav-buttons %}
+ {% if request.cart.has_items %}
+ <div class="form-actions">
+ <input type="submit" class="btn btn-lg btn-primary pull-right" value="{% trans "Next" %}">
+ {% if not CHECKOUT_STEP_FIRST %}
+ <input type="submit" class="btn btn-lg btn-default pull-left" name="back" value="{% trans "Back" %}">
+ {% endif %}
+ </div>
+ {% else %}
+ <p>{% trans "Your cart is empty." %}</p>
+ <p>{% trans "This may be due to your session timing out after a period of inactivity." %}</p>
+ <p>{% trans "We apologize for the inconvenience." %}</p>
+ <br>
+ <p><a class="btn btn-lg btn-primary" href="{% url "page" "shop" %}">{% trans "Continue Shopping" %}</a></p>
+ {% endif %}
+ {% endblock %}
+
+</form>
+
+{% if request.cart.has_items %}
+<div class="col-md-4">
+ <div class="panel panel-default checkout-panel">
+ <div class="panel-body">
+ <ul class="media-list">
+ {% for item in request.cart %}
+ <li class="media">
+ {% if item.image %}
+ <img class="pull-left" alt="{{ item.description }}" src="{{ MEDIA_URL }}{% thumbnail item.image 30 30 %}">
+ {% endif %}
+ <div class="media-body">
+ {{ item.quantity }} x {{ item.description }}
+ <span class="price">{{ item.total_price|currency }}</span>
+ </div>
+ </li>
+ {% endfor %}
+ </ul>
+ {% order_totals %}
+ <br style="clear:both;">
+ <a class="btn btn-default" href="{% url "shop_cart" %}">{% trans "Edit Cart" %}</a>
+ </div>
+ </div>
+</div>
+{% endif %}
+
+{% block after-form %}{% endblock %}
+</div>
+{% endblock %}
--- /dev/null
+{% extends "shop/base.html" %}
+{% load i18n %}
+
+{% block body_id %}complete{% endblock %}
+
+{% block meta_title %}{% trans "Order Complete" %}{% endblock %}
+
+{% block extra_head %}
+{{ block.super }}
+{% if settings.GOOGLE_ANALYTICS_ID %}
+<script>
+
+var decimal = function(amount) {
+ if (amount.toString().indexOf('.') == -1) {
+ amount += '.00';
+ }
+ return String(amount);
+};
+
+var _gaq = [['_trackPageview'], ['_addTrans',
+ // order ID - required
+ '{{ order.id }}',
+ // affiliation or store name
+ '',
+ // total - required
+ decimal({{ order.item_total }}{% if order.discount_total %} - {{ order.discount_total }}{% endif %}),
+ // tax
+ decimal({% if order.tax_total %}{{ order.tax_total }}{% else %}0{% endif %}),
+ // shipping
+ decimal({{ order.shipping_total }}),
+ // city
+ '{{ order.billing_detail_city|escapejs }}',
+ // state or province
+ '{{ order.billing_detail_state|escapejs }}',
+ // country
+ '{{ order.billing_detail_country|escapejs }}'
+]];
+
+{% for item in items %}
+_gaq.push(['_addItem',
+ // order ID - required
+ '{{ order.id }}',
+ // SKU/code - required
+ '{{ item.sku }}',
+ // product name
+ '{{ item.name|escapejs }}',
+ // category or variation
+ '{{ item.description|escapejs }}',
+ // unit price - required
+ decimal({{ item.unit_price }}),
+ // quantity - required
+ '{{ item.quantity }}'
+]);
+{% endfor %}
+
+// submits transaction to the Analytics servers
+_gaq.push(['_trackTrans']);
+
+</script>
+{% endif %}
+{% endblock %}
+
+{% block title %}{% trans "Order Complete" %}{% endblock %}
+
+{% block breadcrumb_menu %}
+{% for step in steps %}
+<li>{{ step.title }}</li>
+{% endfor %}
+<li><strong>{% trans "Complete" %}</strong></li>
+{% endblock %}
+
+
+{% block main %}
+<p>{% trans "Thank you for shopping with us, your order is complete." %}</p>
+<p>{% trans "We've sent you a receipt via email." %}</p>
+<p>{% trans "You can also view your invoice using one of the links below." %}</p>
+<br>
+<form class="order-complete-form" method="post" action="{% url "shop_invoice_resend" order.id %}?next={{ request.path }}">
+ {% csrf_token %}
+ {% if has_pdf %}
+ <a class="btn btn-primary" href="{% url "shop_invoice" order.id %}?format=pdf">{% trans "Download PDF invoice" %}</a>
+ {% endif %}
+ <a class="btn btn-default" target="_blank" href="{% url "shop_invoice" order.id %}">{% trans "View invoice in your browser" %}</a>
+ <input type="submit" class="btn btn-default" value="{% trans "Re-send order email" %}">
+</form>
+{% endblock %}
--- /dev/null
+{% extends "shop/checkout.html" %}
+{% load i18n shop_tags %}
+
+{% block fields %}
+{% if request.cart.has_items %}
+
+<div class="confirmation col-md-6">
+ <div class="panel panel-default">
+ <div class="panel-body">
+ <h3>{% trans "Billing Details" %}</h3>
+ <ul class="list-unstyled">
+
+ {% for field, value in form.billing_detail_fields.values %}
+ <li><label>{{ field }}:</label> {{ value }}</li>
+ {% endfor %}
+
+ </ul>
+ </div>
+ </div>
+</div>
+
+<div class="confirmation col-md-6">
+ <div class="panel panel-default">
+ <div class="panel-body">
+ <h3>{% trans "Shipping Details" %}</h3>
+ <ul class="list-unstyled">
+
+ {% for field, value in form.shipping_detail_fields.values %}
+ <li><label>{{ field }}:</label> {{ value }}</li>
+ {% endfor %}
+
+ {% for field, value in form.additional_instructions_field.values %}
+ <li><label>{{ field }}:</label> {{ value }}</li>
+ {% endfor %}
+
+ </ul>
+ </div>
+ </div>
+</div>
+{% if settings.SHOP_PAYMENT_STEP_ENABLED %}
+{% comment %}
+<br style="clear:both;">
+<div class="confirmation col-md-6">
+ <div class="panel panel-default">
+ <div class="panel-body">
+ <h3>{% trans "Payment Details" %}</h3>
+ <ul class="list-unstyled">
+
+ {% for field, value in form.card_name_field.values %}
+ <li><label>{{ field }}:</label> {{ value }}</li>
+ {% endfor %}
+
+ {% for field, value in form.card_type_field.values %}
+ <li><label>{{ field }}:</label> {{ value }}</li>
+ {% endfor %}
+
+ <li>
+ {% with form.card_expiry_fields.values as expiry_fields %}
+ {% with expiry_fields.next as month_field %}
+ <label>{{ month_field.0 }}:</label> {{ month_field.1 }}/{{ expiry_fields.next.1 }}
+ {% endwith %}
+ {% endwith %}
+ </li>
+
+ {% for field, value in form.card_fields.values %}
+ <li><label>{{ field }}:</label> {{ value }}</li>
+ {% endfor %}
+
+ </ul>
+ </div>
+ </div>
+</div>
+{% endcomment %}
+{% endif %}
+<br style="clear:both;">
+
+{% for field in form %}{{ field }}{% endfor %}
+
+{% endif %}
+{% endblock %}
--- /dev/null
+{% load shop_tags i18n %}
+
+<h1>{{ settings.SITE_TITLE }}</h1>
+
+<table width="100%" border="0">
+ <tr>
+ <td>{% trans "Order ID:" %} {{ order.id }}</td>
+ <td align="right">{{ order.time }}</td>
+ </tr>
+</table>
+
+<h2>{% trans "Your Details" %}</h2>
+<table width="100%" border="1" cellspacing="0" cellpadding="10">
+<tr>
+ <th align="left" width="50%">{% trans "Billing Details" %}</th>
+ <th align="left" width="50%">{% trans "Shipping Details" %}</th>
+</tr>
+<tr>
+ <td valign="top">
+ <table border="0">
+ {% for field, value in order_billing_detail_fields %}
+ <tr><td>{{ field }}: </td><td>{{ value }}</td></tr>
+ {% endfor %}
+ </table>
+ </td>
+ <td valign="top">
+ <table border="0">
+ {% for field, value in order_shipping_detail_fields %}
+ <tr><td>{{ field }}: </td><td>{{ value }}</td></tr>
+ {% endfor %}
+ </table>
+ </td>
+</tr>
+</table>
+
+<h2>{% trans "Items Ordered" %}</h2>
+<table width="100%" border="1" cellspacing="0" cellpadding="10">
+ <tr>
+ <th align="left">{% trans "Item" %}</th>
+ <th align="right">{% trans "Unit Price" %}</th>
+ <th align="right">{% trans "Qty" %}</th>
+ <th align="right">{% trans "Price" %}</th>
+ </tr>
+ {% for item in order.items.all %}
+ <tr>
+ <td>{{ item.description }}</td>
+ <td align="right" valign="top">{{ item.unit_price|currency }}</td>
+ <td align="right" valign="top">{{ item.quantity }}</td>
+ <td align="right" valign="top">{{ item.total_price|currency }}</td>
+ </tr>
+ {% endfor %}
+ <tr>
+ <td colspan="4" align="right">{% order_totals %}</td>
+ </tr>
+</table>
--- /dev/null
+{% load shop_tags i18n %}
+
+<h1 align="right">{{ settings.SITE_TITLE }}</h1>
+
+<table width="100%" border="0">
+ <tr>
+ <td align="left">{{ order.time }}</td>
+ <td align="right">{% trans "Order ID:" %} {{ order.id }}</td>
+ </tr>
+</table>
+
+<h2 align="right">{% trans "Your Details" %}</h2>
+<table width="100%" border="1" cellspacing="0" cellpadding="10">
+<tr>
+ <th align="right" width="50%">{% trans "Billing Details" %}</th>
+ <th align="right" width="50%">{% trans "Shipping Details" %}</th>
+</tr>
+<tr>
+ <td valign="top" align="right">
+ <table border="0">
+ {% for field, value in order_billing_detail_fields %}
+ <tr><td>{{ value }}</td><td> : {{ field }}</td></tr>
+ {% endfor %}
+ </table>
+ </td>
+ <td valign="top" align="right">
+ <table border="0" align="right">
+ {% for field, value in order_shipping_detail_fields %}
+ <tr><td>{{ value }}</td><td> : {{ field }}</td></tr>
+ {% endfor %}
+ </table>
+ </td>
+</tr>
+</table>
+
+<h2 align="right">{% trans "Items Ordered" %}</h2>
+<table width="100%" border="1" cellspacing="0" cellpadding="10">
+ <tr>
+
+
+
+ <th align="left">{% trans "Price" %}</th>
+ <th align="left">{% trans "Qty" %}</th>
+ <th align="left">{% trans "Unit Price" %}</th>
+ <th align="right">{% trans "Item" %}</th>
+ </tr>
+ {% for item in order.items.all %}
+ <tr>
+ <td align="left" valign="top">{{ item.total_price|currency }}</td>
+ <td align="left" valign="top">{{ item.quantity }}</td>
+ <td align="left" valign="top">{{ item.unit_price|currency }}</td>
+ <td align="right">{{ item.description }}</td>
+
+
+
+ </tr>
+ {% endfor %}
+ <tr>
+ <td colspan="4" align="left">{% order_totals %}</td>
+ </tr>
+</table>
--- /dev/null
+{% load shop_tags i18n %}
+<div class="order-totals">
+ {% if discount_total or shipping_total %}
+ <div><label>{% trans "Sub total" %}:</label> <span>{{ item_total|currency }}</span></div>
+ {% endif %}
+ {% if discount_total %}
+ <div>
+ <label>
+ {% if discount_type %}
+ {{ discount_type }}:
+ {% else %}
+ {% trans "Discount" %}:
+ {% endif %}
+ </label> <span>{{ discount_total|currency }}</span>
+ </div>
+ {% endif %}
+ {% if shipping_type or shipping_total %}
+ <div>
+ <label>
+ {% if shipping_type %}
+ {{ shipping_type }}:
+ {% else %}
+ {% trans "Shipping" %}:
+ {% endif %}
+ </label> <span>{{ shipping_total|currency }}</span>
+ </div>
+ {% endif %}
+ {% if tax_total %}
+ <div>
+ <label>
+ {% if tax_type %}
+ {{ tax_type }}:
+ {% else %}
+ {% trans "Tax" %}:
+ {% endif %}
+ </label> <span>{{ tax_total|currency }}</span>
+ </div>
+ {% endif %}
+ <div class="total"><label>{% trans "Total" %}:</label> <span>{{ order_total|currency }}</span></div>
+</div>
--- /dev/null
+{% load shop_tags i18n %}{% if discount_total or shipping_total %}
+{% trans "Sub total" %}: {{ item_total|currency }}
+{% endif %}{% if discount_total %}
+{% if discount_type %}{{ discount_type }}{% else %}{% trans "Discount" %}{% endif %}: {{ discount_total|currency }}
+{% endif %}{% if shipping_type or shipping_total %}
+{% if shipping_type %}{{ shipping_type }}{% else %}{% trans "Shipping" %}{% endif %}: {{ shipping_total|currency }}
+{% endif %} {% if tax_total %}
+{% if tax_type %}{{ tax_type }}{% else %}{% trans "Tax" %}{% endif %}: {{ tax_total|currency }}
+{% endif %}{% trans "Total" %}: {{ order_total|currency }}
+
+
--- /dev/null
+{% load i18n mezzanine_tags multipayment_forms %}
+
+{% if PRIMARY_PAYMENT_PROCESSOR_IN_USE %}
+ <fieldset>
+ <legend>{% trans "Payment Details" %}</legend>
+ {% fields_for form.card_name_field %}
+ {% fields_for form.card_type_field %}
+ {% with form.card_expiry_fields as card_expiry_fields %}
+ <div class="control-group card-expiry-fields{% if card_expiry_fields.errors.card_expiry_year %} error{% endif %}">
+ <label>{% trans "Card Expiry" %}</label>
+ {% fields_for card_expiry_fields %}
+ </div>
+ {% endwith %}
+ {% fields_for form.card_fields %}
+ </fieldset>
+{% endif %}
--- /dev/null
+{% load staticfiles mezzanine_tags shop_tags records_tags rating_tags i18n %}
+
+<ul id="variations" class="list-unstyled">
+ {% for variation in variations %}
+ <li id="variation-{{ variation.sku }}"
+ {% if not variation.default %}style="display:none;"{% endif %}>
+ {% if variation.has_price %}
+ {% if variation.on_sale %}
+ <span class="old-price">{{ variation.unit_price|currency }}</span>
+ {% trans "On sale:" %}
+ {% endif %}
+ <span class="price">{% trans "Price" %}: {{ variation.price|currency }}</span>
+ {% else %}
+ {% if has_available_variations %}
+ <span class="error-msg">
+ {% trans "The selected options are currently unavailable." %}
+ </span>
+ {% endif %}
+ {% endif %}
+ </li>
+ {% endfor %}
+</ul>
--- /dev/null
+{% load i18n shop_tags mezzanine_tags %}
+{% spaceless %}
+<a href="{% url "shop_cart" %}">
+<span class="glyphicon glyphicon-shopping-cart"></span>
+{% blocktrans count request.cart.total_quantity as cart_quantity %}1 item{% plural %}{{ cart_quantity }} items{% endblocktrans %}
+{% trans "in cart" %}:
+{{ request.cart.total_price|currency }}</a><br>
+{% if request.cart.total_quantity != 0 %}
+<a href="{% url "shop_checkout" %}" class="btn btn-primary">
+ {% if request.session.order.step %}{% trans "Return to Checkout" %}{% else %}{% trans "Go to Checkout" %}{% endif %}
+</a><br>
+{% endif %}
+{% if settings.SHOP_USE_WISHLIST %}
+<a href="{% url "shop_wishlist" %}" class="btn-wishlist">
+<span class="glyphicon glyphicon-star"></span>
+{% blocktrans count request.wishlist|length as wishlist_count %}Wishlist contains 1 item{% plural %} Wishlist contains {{ wishlist_count }} items{% endblocktrans %}</a>
+{% endif %}
+{% endspaceless %}
--- /dev/null
+{% load i18n shop_tags mezzanine_tags %}
+{% spaceless %}
+<a href="{% url "shop_cart" %}">
+<span class="glyphicon glyphicon-shopping-cart"></span>
+{% blocktrans count request.cart.total_quantity as cart_quantity %}1 item{% plural %}{{ cart_quantity }} items{% endblocktrans %}
+{% trans "in cart" %}:
+{{ request.cart.total_price|currency }}</a><br>
+{% if request.cart.total_quantity != 0 %}
+<a href="{% url "shop_checkout" %}" class="btn btn-primary">
+ {% if request.session.order.step %}{% trans "Return to Checkout" %}{% else %}{% trans "Go to Checkout" %}{% endif %}
+</a><br>
+{% endif %}
+{% if settings.SHOP_USE_WISHLIST %}
+<a href="{% url "shop_wishlist" %}" class="btn-wishlist">
+<span class="glyphicon glyphicon-star"></span>
+{% blocktrans count request.wishlist|length as wishlist_count %}Wishlist contains 1 item{% plural %} Wishlist contains {{ wishlist_count }} items{% endblocktrans %}</a>
+{% endif %}
+{% endspaceless %}
--- /dev/null
+{% extends "shop/base.html" %}
+{% load mezzanine_tags shop_tags i18n %}
+
+{% block meta_title %}{% trans "Order History" %}{% endblock %}
+{% block title %}{% trans "Order History" %}{% endblock %}
+
+{% block breadcrumb_menu %}
+{{ block.super }}
+<li>{% trans "Order History" %}</li>
+{% endblock %}
+
+{% block main %}
+
+{% if orders %}
+
+<table class="table table-striped order-history">
+ <thead>
+ <th class="left">ID</th>
+ <th class="left">{% trans "Date" %}</th>
+ <th class="right">{% trans "Qty" %}</th>
+ <th class="right">{% trans "Paid" %}</th>
+ <th> </th>
+ </thead>
+ <tbody>
+ {% for order in orders.object_list %}
+ <tr>
+ <td class="left">{{ order.id }}</td>
+ <td class="left">{{ order.time|date:"SHORT_DATE_FORMAT" }}</td>
+ <td class="right">{{ order.quantity_total }}</td>
+ <td class="right">{{ order.total|currency }}</td>
+ <td class="right">
+ <form class="order-history-form" method="post" action="{% url "shop_invoice_resend" order.id %}?next={{ request.path }}">
+ {% csrf_token %}
+ {% if has_pdf %}
+ <a class="btn btn-sm btn-primary" href="{% url "shop_invoice" order.id %}?format=pdf">{% trans "Download PDF" %}</a>
+ {% endif %}
+ <a class="btn btn-sm btn-default" target="_blank" href="{% url "shop_invoice" order.id %}">{% trans "View invoice" %}</a>
+ <input type="submit" class="btn btn-sm btn-default" value="{% trans "Re-send order email" %}">
+ </form>
+ </td>
+ </tr>
+ {% endfor %}
+ </tbody>
+</table>
+{% pagination_for orders %}
+
+{% else %}
+<p>{% trans "You have not ordered anything from us yet." %}</p>
+{% endif %}
+
+{% endblock %}
--- /dev/null
+{% if not LANGUAGE_BIDI %}
+ {% include "shop/includes/order_details.html" %}
+{% else %}
+ {% include "shop/includes/order_details_rtl.html" %}
+{% endif %}
--- /dev/null
+{% extends "shop/order_invoice.html" %}
--- /dev/null
+{% extends "shop/checkout.html" %}
+
+{% load i18n multipayment_forms %}
+
+
+<div class="form-actions clearfix">
+ <div class="form-actions-wrap">
+ <input type="submit" value="Next" class="btn btn-large btn-primary">
+
+ </div>
+ </div>
+
+{% block before-form %}
+ {% if request.cart.has_items %}
+ {% multipayment_forms request form as multipayment_forms %}
+ {% if multipayment_forms %}
+ <div class="form-actions clearfix">
+ <div class="form-actions-wrap">
+ {% for name,form in multipayment_forms %}<form method="post" action="{{ form.action }}">
+ {{ form.as_p }}
+ <input type="submit" value="{% trans name %}" class="btn btn-large">
+ </form>{% endfor %}
+ </div>
+ </div>
+ {% endif %}
+ {% endif %}
+{% endblock %}
+
+{% block fields %}
+ {% if request.cart.has_items %}
+ {% include "shop/includes/payment_fields.html" %}
+ {% if not PRIMARY_PAYMENT_PROCESSOR_IN_USE %}<div style="display:none">{% endif %}
+ {{ form.other_fields.as_ul }}
+ {% if not PRIMARY_PAYMENT_PROCESSOR_IN_USE %}</div>{% endif %}
+ {% endif %}
+{% endblock %}
+
+
+{% block nav-buttons %}
+ {% if request.cart.has_items %}
+ <div class="form-actions clearfix">
+ <div class="form-actions-wrap">
+ {% if PRIMARY_PAYMENT_PROCESSOR_IN_USE %}
+ <input type="submit" class="btn btn-large btn-primary" value="{% trans "Next" %}">
+ {% endif %}
+ {% if not CHECKOUT_STEP_FIRST %}
+ <input type="submit" class="btn btn-large" name="back" value="{% trans "Back" %}">
+ {% endif %}
+ </div>
+ </div>
+ {% else %}
+ {{ block.super }}
+ {% endif %}
+{% endblock %}
\ No newline at end of file
--- /dev/null
+{% extends "shop/base.html" %}
+{% load staticfiles mezzanine_tags shop_tags records_tags rating_tags i18n %}
+
+{% block meta_title %}{{ product.meta_title }}{% endblock %}
+{% block body_id %}category{% endblock %}
+
+{% block meta_keywords %}{% metablock %}
+{% for keyword in product.keywords.all %}
+ {% if not forloop.first %}, {% endif %}
+ {{ keyword }}
+{% endfor %}
+{% endmetablock %}{% endblock %}
+
+{% block meta_description %}{% metablock %}
+{{ product.description }}
+{% endmetablock %}{% endblock %}
+
+{% block extra_css %}
+{{ block.super }}
+<link rel="stylesheet" href="{% static "mezzanine/css/magnific-popup.css" %}">
+{% endblock %}
+
+{% block extra_js %}
+{{ block.super }}
+<script src="{% static "mezzanine/js/magnific-popup.js" %}"></script>
+<script>
+$(document).ready(function() {
+ $('#product-images-large').magnificPopup({
+ delegate: 'a',
+ type: 'image',
+ gallery: {
+ enabled: true,
+ }
+ });
+});
+</script>
+<script>
+$(function () {
+ $('[data-toggle="popover"]').popover()
+})
+</script>
+
+{% endblock %}
+
+{% block extra_head %}
+{{ block.super }}
+<script>var variations = {{ variations_json|safe }};</script>
+<script src="{% static "cartridge/js/product_variations.js" %}"></script>
+{% endblock %}
+
+{% block breadcrumb_menu %}
+{{ block.super }}
+<li>{{ product.title }}</li>
+{% endblock %}
+
+{% block title %}
+<span class="bg-white">
+{% editable product.title %}{{ product.title }}{% endeditable %}
+</span>
+{% endblock %}
+
+{% block main %}
+
+<div class="row" style="padding-top: 1em;">
+
+<div class="col-md-5">
+{% if images %}
+{% spaceless %}
+<ul id="product-images-large" class="list-unstyled list-inline">
+ {% for image in images %}
+ <li id="image-{{ image.id }}-large"{% if not forloop.first %}style="display:none;"{% endif %}>
+ <a class="product-image-large" href="{{ MEDIA_URL }}{{ image.file }}">
+ <img alt="{{ image.description }}" src="{{ MEDIA_URL }}{% thumbnail image.file 0 300 %}" class="img-thumbnail img-responsive col-xs-12">
+ </a>
+ </li>
+ {% endfor %}
+</ul>
+
+{% if images|length != 1 %}
+<ul id="product-images-thumb" class="list-unstyled list-inline">
+ {% for image in images %}
+ <li>
+ <a class="thumbnail" id="image-{{ image.id }}" href="{{ MEDIA_URL }}{{ image.file }}">
+ <img alt="{{ image.description }}" src="{{ MEDIA_URL }}{% thumbnail image.file 75 75 %}">
+ </a>
+ </li>
+ {% endfor %}
+</ul>
+{% endif %}
+
+{% endspaceless %}
+{% endif %}
+</div>
+
+<div class="col-md-6">
+<ul class="description">
+ <li><strong>{{ product.record.artist }}</strong></li>
+ <li><em>{{ product.record.title }}</em></li>
+ <li>
+ {% trans "Label:" %}
+ {{ product.record.label }}
+ </li>
+ <li>
+ {% trans "Country:" %}
+ {{ product.record.country }}
+ </li>
+ {% if product.record.release_year %}
+ <li>
+ {% trans "Release year:" %}
+ {{ product.record.release_year }}
+ </li>
+ {% else %}
+ <li>
+ {% trans "Release decade:" %}
+ {{ product.record.release_decade }}</li>
+ {% endif %}
+ <li>
+ {% trans "Cover:" %}
+ <a class="badge" tabindex="0" role="button" data-toggle="popover" data-trigger="hover focus"
+ title="{{ product.record.cover_condition.name }}"
+ data-content="{{ product.record.cover_condition.description }}">
+ {{ product.record.cover_condition.abbr }}
+ </a>
+ </li>
+ <li>
+ {% trans " Vinyl:" %}
+ <a class="badge" tabindex="0" role="button" data-toggle="popover" data-trigger="hover focus"
+ title="{{ product.record.vinyl_condition.name }}"
+ data-content="{{ product.record.cover_condition.description }}">
+ {{ product.record.vinyl_condition.abbr }}
+ </a>
+ </li>
+ <li>{% include "shop/includes/price.html" %}</li>
+</ul>
+
+<div class="audio">
+{% if product.record.audio_file %}
+<audio controls>
+ <source src="{{ MEDIA_URL }}{{ product.record.audio_file }}">
+</audio>
+</div>
+{% endif %}
+
+</div>
+</div>
+
+<div class="description">
+{% editable product.content %}
+{{ product.content|richtext_filters|safe }}
+{% endeditable %}
+</div>
+
+{% if product.available and has_available_variations %}
+
+{% errors_for add_product_form %}
+
+<form method="post" id="add-cart" class="shop-form">{% csrf_token %}
+ <div style="display: none;">
+ {% fields_for add_product_form %}
+ </div>
+ <div class="form-actions">
+ <input type="submit" class="btn btn-primary btn-lg pull-right" name="add_cart" value="{% trans "Add to cart" %}">
+ {% if settings.SHOP_USE_WISHLIST %}
+ <input type="submit" class="btn btn-default btn-lg pull-left" name="add_wishlist" value="{% trans "Save for later" %}">
+ {% endif %}
+ </div>
+</form>
+{% else %}
+<p class="error-msg">{% trans "This product is currently unavailable." %}</p>
+{% endif %}
+
+{% if settings.SHOP_USE_RATINGS %}
+<div class="panel panel-default rating">
+ <div class="panel-body">{% rating_for product %}</div>
+</div>
+{% endif %}
+
+{% if settings.SHOP_USE_RELATED_PRODUCTS and related_products %}
+<h2>{% trans "Related Products" %}</h2>
+<div class="row related-products">
+ {% for product in related_products %}
+ <div class="col-xs-6 col-sm-4 col-md-3 product-thumb">
+ <a class="thumbnail" href="{{ product.get_absolute_url }}">
+ {% if product.image %}
+ <img src="{{ MEDIA_URL }}{% thumbnail product.image 90 90 %}">
+ {% endif %}
+ <div class="caption">
+ <h6>{{ product }}</h6>
+ <div class="price-info">
+ {% if product.has_price %}
+ {% if product.on_sale %}
+ <span class="old-price">{{ product.unit_price|currency }}</span>
+ {% trans "On sale:" %}
+ {% endif %}
+ <span class="price">{{ product.price|currency }}</span>
+ {% else %}
+ <span class="coming-soon">{% trans "Coming soon" %}</span>
+ {% endif %}
+ </div>
+ </div>
+ </a>
+ </div>
+ {% endfor %}
+</div>
+{% endif %}
+
+{% endblock %}
--- /dev/null
+{% extends "shop/base.html" %}
+{% load mezzanine_tags shop_tags i18n %}
+
+{% block meta_title %}{% trans "Your Wishlist" %}{% endblock %}
+{% block title %}{% trans "Your Wishlist" %}{% endblock %}
+
+{% block breadcrumb_menu %}
+{{ block.super }}
+<li>{% trans "Your Wishlist" %}</li>
+{% endblock %}
+
+{% block main %}
+{% if error %}{{ error }}{% endif %}
+{% if request.wishlist %}
+<table class="table table-striped wishlist">
+ {% for item in wishlist_items %}
+ <tr>
+ <td width="30">
+ {% if item.image %}
+ <a href="{{ item.get_absolute_url }}"><img alt="{{ item }}" src="{{ MEDIA_URL }}{% thumbnail item.image.file 30 30 %}"></a>
+ {% else %}
+
+ {% endif %}
+ </td>
+ <td>
+ <a href="{{ item.get_absolute_url }}">{{ item }}</a>
+ </td>
+ <td class="wishlist-actions">
+ <form method="post">
+ {{ item.unit_price|currency }}
+ {% csrf_token %}
+ <input type="hidden" name="sku" value="{{ item.sku }}">
+ <input type="hidden" name="quantity" value="1">
+ <input type="submit" class="btn btn-sm btn-primary" name="add_cart" value="{% trans "Buy" %}">
+ <input type="submit" class="btn btn-sm btn-default" name="remove_wishlist" value="{% trans "Remove" %}">
+ </form>
+ </td>
+ </tr>
+ {% endfor %}
+</table>
+{% else %}
+<p>{% trans "Your wishlist is empty." %}</p>
+<br>
+<p><a class="btn btn-large btn-primary" href="{% url "page" "shop" %}">{% trans "Continue Shopping" %}</a></p>
+{% endif %}
+{% endblock %}
--- /dev/null
+"""
+WSGI config for diggersdigest project.
+
+It exposes the WSGI callable as a module-level variable named ``application``.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/1.8/howto/deployment/wsgi/
+"""
+
+import os
+
+from django.core.wsgi import get_wsgi_application
+from mezzanine.utils.conf import real_project_name
+
+os.environ.setdefault("DJANGO_SETTINGS_MODULE",
+ "%s.settings" % real_project_name("diggersdigest"))
+
+application = get_wsgi_application()
+++ /dev/null
-# Poll Twitter every 5 minutes
-# Comment-out if you don't use Mezzanine's Twitter app
-*/5 * * * * %(user)s %(manage)s poll_twitter
+++ /dev/null
-from __future__ import unicode_literals
-import multiprocessing
-
-bind = "unix:%(proj_path)s/gunicorn.sock"
-workers = %(num_workers)s
-errorlog = "/home/%(user)s/logs/%(proj_name)s_error.log"
-loglevel = "error"
-proc_name = "%(proj_name)s"
+++ /dev/null
-from __future__ import unicode_literals
-
-SECRET_KEY = "%(secret_key)s"
-NEVERCACHE_KEY = "%(nevercache_key)s"
-ALLOWED_HOSTS = [%(domains_python)s]
-
-DATABASES = {
- "default": {
- # Ends with "postgresql_psycopg2", "mysql", "sqlite3" or "oracle".
- "ENGINE": "django.db.backends.postgresql_psycopg2",
- # DB name or path to database file if using sqlite3.
- "NAME": "%(proj_name)s",
- # Not used with sqlite3.
- "USER": "%(proj_name)s",
- # Not used with sqlite3.
- "PASSWORD": "%(db_pass)s",
- # Set to empty string for localhost. Not used with sqlite3.
- "HOST": "127.0.0.1",
- # Set to empty string for default. Not used with sqlite3.
- "PORT": "",
- }
-}
-
-SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTOCOL", "https")
-
-CACHE_MIDDLEWARE_SECONDS = 60
-
-CACHE_MIDDLEWARE_KEY_PREFIX = "%(proj_name)s"
-
-CACHES = {
- "default": {
- "BACKEND": "django.core.cache.backends.memcached.MemcachedCache",
- "LOCATION": "127.0.0.1:11211",
- }
-}
-
-SESSION_ENGINE = "django.contrib.sessions.backends.cache"
+++ /dev/null
-
-upstream %(proj_name)s {
- server unix:%(proj_path)s/gunicorn.sock fail_timeout=0;
-}
-
-server {
-
- listen 80;
- %(ssl_disabled)s listen 443 ssl;
- server_name %(domains_nginx)s;
- client_max_body_size 10M;
- keepalive_timeout 15;
- error_log /home/%(user)s/logs/%(proj_name)s_error_nginx.log info;
-
- %(ssl_disabled)s ssl_certificate conf/%(proj_name)s.crt;
- %(ssl_disabled)s ssl_certificate_key conf/%(proj_name)s.key;
- %(ssl_disabled)s ssl_session_cache shared:SSL:10m;
- %(ssl_disabled)s ssl_session_timeout 10m;
- %(ssl_disabled)s ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA;
- %(ssl_disabled)s ssl_prefer_server_ciphers on;
-
- # Deny illegal Host headers
- if ($host !~* ^(%(domains_regex)s)$) {
- return 444;
- }
-
- location / {
- proxy_redirect off;
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header X-Forwarded-Protocol $scheme;
- proxy_pass http://%(proj_name)s;
- }
-
- location /static/ {
- root %(proj_path)s;
- access_log off;
- log_not_found off;
- expires 30d;
- }
-
- location /robots.txt {
- root %(proj_path)s/static;
- access_log off;
- log_not_found off;
- }
-
- location /favicon.ico {
- root %(proj_path)s/static/img;
- access_log off;
- log_not_found off;
- }
-
-}
+++ /dev/null
-#!/bin/sh
-
-app='diggersdigest'
-
-# paths
-root_dir='/code'
-app_dir=$root_dir'/'$app
-static=$root_dir'/static/'
-sandbox=$app_dir
-manage=$sandbox'/manage.py'
-wsgi=$sandbox'/wsgi.py'
-
-# waiting for other services
-# sh $app_dir/examples/deploy/wait.sh
-
-# django init
-python $manage migrate --noinput
-python $manage collectstatic --noinput
-
-# static files auto update
-#watchmedo shell-command --patterns="*.js;*.css" --recursive \
-# --command='python '$manage' collectstatic --noinput' $static &
-
-# app start
-#uwsgi --socket :8000 --wsgi-file $wsgi --chdir $sandbox --master --processes 4 --threads 2 --py-autoreload 3
-
-python $manage runserver 0.0.0.0:8000
+++ /dev/null
-[program:gunicorn_%(proj_name)s]
-command=%(venv_path)s/bin/gunicorn -c gunicorn.conf.py -p gunicorn.pid %(proj_app)s.wsgi:application
-directory=%(proj_path)s
-user=%(user)s
-autostart=true
-stdout_logfile = /home/%(user)s/logs/%(proj_name)s_supervisor
-autorestart=true
-redirect_stderr=true
-environment=LANG="%(locale)s",LC_ALL="%(locale)s",LC_LANG="%(locale)s"
+++ /dev/null
-
-DEBUG = True
-
-# Make these unique, and don't share it with anybody.
-SECRET_KEY = "+3b01&_6_m@@yb4f06$s0zno8vkybh81nbuj_q(xzk+xeih1+s"
-NEVERCACHE_KEY = "l11tr%#!uc@+%$51(&+%=&z6h9yrw42(jpcj$3_&6evtu6hl%z"
-
-DATABASES = {
- 'default': {
- 'ENGINE': 'django.db.backends.mysql',
- 'NAME': 'diggersdigest',
- 'USER': 'digger',
- 'PASSWORD': 'admin',
- 'HOST': 'db',
- 'PORT': 3306,
- }
-}
-
-# EXTENSIONS AND FORMATS
-# Allowed Extensions for File Upload. Lower case is important.
-FILEBROWSER_EXTENSIONS = {
- 'Folder': [''],
- 'Image': ['.jpg', '.jpeg', '.gif', '.png', '.tif', '.tiff'],
- 'Document': ['.pdf', '.doc', '.rtf', '.txt', '.xls', '.csv', '.docx'],
- 'Video': ['.mov', '.wmv', '.mpeg', '.mpg', '.avi', '.rm'],
- 'Audio': ['.mp3', '.mp4', '.wav', '.aiff', '.midi', '.m4p']
- }
-# Define different formats for allowed selections.
-# This has to be a subset of EXTENSIONS.
-# e.g., add ?type=image to the browse-URL ...
-FILEBROWSER_SELECT_FORMATS = {
- 'File': ['Folder', 'Document'],
- 'Image': ['Image'],
- 'Media': ['Video', 'Audio'],
- 'Audio': ['Audio'],
- 'Document': ['Document'],
- # for TinyMCE we can also define lower-case items
- 'image': ['Image'],
- 'file': ['Folder', 'Image', 'Document'],
- 'media': ['Video', 'Audio'],
- 'audio': ['Audio'],
-}
-
-###################
-# DEPLOY SETTINGS #
-###################
-
-# Domains for public site
-# ALLOWED_HOSTS = [""]
-
-# These settings are used by the default fabfile.py provided.
-# Check fabfile.py for defaults.
-
-# FABRIC = {
-# "DEPLOY_TOOL": "rsync", # Deploy with "git", "hg", or "rsync"
-# "SSH_USER": "", # VPS SSH username
-# "HOSTS": [""], # The IP address of your VPS
-# "DOMAINS": ALLOWED_HOSTS, # Edit domains in ALLOWED_HOSTS
-# "REQUIREMENTS_PATH": "requirements.txt", # Project's pip requirements
-# "LOCALE": "en_US.UTF-8", # Should end with ".UTF-8"
-# "DB_PASS": "", # Live database password
-# "ADMIN_PASS": "", # Live admin user password
-# "SECRET_KEY": SECRET_KEY,
-# "NEVERCACHE_KEY": NEVERCACHE_KEY,
-# }
+++ /dev/null
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
-import mezzanine.core.fields
-import mezzanine.utils.models
-from django.conf import settings
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('sites', '0001_initial'),
- migrations.swappable_dependency(settings.AUTH_USER_MODEL),
- ]
-
- operations = [
- migrations.CreateModel(
- name='BlogCategory',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('title', models.CharField(max_length=500, verbose_name='Title')),
- ('slug', models.CharField(help_text='Leave blank to have the URL auto-generated from the title.', max_length=2000, null=True, verbose_name='URL', blank=True)),
- ('site', models.ForeignKey(editable=False, to='sites.Site')),
- ],
- options={
- 'ordering': ('title',),
- 'verbose_name': 'Blog Category',
- 'verbose_name_plural': 'Blog Categories',
- },
- bases=(models.Model,),
- ),
- migrations.CreateModel(
- name='BlogPost',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('comments_count', models.IntegerField(default=0, editable=False)),
- ('keywords_string', models.CharField(max_length=500, editable=False, blank=True)),
- ('rating_count', models.IntegerField(default=0, editable=False)),
- ('rating_sum', models.IntegerField(default=0, editable=False)),
- ('rating_average', models.FloatField(default=0, editable=False)),
- ('title', models.CharField(max_length=500, verbose_name='Title')),
- ('slug', models.CharField(help_text='Leave blank to have the URL auto-generated from the title.', max_length=2000, null=True, verbose_name='URL', blank=True)),
- ('_meta_title', models.CharField(help_text='Optional title to be used in the HTML title tag. If left blank, the main title field will be used.', max_length=500, null=True, verbose_name='Title', blank=True)),
- ('description', models.TextField(verbose_name='Description', blank=True)),
- ('gen_description', models.BooleanField(default=True, help_text='If checked, the description will be automatically generated from content. Uncheck if you want to manually set a custom description.', verbose_name='Generate description')),
- ('created', models.DateTimeField(null=True, editable=False)),
- ('updated', models.DateTimeField(null=True, editable=False)),
- ('status', models.IntegerField(default=2, help_text='With Draft chosen, will only be shown for admin users on the site.', verbose_name='Status', choices=[(1, 'Draft'), (2, 'Published')])),
- ('publish_date', models.DateTimeField(help_text="With Published chosen, won't be shown until this time", null=True, verbose_name='Published from', blank=True)),
- ('expiry_date', models.DateTimeField(help_text="With Published chosen, won't be shown after this time", null=True, verbose_name='Expires on', blank=True)),
- ('short_url', models.URLField(null=True, blank=True)),
- ('in_sitemap', models.BooleanField(default=True, verbose_name='Show in sitemap')),
- ('content', mezzanine.core.fields.RichTextField(verbose_name='Content')),
- ('allow_comments', models.BooleanField(default=True, verbose_name='Allow comments')),
- ('featured_image', mezzanine.core.fields.FileField(max_length=255, null=True, verbose_name='Featured Image', blank=True)),
- ('categories', models.ManyToManyField(related_name='blogposts', verbose_name='Categories', to='blog.BlogCategory', blank=True)),
- ('related_posts', models.ManyToManyField(related_name='related_posts_rel_+', verbose_name='Related posts', to='blog.BlogPost', blank=True)),
- ('site', models.ForeignKey(editable=False, to='sites.Site')),
- ('user', models.ForeignKey(related_name='blogposts', verbose_name='Author', to=settings.AUTH_USER_MODEL)),
- ],
- options={
- 'ordering': ('-publish_date',),
- 'verbose_name': 'Blog post',
- 'verbose_name_plural': 'Blog posts',
- },
- bases=(models.Model, mezzanine.utils.models.AdminThumbMixin),
- ),
- ]
+++ /dev/null
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('blog', '0001_initial'),
- ]
-
- operations = [
- migrations.AlterField(
- model_name='blogpost',
- name='publish_date',
- field=models.DateTimeField(help_text="With Published chosen, won't be shown until this time", null=True, verbose_name='Published from', db_index=True, blank=True),
- ),
- ]
+++ /dev/null
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('shop', '0003_auto_20150906_1911'),
- ('blog', '0002_auto_20150527_1555'),
- ]
-
- operations = [
- migrations.AddField(
- model_name='blogpost',
- name='related_products',
- field=models.ManyToManyField(to='shop.Product', verbose_name=b'Related products', blank=True),
- ),
- ]
+++ /dev/null
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
-from decimal import Decimal
-import mezzanine.utils.models
-import django.db.models.deletion
-import mezzanine.core.fields
-import cartridge.shop.fields
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('pages', '0003_auto_20150527_1555'),
- ('sites', '0001_initial'),
- ]
-
- operations = [
- migrations.CreateModel(
- name='Cart',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('last_updated', models.DateTimeField(null=True, verbose_name='Last updated')),
- ],
- ),
- migrations.CreateModel(
- name='CartItem',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('sku', cartridge.shop.fields.SKUField(max_length=20, verbose_name='SKU')),
- ('description', models.CharField(max_length=2000, verbose_name='Description')),
- ('quantity', models.IntegerField(default=0, verbose_name='Quantity')),
- ('unit_price', cartridge.shop.fields.MoneyField(decimal_places=2, default=Decimal('0'), max_digits=10, blank=True, null=True, verbose_name='Unit price')),
- ('total_price', cartridge.shop.fields.MoneyField(decimal_places=2, default=Decimal('0'), max_digits=10, blank=True, null=True, verbose_name='Total price')),
- ('url', models.CharField(max_length=2000)),
- ('image', models.CharField(max_length=200, null=True)),
- ('cart', models.ForeignKey(related_name='items', to='shop.Cart')),
- ],
- options={
- 'abstract': False,
- },
- ),
- migrations.CreateModel(
- name='Category',
- fields=[
- ('page_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='pages.Page')),
- ('content', mezzanine.core.fields.RichTextField(verbose_name='Content')),
- ('featured_image', mezzanine.core.fields.FileField(max_length=255, null=True, verbose_name='Featured Image', blank=True)),
- ('price_min', cartridge.shop.fields.MoneyField(null=True, verbose_name='Minimum price', max_digits=10, decimal_places=2, blank=True)),
- ('price_max', cartridge.shop.fields.MoneyField(null=True, verbose_name='Maximum price', max_digits=10, decimal_places=2, blank=True)),
- ('combined', models.BooleanField(default=True, help_text='If checked, products must match all specified filters, otherwise products can match any specified filter.', verbose_name='Combined')),
- ],
- options={
- 'ordering': ('_order',),
- 'verbose_name': 'Product category',
- 'verbose_name_plural': 'Product categories',
- },
- bases=('pages.page', models.Model),
- ),
- migrations.CreateModel(
- name='DiscountCode',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('title', models.CharField(max_length=100, verbose_name='Title')),
- ('active', models.BooleanField(default=False, verbose_name='Active')),
- ('discount_deduct', cartridge.shop.fields.MoneyField(null=True, verbose_name='Reduce by amount', max_digits=10, decimal_places=2, blank=True)),
- ('discount_percent', cartridge.shop.fields.PercentageField(null=True, verbose_name='Reduce by percent', max_digits=5, decimal_places=2, blank=True)),
- ('discount_exact', cartridge.shop.fields.MoneyField(null=True, verbose_name='Reduce to amount', max_digits=10, decimal_places=2, blank=True)),
- ('valid_from', models.DateTimeField(null=True, verbose_name='Valid from', blank=True)),
- ('valid_to', models.DateTimeField(null=True, verbose_name='Valid to', blank=True)),
- ('code', cartridge.shop.fields.DiscountCodeField(unique=True, max_length=20, verbose_name='Code')),
- ('min_purchase', cartridge.shop.fields.MoneyField(null=True, verbose_name='Minimum total purchase', max_digits=10, decimal_places=2, blank=True)),
- ('free_shipping', models.BooleanField(default=False, verbose_name='Free shipping')),
- ('uses_remaining', models.IntegerField(help_text='If you wish to limit the number of times a code may be used, set this value. It will be decremented upon each use.', null=True, verbose_name='Uses remaining', blank=True)),
- ('categories', models.ManyToManyField(related_name='discountcode_related', verbose_name='Categories', to='shop.Category', blank=True)),
- ],
- options={
- 'verbose_name': 'Discount code',
- 'verbose_name_plural': 'Discount codes',
- },
- ),
- migrations.CreateModel(
- name='Order',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('billing_detail_first_name', models.CharField(max_length=100, verbose_name='First name')),
- ('billing_detail_last_name', models.CharField(max_length=100, verbose_name='Last name')),
- ('billing_detail_street', models.CharField(max_length=100, verbose_name='Street')),
- ('billing_detail_city', models.CharField(max_length=100, verbose_name='City/Suburb')),
- ('billing_detail_state', models.CharField(max_length=100, verbose_name='State/Region')),
- ('billing_detail_postcode', models.CharField(max_length=10, verbose_name='Zip/Postcode')),
- ('billing_detail_country', models.CharField(max_length=100, verbose_name='Country')),
- ('billing_detail_phone', models.CharField(max_length=20, verbose_name='Phone')),
- ('billing_detail_email', models.EmailField(max_length=254, verbose_name='Email')),
- ('shipping_detail_first_name', models.CharField(max_length=100, verbose_name='First name')),
- ('shipping_detail_last_name', models.CharField(max_length=100, verbose_name='Last name')),
- ('shipping_detail_street', models.CharField(max_length=100, verbose_name='Street')),
- ('shipping_detail_city', models.CharField(max_length=100, verbose_name='City/Suburb')),
- ('shipping_detail_state', models.CharField(max_length=100, verbose_name='State/Region')),
- ('shipping_detail_postcode', models.CharField(max_length=10, verbose_name='Zip/Postcode')),
- ('shipping_detail_country', models.CharField(max_length=100, verbose_name='Country')),
- ('shipping_detail_phone', models.CharField(max_length=20, verbose_name='Phone')),
- ('additional_instructions', models.TextField(verbose_name='Additional instructions', blank=True)),
- ('time', models.DateTimeField(auto_now_add=True, verbose_name='Time', null=True)),
- ('key', models.CharField(max_length=40)),
- ('user_id', models.IntegerField(null=True, blank=True)),
- ('shipping_type', models.CharField(max_length=50, verbose_name='Shipping type', blank=True)),
- ('shipping_total', cartridge.shop.fields.MoneyField(null=True, verbose_name='Shipping total', max_digits=10, decimal_places=2, blank=True)),
- ('tax_type', models.CharField(max_length=50, verbose_name='Tax type', blank=True)),
- ('tax_total', cartridge.shop.fields.MoneyField(null=True, verbose_name='Tax total', max_digits=10, decimal_places=2, blank=True)),
- ('item_total', cartridge.shop.fields.MoneyField(null=True, verbose_name='Item total', max_digits=10, decimal_places=2, blank=True)),
- ('discount_code', cartridge.shop.fields.DiscountCodeField(max_length=20, verbose_name='Discount code', blank=True)),
- ('discount_total', cartridge.shop.fields.MoneyField(null=True, verbose_name='Discount total', max_digits=10, decimal_places=2, blank=True)),
- ('total', cartridge.shop.fields.MoneyField(null=True, verbose_name='Order total', max_digits=10, decimal_places=2, blank=True)),
- ('transaction_id', models.CharField(max_length=255, null=True, verbose_name='Transaction ID', blank=True)),
- ('status', models.IntegerField(default=1, verbose_name='Status', choices=[(1, 'Unprocessed'), (2, 'Processed')])),
- ('site', models.ForeignKey(editable=False, to='sites.Site')),
- ],
- options={
- 'ordering': ('-id',),
- 'verbose_name': 'Order',
- 'verbose_name_plural': 'Orders',
- },
- ),
- migrations.CreateModel(
- name='OrderItem',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('sku', cartridge.shop.fields.SKUField(max_length=20, verbose_name='SKU')),
- ('description', models.CharField(max_length=2000, verbose_name='Description')),
- ('quantity', models.IntegerField(default=0, verbose_name='Quantity')),
- ('unit_price', cartridge.shop.fields.MoneyField(decimal_places=2, default=Decimal('0'), max_digits=10, blank=True, null=True, verbose_name='Unit price')),
- ('total_price', cartridge.shop.fields.MoneyField(decimal_places=2, default=Decimal('0'), max_digits=10, blank=True, null=True, verbose_name='Total price')),
- ('order', models.ForeignKey(related_name='items', to='shop.Order')),
- ],
- options={
- 'abstract': False,
- },
- ),
- migrations.CreateModel(
- name='Product',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('keywords_string', models.CharField(max_length=500, editable=False, blank=True)),
- ('rating_count', models.IntegerField(default=0, editable=False)),
- ('rating_sum', models.IntegerField(default=0, editable=False)),
- ('rating_average', models.FloatField(default=0, editable=False)),
- ('title', models.CharField(max_length=500, verbose_name='Title')),
- ('slug', models.CharField(help_text='Leave blank to have the URL auto-generated from the title.', max_length=2000, null=True, verbose_name='URL', blank=True)),
- ('_meta_title', models.CharField(help_text='Optional title to be used in the HTML title tag. If left blank, the main title field will be used.', max_length=500, null=True, verbose_name='Title', blank=True)),
- ('description', models.TextField(verbose_name='Description', blank=True)),
- ('gen_description', models.BooleanField(default=True, help_text='If checked, the description will be automatically generated from content. Uncheck if you want to manually set a custom description.', verbose_name='Generate description')),
- ('created', models.DateTimeField(null=True, editable=False)),
- ('updated', models.DateTimeField(null=True, editable=False)),
- ('status', models.IntegerField(default=2, help_text='With Draft chosen, will only be shown for admin users on the site.', verbose_name='Status', choices=[(1, 'Draft'), (2, 'Published')])),
- ('publish_date', models.DateTimeField(help_text="With Published chosen, won't be shown until this time", null=True, verbose_name='Published from', db_index=True, blank=True)),
- ('expiry_date', models.DateTimeField(help_text="With Published chosen, won't be shown after this time", null=True, verbose_name='Expires on', blank=True)),
- ('short_url', models.URLField(null=True, blank=True)),
- ('in_sitemap', models.BooleanField(default=True, verbose_name='Show in sitemap')),
- ('content', mezzanine.core.fields.RichTextField(verbose_name='Content')),
- ('unit_price', cartridge.shop.fields.MoneyField(null=True, verbose_name='Unit price', max_digits=10, decimal_places=2, blank=True)),
- ('sale_id', models.IntegerField(null=True)),
- ('sale_price', cartridge.shop.fields.MoneyField(null=True, verbose_name='Sale price', max_digits=10, decimal_places=2, blank=True)),
- ('sale_from', models.DateTimeField(null=True, verbose_name='Sale start', blank=True)),
- ('sale_to', models.DateTimeField(null=True, verbose_name='Sale end', blank=True)),
- ('sku', cartridge.shop.fields.SKUField(max_length=20, unique=True, null=True, verbose_name='SKU', blank=True)),
- ('num_in_stock', models.IntegerField(null=True, verbose_name='Number in stock', blank=True)),
- ('available', models.BooleanField(default=False, verbose_name='Available for purchase')),
- ('image', models.CharField(max_length=100, null=True, verbose_name='Image', blank=True)),
- ('date_added', models.DateTimeField(auto_now_add=True, verbose_name='Date added', null=True)),
- ('categories', models.ManyToManyField(to='shop.Category', verbose_name='Product categories', blank=True)),
- ('related_products', models.ManyToManyField(related_name='related_products_rel_+', verbose_name='Related products', to='shop.Product', blank=True)),
- ('site', models.ForeignKey(editable=False, to='sites.Site')),
- ('upsell_products', models.ManyToManyField(related_name='upsell_products_rel_+', verbose_name='Upsell products', to='shop.Product', blank=True)),
- ],
- options={
- 'verbose_name': 'Product',
- 'verbose_name_plural': 'Products',
- },
- bases=(models.Model, mezzanine.utils.models.AdminThumbMixin),
- ),
- migrations.CreateModel(
- name='ProductAction',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('timestamp', models.IntegerField()),
- ('total_cart', models.IntegerField(default=0)),
- ('total_purchase', models.IntegerField(default=0)),
- ('product', models.ForeignKey(related_name='actions', to='shop.Product')),
- ],
- ),
- migrations.CreateModel(
- name='ProductImage',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('_order', mezzanine.core.fields.OrderField(null=True, verbose_name='Order')),
- ('file', mezzanine.core.fields.FileField(max_length=255, verbose_name='Image')),
- ('description', models.CharField(max_length=100, verbose_name='Description', blank=True)),
- ('product', models.ForeignKey(related_name='images', to='shop.Product')),
- ],
- options={
- 'ordering': ('_order',),
- 'verbose_name': 'Image',
- 'verbose_name_plural': 'Images',
- },
- ),
- migrations.CreateModel(
- name='ProductOption',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('type', models.IntegerField(verbose_name='Type', choices=[(1, 'Cover condition'), (2, 'Vinyl condition')])),
- ('name', cartridge.shop.fields.OptionField(max_length=50, null=True, verbose_name='Name')),
- ],
- options={
- 'verbose_name': 'Product option',
- 'verbose_name_plural': 'Product options',
- },
- ),
- migrations.CreateModel(
- name='ProductVariation',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('unit_price', cartridge.shop.fields.MoneyField(null=True, verbose_name='Unit price', max_digits=10, decimal_places=2, blank=True)),
- ('sale_id', models.IntegerField(null=True)),
- ('sale_price', cartridge.shop.fields.MoneyField(null=True, verbose_name='Sale price', max_digits=10, decimal_places=2, blank=True)),
- ('sale_from', models.DateTimeField(null=True, verbose_name='Sale start', blank=True)),
- ('sale_to', models.DateTimeField(null=True, verbose_name='Sale end', blank=True)),
- ('sku', cartridge.shop.fields.SKUField(max_length=20, unique=True, null=True, verbose_name='SKU', blank=True)),
- ('num_in_stock', models.IntegerField(null=True, verbose_name='Number in stock', blank=True)),
- ('default', models.BooleanField(default=False, verbose_name='Default')),
- ('option1', cartridge.shop.fields.OptionField(max_length=50, null=True, verbose_name='Cover condition')),
- ('option2', cartridge.shop.fields.OptionField(max_length=50, null=True, verbose_name='Vinyl condition')),
- ('image', models.ForeignKey(on_delete=django.db.models.deletion.SET_NULL, verbose_name='Image', blank=True, to='shop.ProductImage', null=True)),
- ('product', models.ForeignKey(related_name='variations', to='shop.Product')),
- ],
- options={
- 'ordering': ('-default',),
- },
- ),
- migrations.CreateModel(
- name='Sale',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('title', models.CharField(max_length=100, verbose_name='Title')),
- ('active', models.BooleanField(default=False, verbose_name='Active')),
- ('discount_deduct', cartridge.shop.fields.MoneyField(null=True, verbose_name='Reduce by amount', max_digits=10, decimal_places=2, blank=True)),
- ('discount_percent', cartridge.shop.fields.PercentageField(null=True, verbose_name='Reduce by percent', max_digits=5, decimal_places=2, blank=True)),
- ('discount_exact', cartridge.shop.fields.MoneyField(null=True, verbose_name='Reduce to amount', max_digits=10, decimal_places=2, blank=True)),
- ('valid_from', models.DateTimeField(null=True, verbose_name='Valid from', blank=True)),
- ('valid_to', models.DateTimeField(null=True, verbose_name='Valid to', blank=True)),
- ('categories', models.ManyToManyField(related_name='sale_related', verbose_name='Categories', to='shop.Category', blank=True)),
- ('products', models.ManyToManyField(to='shop.Product', verbose_name='Products', blank=True)),
- ],
- options={
- 'verbose_name': 'Sale',
- 'verbose_name_plural': 'Sales',
- },
- ),
- migrations.AddField(
- model_name='discountcode',
- name='products',
- field=models.ManyToManyField(to='shop.Product', verbose_name='Products', blank=True),
- ),
- migrations.AddField(
- model_name='category',
- name='options',
- field=models.ManyToManyField(related_name='product_options', verbose_name='Product options', to='shop.ProductOption', blank=True),
- ),
- migrations.AddField(
- model_name='category',
- name='products',
- field=models.ManyToManyField(to='shop.Product', verbose_name='Products', blank=True),
- ),
- migrations.AddField(
- model_name='category',
- name='sale',
- field=models.ForeignKey(verbose_name='Sale', blank=True, to='shop.Sale', null=True),
- ),
- migrations.AlterUniqueTogether(
- name='productaction',
- unique_together=set([('product', 'timestamp')]),
- ),
- ]
+++ /dev/null
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('shop', '0001_initial'),
- ]
-
- operations = [
- migrations.AddField(
- model_name='order',
- name='callback_uuid',
- field=models.CharField(default=0, max_length=36),
- preserve_default=False,
- ),
- ]
+++ /dev/null
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
-import cartridge.shop.fields
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('shop', '0002_order_callback_uuid'),
- ]
-
- operations = [
- migrations.AlterField(
- model_name='productoption',
- name='type',
- field=models.IntegerField(verbose_name='Type', choices=[(1, 'Size'), (2, 'Colour')]),
- ),
- migrations.AlterField(
- model_name='productvariation',
- name='option1',
- field=cartridge.shop.fields.OptionField(max_length=50, null=True, verbose_name='Size'),
- ),
- migrations.AlterField(
- model_name='productvariation',
- name='option2',
- field=cartridge.shop.fields.OptionField(max_length=50, null=True, verbose_name='Colour'),
- ),
- ]
+++ /dev/null
-
-from __future__ import absolute_import, unicode_literals
-import os
-from django.utils.translation import ugettext_lazy as _
-
-
-######################
-# MEZZANINE SETTINGS #
-######################
-
-# The following settings are already defined with default values in
-# the ``defaults.py`` module within each of Mezzanine's apps, but are
-# common enough to be put here, commented out, for conveniently
-# overriding. Please consult the settings documentation for a full list
-# of settings Mezzanine implements:
-# http://mezzanine.jupo.org/docs/configuration.html#default-settings
-
-# Controls the ordering and grouping of the admin menu.
-#
-# ADMIN_MENU_ORDER = (
-# ("Content", ("pages.Page", "blog.BlogPost",
-# "generic.ThreadedComment", (_("Media Library"), "fb_browse"),)),
-# (_("Shop"), ("shop.Product", "shop.ProductOption", "shop.DiscountCode",
-# "shop.Sale", "shop.Order")),
-# ("Site", ("sites.Site", "redirects.Redirect", "conf.Setting")),
-# ("Users", ("auth.User", "auth.Group",)),
-# )
-
-# A three item sequence, each containing a sequence of template tags
-# used to render the admin dashboard.
-#
-# DASHBOARD_TAGS = (
-# ("blog_tags.quick_blog", "mezzanine_tags.app_list"),
-# ("comment_tags.recent_comments",),
-# ("mezzanine_tags.recent_actions",),
-# )
-
-# A sequence of templates used by the ``page_menu`` template tag. Each
-# item in the sequence is a three item sequence, containing a unique ID
-# for the template, a label for the template, and the template path.
-# These templates are then available for selection when editing which
-# menus a page should appear in. Note that if a menu template is used
-# that doesn't appear in this setting, all pages will appear in it.
-
-PAGE_MENU_TEMPLATES = (
- (1, _("Top navigation bar"), "pages/menus/dropdown.html"),
- # (2, _("Left-hand tree"), "pages/menus/tree.html"),
- # (3, _("Footer"), "pages/menus/footer.html"),
-)
-
-# A sequence of fields that will be injected into Mezzanine's (or any
-# library's) models. Each item in the sequence is a four item sequence.
-# The first two items are the dotted path to the model and its field
-# name to be added, and the dotted path to the field class to use for
-# the field. The third and fourth items are a sequence of positional
-# args and a dictionary of keyword args, to use when creating the
-# field instance. When specifying the field class, the path
-# ``django.models.db.`` can be omitted for regular Django model fields.
-#
-
-EXTRA_MODEL_FIELDS = (
- (
- # Dotted path to field.# Dotted path to field.
- "mezzanine.blog.models.BlogPost.related_products",
- # Dotted path to field class.
- "django.db.models.ManyToManyField",
- # Positional args for field class.
- ("shop.Product",),
- # Keyword args for field class.
- {"verbose_name": ("Related products"), "blank": True},
- ),
- # Add the callback_uuid field to orders. This field is helpful for identifying
- # orders being checked out.
- (
- "cartridge.shop.models.Order.callback_uuid",
- "django.db.models.CharField",
- (),
- {"blank" : False, "max_length" : 36},
- ),
- # ...
- # # Example of adding a field to *all* of Mezzanine's content types:
- # (
- # "mezzanine.pages.models.Page.another_field",
- # "IntegerField", # 'django.db.models.' is implied if path is omitted.
- # (_("Another name"),),
- # {"blank": True, "default": 1},
- # ),
- )
-
-# Setting to turn on featured images for blog posts. Defaults to False.
-#
-BLOG_USE_FEATURED_IMAGE = True
-
-# If True, the django-modeltranslation will be added to the
-# INSTALLED_APPS setting.
-USE_MODELTRANSLATION = False
-
-SEARCH_MODEL_CHOICES = ('shop.Product',)
-
-
-######################
-# CARTRIDGE SETTINGS #
-######################
-
-# The following settings are already defined in cartridge.shop.defaults
-# with default values, but are common enough to be put here, commented
-# out, for conveniently overriding. Please consult the settings
-# documentation for a full list of settings Cartridge implements:
-# http://cartridge.jupo.org/configuration.html#default-settings
-
-# Sequence of available credit card types for payment.
-# SHOP_CARD_TYPES = ("Mastercard", "Visa", "Diners", "Amex")
-
-# Setting to turn on featured images for shop categories. Defaults to False.
-# SHOP_CATEGORY_USE_FEATURED_IMAGE = True
-
-# Set an alternative OrderForm class for the checkout process.
-# SHOP_CHECKOUT_FORM_CLASS = 'cartridge.shop.forms.OrderForm'
-
-# If True, the checkout process is split into separate
-# billing/shipping and payment steps.
-# SHOP_CHECKOUT_STEPS_SPLIT = True
-
-# If True, the checkout process has a final confirmation step before
-# completion.
-# SHOP_CHECKOUT_STEPS_CONFIRMATION = True
-
-# Controls the formatting of monetary values accord to the locale
-# module in the python standard library. If an empty string is
-# used, will fall back to the system's locale.
-#SHOP_CURRENCY_LOCALE = ''
-
-# Dotted package path and name of the function that
-# is called on submit of the billing/shipping checkout step. This
-# is where shipping calculation can be performed and set using the
-# function ``cartridge.shop.utils.set_shipping``.
-# SHOP_HANDLER_BILLING_SHIPPING = \
-# "cartridge.shop.checkout.default_billship_handler"
-
-# Dotted package path and name of the function that
-# is called once an order is successful and all of the order
-# object's data has been created. This is where any custom order
-# processing should be implemented.
-# SHOP_HANDLER_ORDER = "cartridge.shop.checkout.default_order_handler"
-
-# Dotted package path and name of the function that
-# is called on submit of the payment checkout step. This is where
-# integration with a payment gateway should be implemented.
-# SHOP_HANDLER_PAYMENT = "cartridge.shop.checkout.default_payment_handler"
-
-# Sequence of value/name pairs for order statuses.
-# SHOP_ORDER_STATUS_CHOICES = (
-# (1, "Unprocessed"),
-# (2, "Processed"),
-# )
-
-# Sequence of value/name pairs for types of product options,
-# eg Size, Colour. NOTE: Increasing the number of these will
-# require database migrations!
-#SHOP_OPTION_TYPE_CHOICES = (
-# (1, "Cover condition"),
-# (2, "Vinyl condition"),
-# )
-
-SHOP_USE_VARIATIONS = False
-
-# Sequence of indexes from the SHOP_OPTION_TYPE_CHOICES setting that
-# control how the options should be ordered in the admin,
-# SHOP_OPTION_ADMIN_ORDER = (1, 2)
-
-SHOP_USE_RATINGS = False
-
-# Add Migration Module path see : https://github.com/stephenmcd/mezzanine/blob/master/docs/model-customization.rst#field-injection-caveats
-MIGRATION_MODULES = {
- "shop": "diggersdigest.migrations.shop",
- "blog": "diggersdigest.migrations.blog"
-}
-
-# USE or EXTEND the custom callback-uuid form
-SHOP_CHECKOUT_FORM_CLASS = 'payments.multipayments.forms.base.CallbackUUIDOrderForm'
-
-PRIMARY_PAYMENT_PROCESSOR_IN_USE = False
-
-SECONDARY_PAYMENT_PROCESSORS = (
- ('paypal', {
- 'name' : 'Pay With Pay-Pal',
- 'form' : 'payments.multipayments.forms.paypal.PaypalSubmissionForm'
- }),
-)
-
-
-# Currency type.
-PAYPAL_CURRENCY = "EUR"
-
-# Business account email. Sandbox emails look like this.
-PAYPAL_BUSINESS = 'pellerin@parisson.com'
-PAYPAL_RECEIVER_EMAIL = PAYPAL_BUSINESS
-
-# Use this to enable https on return URLs. This is strongly recommended! (Except for sandbox)
-PAYPAL_RETURN_WITH_HTTPS = False
-
-# Function that returns args for `reverse`.
-# URL is sent to PayPal as the for returning to a 'complete' landing page.
-PAYPAL_RETURN_URL = lambda cart, uuid, order_form: ('shop_complete', None, None)
-
-# Function that returns args for `reverse`.
-# URL is sent to PayPal as the URL to callback to for PayPal IPN.
-# Set to None if you do not wish to use IPN.
-PAYPAL_IPN_URL = lambda cart, uuid, order_form: ('paypal.standard.ipn.views.ipn', None, {})
-
-
-# URL the secondary-payment-form is submitted to
-# Dev example
-PAYPAL_SUBMIT_URL = 'https://www.sandbox.paypal.com/cgi-bin/webscr'
-# Prod example
-# PAYPAL_SUBMIT_URL = 'https://www.paypal.com/cgi-bin/webscr'
-
-# For real use set to False
-PAYPAL_TEST = True
-
-########################
-# MAIN DJANGO SETTINGS #
-########################
-
-SITE_DOMAIN = 'localhost'
-
-# Hosts/domain names that are valid for this site; required if DEBUG is False
-# See https://docs.djangoproject.com/en/dev/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.
-# On Unix systems, a value of None will cause Django to use the same
-# timezone as the operating system.
-# If running in a Windows environment this must be set to the same as your
-# system time zone.
-TIME_ZONE = 'UTC'
-
-# If you set this to True, Django will use timezone-aware datetimes.
-USE_TZ = True
-
-# Language code for this installation. All choices can be found here:
-# http://www.i18nguy.com/unicode/language-identifiers.html
-LANGUAGE_CODE = "fr"
-
-# Supported languages
-LANGUAGES = (
- ('fr', _('French')),
- ('en', _('English')),
-)
-
-# A boolean that turns on/off debug mode. When set to ``True``, stack traces
-# are displayed for error pages. Should always be set to ``False`` in
-# production. Best set to ``True`` in local_settings.py
-DEBUG = False
-
-# Whether a user's session cookie expires when the Web browser is closed.
-SESSION_EXPIRE_AT_BROWSER_CLOSE = True
-
-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
-
-AUTHENTICATION_BACKENDS = ("mezzanine.core.auth_backends.MezzanineBackend",)
-
-# The numeric mode to set newly-uploaded files to. The value should be
-# a mode you'd pass directly to os.chmod.
-FILE_UPLOAD_PERMISSIONS = 0o644
-
-
-
-#############
-# DATABASES #
-#############
-
-DATABASES = {
- "default": {
- # Ends with "postgresql_psycopg2", "mysql", "sqlite3" or "oracle".
- "ENGINE": "django.db.backends.sqlite3",
- # DB name or path to database file if using sqlite3.
- "NAME": "dev.db",
- # Not used with sqlite3.
- "USER": "",
- # Not used with sqlite3.
- "PASSWORD": "",
- # Set to empty string for localhost. Not used with sqlite3.
- "HOST": "",
- # Set to empty string for default. Not used with sqlite3.
- "PORT": "",
- }
-}
-
-#########
-# PATHS #
-#########
-
-# Full filesystem path to the project.
-PROJECT_APP_PATH = os.path.dirname(os.path.abspath(__file__))
-PROJECT_APP = os.path.basename(PROJECT_APP_PATH)
-PROJECT_ROOT = BASE_DIR = os.path.dirname(PROJECT_APP_PATH)
-
-# Every cache key will get prefixed with this value - here we set it to
-# the name of the directory the project is in to try and use something
-# project specific.
-CACHE_MIDDLEWARE_KEY_PREFIX = PROJECT_APP
-
-# URL prefix for static files.
-# Example: "http://media.lawrence.com/static/"
-STATIC_URL = "/static/"
-
-# 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 = os.path.join(PROJECT_ROOT, STATIC_URL.strip("/"))
-
-# 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 = STATIC_URL + "media/"
-
-# 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.strip("/").split("/"))
-
-# Package/module name to import the root urlpatterns from for the project.
-ROOT_URLCONF = "%s.urls" % PROJECT_APP
-
-# 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.
-TEMPLATE_DIRS = (os.path.join(PROJECT_ROOT, "templates"),)
-
-
-################
-# APPLICATIONS #
-################
-
-INSTALLED_APPS = (
- "django.contrib.admin",
- "django.contrib.auth",
- "django.contrib.contenttypes",
- "django.contrib.redirects",
- "django.contrib.sessions",
- "django.contrib.sites",
- "django.contrib.sitemaps",
- "django.contrib.staticfiles",
- "mezzanine.boot",
- "mezzanine.conf",
- "mezzanine.core",
- "mezzanine.generic",
- "mezzanine.pages",
- "cartridge.shop",
- "mezzanine.blog",
- "mezzanine.forms",
- "mezzanine.galleries",
- "mezzanine.twitter",
- "mezzanine.accounts",
- # "mezzanine.mobile",
- "records",
- "payments.multipayments",
- 'paypal.standard.ipn',
-)
-
-# List of processors used by RequestContext to populate the context.
-# Each one should be a callable that takes the request object as its
-# only parameter and returns a dictionary to add to the context.
-TEMPLATE_CONTEXT_PROCESSORS = (
- "django.contrib.auth.context_processors.auth",
- "django.contrib.messages.context_processors.messages",
- "django.core.context_processors.debug",
- "django.core.context_processors.i18n",
- "django.core.context_processors.static",
- "django.core.context_processors.media",
- "django.core.context_processors.request",
- "django.core.context_processors.tz",
- "mezzanine.conf.context_processors.settings",
- "mezzanine.pages.context_processors.page",
- "payments.multipayments.context_processors.settings",
-)
-
-# List of middleware classes to use. Order is important; in the request phase,
-# these middleware classes will be applied in the order given, and in the
-# response phase the middleware will be applied in reverse order.
-MIDDLEWARE_CLASSES = (
- "mezzanine.core.middleware.UpdateCacheMiddleware",
-
- 'django.contrib.sessions.middleware.SessionMiddleware',
- # Uncomment if using internationalisation or localisation
- # 'django.middleware.locale.LocaleMiddleware',
- 'django.middleware.common.CommonMiddleware',
- 'django.middleware.csrf.CsrfViewMiddleware',
- 'django.contrib.auth.middleware.AuthenticationMiddleware',
- 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
- 'django.contrib.messages.middleware.MessageMiddleware',
- 'django.middleware.clickjacking.XFrameOptionsMiddleware',
-
- "cartridge.shop.middleware.ShopMiddleware",
- "mezzanine.core.request.CurrentRequestMiddleware",
- "mezzanine.core.middleware.RedirectFallbackMiddleware",
- "mezzanine.core.middleware.TemplateForDeviceMiddleware",
- "mezzanine.core.middleware.TemplateForHostMiddleware",
- "mezzanine.core.middleware.AdminLoginInterfaceSelectorMiddleware",
- "mezzanine.core.middleware.SitePermissionMiddleware",
- # Uncomment the following if using any of the SSL settings:
- # "mezzanine.core.middleware.SSLRedirectMiddleware",
- "mezzanine.pages.middleware.PageMiddleware",
- "mezzanine.core.middleware.FetchFromCacheMiddleware",
-)
-
-# Store these package names here as they may change in the future since
-# at the moment we are using custom forks of them.
-PACKAGE_NAME_FILEBROWSER = "filebrowser_safe"
-PACKAGE_NAME_GRAPPELLI = "grappelli_safe"
-
-#########################
-# OPTIONAL APPLICATIONS #
-#########################
-
-# These will be added to ``INSTALLED_APPS``, only if available.
-OPTIONAL_APPS = (
- "debug_toolbar",
- "django_extensions",
- "compressor",
- PACKAGE_NAME_FILEBROWSER,
- PACKAGE_NAME_GRAPPELLI,
-)
-
-##################
-# LOCAL SETTINGS #
-##################
-
-# Allow any settings to be defined in local_settings.py which should be
-# ignored in your version control system allowing for settings to be
-# defined per machine.
-try:
- from .local_settings import *
-except ImportError as e:
- if "local_settings" not in str(e):
- raise e
-
-
-####################
-# DYNAMIC SETTINGS #
-####################
-
-# set_dynamic_settings() will rewrite globals based on what has been
-# defined so far, in order to provide some better defaults where
-# applicable. We also allow this settings module to be imported
-# without Mezzanine installed, as the case may be when using the
-# fabfile, where setting the dynamic settings below isn't strictly
-# required.
-try:
- from mezzanine.utils.conf import set_dynamic_settings
-except ImportError:
- pass
-else:
- set_dynamic_settings(globals())
+++ /dev/null
-from __future__ import unicode_literals
-
-from django.conf.urls import patterns, include, url
-from django.conf.urls.i18n import i18n_patterns
-from django.contrib import admin
-
-from mezzanine.core.views import direct_to_template
-from mezzanine.conf import settings
-
-
-admin.autodiscover()
-
-# Add the urlpatterns for any custom Django applications here.
-# You can also change the ``home`` view to add your own functionality
-# to the project's homepage.
-
-urlpatterns = i18n_patterns("",
- # Change the admin prefix here to use an alternate URL for the
- # admin interface, which would be marginally more secure.
- ("^admin/", include(admin.site.urls)),
-)
-
-if settings.USE_MODELTRANSLATION:
- urlpatterns += patterns('',
- url('^i18n/$', 'django.views.i18n.set_language', name='set_language'),
- )
-
-urlpatterns += patterns('',
-
- # Cartridge URLs.
- ("^shop/", include("cartridge.shop.urls")),
- url("^account/orders/$", "cartridge.shop.views.order_history",
- name="shop_order_history"),
-
- # We don't want to presume how your homepage works, so here are a
- # few patterns you can use to set it up.
-
- # HOMEPAGE AS STATIC TEMPLATE
- # ---------------------------
- # This pattern simply loads the index.html template. It isn't
- # commented out like the others, so it's the default. You only need
- # one homepage pattern, so if you use a different one, comment this
- # one out.
-
- url("^$", direct_to_template, {"template": "index.html"}, name="home"),
-
- # HOMEPAGE AS AN EDITABLE PAGE IN THE PAGE TREE
- # ---------------------------------------------
- # This pattern gives us a normal ``Page`` object, so that your
- # homepage can be managed via the page tree in the admin. If you
- # use this pattern, you'll need to create a page in the page tree,
- # and specify its URL (in the Meta Data section) as "/", which
- # is the value used below in the ``{"slug": "/"}`` part. Make
- # sure to uncheck all templates for the "show in menus" field
- # when you create the page, since the link to the homepage is
- # always hard-coded into all the page menus that display navigation
- # on the site. Also note that the normal rule of adding a custom
- # template per page with the template name using the page's slug
- # doesn't apply here, since we can't have a template called
- # "/.html" - so for this case, the template "pages/index.html" can
- # be used.
-
- # url("^$", "mezzanine.pages.views.page", {"slug": "/"}, name="home"),
-
- # HOMEPAGE FOR A BLOG-ONLY SITE
- # -----------------------------
- # This pattern points the homepage to the blog post listing page,
- # and is useful for sites that are primarily blogs. If you use this
- # pattern, you'll also need to set BLOG_SLUG = "" in your
- # ``settings.py`` module, and delete the blog page object from the
- # page tree in the admin if it was installed.
-
- # url("^$", "mezzanine.blog.views.blog_post_list", name="home"),
-
- # MEZZANINE'S URLS
- # ----------------
- # ADD YOUR OWN URLPATTERNS *ABOVE* THE LINE BELOW.
- # ``mezzanine.urls`` INCLUDES A *CATCH ALL* PATTERN
- # FOR PAGES, SO URLPATTERNS ADDED BELOW ``mezzanine.urls``
- # WILL NEVER BE MATCHED!
-
- # If you'd like more granular control over the patterns in
- # ``mezzanine.urls``, go right ahead and take the parts you want
- # from it, and use them directly below instead of using
- # ``mezzanine.urls``.
- ("^", include("mezzanine.urls")),
-
- # MOUNTING MEZZANINE UNDER A PREFIX
- # ---------------------------------
- # You can also mount all of Mezzanine's urlpatterns under a
- # URL prefix if desired. When doing this, you need to define the
- # ``SITE_PREFIX`` setting, which will contain the prefix. Eg:
- # SITE_PREFIX = "my/site/prefix"
- # For convenience, and to avoid repeating the prefix, use the
- # commented out pattern below (commenting out the one above of course)
- # which will make use of the ``SITE_PREFIX`` setting. Make sure to
- # add the import ``from django.conf import settings`` to the top
- # of this file as well.
- # Note that for any of the various homepage patterns above, you'll
- # need to use the ``SITE_PREFIX`` setting as well.
-
- # ("^%s/" % settings.SITE_PREFIX, include("mezzanine.urls"))
-
- (r'^paypal-ipn-8c5erc9ye49ia51rn655mi4xs7/', include('paypal.standard.ipn.urls')),
-
-)
-
-# Adds ``STATIC_URL`` to the context of error pages, so that error
-# pages can use JS, CSS and images.
-handler404 = "mezzanine.core.views.page_not_found"
-handler500 = "mezzanine.core.views.server_error"
+++ /dev/null
-"""
-WSGI config for diggersdigest project.
-
-It exposes the WSGI callable as a module-level variable named ``application``.
-
-For more information on this file, see
-https://docs.djangoproject.com/en/1.8/howto/deployment/wsgi/
-"""
-
-import os
-
-from django.core.wsgi import get_wsgi_application
-from mezzanine.utils.conf import real_project_name
-
-os.environ.setdefault("DJANGO_SETTINGS_MODULE",
- "%s.settings" % real_project_name("diggersdigest"))
-
-application = get_wsgi_application()
+++ /dev/null
-from __future__ import print_function, unicode_literals
-from future.builtins import open
-
-import os
-import re
-import sys
-from contextlib import contextmanager
-from functools import wraps
-from getpass import getpass, getuser
-from glob import glob
-from importlib import import_module
-from posixpath import join
-
-from mezzanine.utils.conf import real_project_name
-
-from fabric.api import abort, env, cd, prefix, sudo as _sudo, run as _run, \
- hide, task, local
-from fabric.context_managers import settings as fab_settings
-from fabric.contrib.console import confirm
-from fabric.contrib.files import exists, upload_template
-from fabric.contrib.project import rsync_project
-from fabric.colors import yellow, green, blue, red
-from fabric.decorators import hosts
-
-
-################
-# Config setup #
-################
-
-env.proj_app = real_project_name("diggersdigest")
-
-conf = {}
-if sys.argv[0].split(os.sep)[-1] in ("fab", "fab-script.py"):
- # Ensure we import settings from the current dir
- try:
- conf = import_module("%s.settings" % env.proj_app).FABRIC
- try:
- conf["HOSTS"][0]
- except (KeyError, ValueError):
- raise ImportError
- except (ImportError, AttributeError):
- print("Aborting, no hosts defined.")
- exit()
-
-env.db_pass = conf.get("DB_PASS", None)
-env.admin_pass = conf.get("ADMIN_PASS", None)
-env.user = conf.get("SSH_USER", getuser())
-env.password = conf.get("SSH_PASS", None)
-env.key_filename = conf.get("SSH_KEY_PATH", None)
-env.hosts = conf.get("HOSTS", [""])
-
-env.proj_name = conf.get("PROJECT_NAME", env.proj_app)
-env.venv_home = conf.get("VIRTUALENV_HOME", "/home/%s/.virtualenvs" % env.user)
-env.venv_path = join(env.venv_home, env.proj_name)
-env.proj_path = "/home/%s/mezzanine/%s" % (env.user, env.proj_name)
-env.manage = "%s/bin/python %s/manage.py" % (env.venv_path, env.proj_path)
-env.domains = conf.get("DOMAINS", [conf.get("LIVE_HOSTNAME", env.hosts[0])])
-env.domains_nginx = " ".join(env.domains)
-env.domains_regex = "|".join(env.domains)
-env.domains_python = ", ".join(["'%s'" % s for s in env.domains])
-env.ssl_disabled = "#" if len(env.domains) > 1 else ""
-env.vcs_tools = ["git", "hg"]
-env.deploy_tool = conf.get("DEPLOY_TOOL", "rsync")
-env.reqs_path = conf.get("REQUIREMENTS_PATH", None)
-env.locale = conf.get("LOCALE", "en_US.UTF-8")
-env.num_workers = conf.get("NUM_WORKERS",
- "multiprocessing.cpu_count() * 2 + 1")
-
-env.secret_key = conf.get("SECRET_KEY", "")
-env.nevercache_key = conf.get("NEVERCACHE_KEY", "")
-
-# Remote git repos need to be "bare" and reside separated from the project
-if env.deploy_tool == "git":
- env.repo_path = "/home/%s/git/%s.git" % (env.user, env.proj_name)
-else:
- env.repo_path = env.proj_path
-
-
-##################
-# Template setup #
-##################
-
-# Each template gets uploaded at deploy time, only if their
-# contents has changed, in which case, the reload command is
-# also run.
-
-templates = {
- "nginx": {
- "local_path": "deploy/nginx.conf.template",
- "remote_path": "/etc/nginx/sites-enabled/%(proj_name)s.conf",
- "reload_command": "service nginx restart",
- },
- "supervisor": {
- "local_path": "deploy/supervisor.conf.template",
- "remote_path": "/etc/supervisor/conf.d/%(proj_name)s.conf",
- "reload_command": "supervisorctl update gunicorn_%(proj_name)s",
- },
- "cron": {
- "local_path": "deploy/crontab.template",
- "remote_path": "/etc/cron.d/%(proj_name)s",
- "owner": "root",
- "mode": "600",
- },
- "gunicorn": {
- "local_path": "deploy/gunicorn.conf.py.template",
- "remote_path": "%(proj_path)s/gunicorn.conf.py",
- },
- "settings": {
- "local_path": "deploy/local_settings.py.template",
- "remote_path": "%(proj_path)s/%(proj_app)s/local_settings.py",
- },
-}
-
-
-######################################
-# Context for virtualenv and project #
-######################################
-
-@contextmanager
-def virtualenv():
- """
- Runs commands within the project's virtualenv.
- """
- with cd(env.venv_path):
- with prefix("source %s/bin/activate" % env.venv_path):
- yield
-
-
-@contextmanager
-def project():
- """
- Runs commands within the project's directory.
- """
- with virtualenv():
- with cd(env.proj_path):
- yield
-
-
-@contextmanager
-def update_changed_requirements():
- """
- Checks for changes in the requirements file across an update,
- and gets new requirements if changes have occurred.
- """
- reqs_path = join(env.proj_path, env.reqs_path)
- get_reqs = lambda: run("cat %s" % reqs_path, show=False)
- old_reqs = get_reqs() if env.reqs_path else ""
- yield
- if old_reqs:
- new_reqs = get_reqs()
- if old_reqs == new_reqs:
- # Unpinned requirements should always be checked.
- for req in new_reqs.split("\n"):
- if req.startswith("-e"):
- if "@" not in req:
- # Editable requirement without pinned commit.
- break
- elif req.strip() and not req.startswith("#"):
- if not set(">=<") & set(req):
- # PyPI requirement without version.
- break
- else:
- # All requirements are pinned.
- return
- pip("-r %s/%s" % (env.proj_path, env.reqs_path))
-
-
-###########################################
-# Utils and wrappers for various commands #
-###########################################
-
-def _print(output):
- print()
- print(output)
- print()
-
-
-def print_command(command):
- _print(blue("$ ", bold=True) +
- yellow(command, bold=True) +
- red(" ->", bold=True))
-
-
-@task
-def run(command, show=True, *args, **kwargs):
- """
- Runs a shell comand on the remote server.
- """
- if show:
- print_command(command)
- with hide("running"):
- return _run(command, *args, **kwargs)
-
-
-@task
-def sudo(command, show=True, *args, **kwargs):
- """
- Runs a command as sudo on the remote server.
- """
- if show:
- print_command(command)
- with hide("running"):
- return _sudo(command, *args, **kwargs)
-
-
-def log_call(func):
- @wraps(func)
- def logged(*args, **kawrgs):
- header = "-" * len(func.__name__)
- _print(green("\n".join([header, func.__name__, header]), bold=True))
- return func(*args, **kawrgs)
- return logged
-
-
-def get_templates():
- """
- Returns each of the templates with env vars injected.
- """
- injected = {}
- for name, data in templates.items():
- injected[name] = dict([(k, v % env) for k, v in data.items()])
- return injected
-
-
-def upload_template_and_reload(name):
- """
- Uploads a template only if it has changed, and if so, reload the
- related service.
- """
- template = get_templates()[name]
- local_path = template["local_path"]
- if not os.path.exists(local_path):
- project_root = os.path.dirname(os.path.abspath(__file__))
- local_path = os.path.join(project_root, local_path)
- remote_path = template["remote_path"]
- reload_command = template.get("reload_command")
- owner = template.get("owner")
- mode = template.get("mode")
- remote_data = ""
- if exists(remote_path):
- with hide("stdout"):
- remote_data = sudo("cat %s" % remote_path, show=False)
- with open(local_path, "r") as f:
- local_data = f.read()
- # Escape all non-string-formatting-placeholder occurrences of '%':
- local_data = re.sub(r"%(?!\(\w+\)s)", "%%", local_data)
- if "%(db_pass)s" in local_data:
- env.db_pass = db_pass()
- local_data %= env
- clean = lambda s: s.replace("\n", "").replace("\r", "").strip()
- if clean(remote_data) == clean(local_data):
- return
- upload_template(local_path, remote_path, env, use_sudo=True, backup=False)
- if owner:
- sudo("chown %s %s" % (owner, remote_path))
- if mode:
- sudo("chmod %s %s" % (mode, remote_path))
- if reload_command:
- sudo(reload_command)
-
-
-def rsync_upload():
- """
- Uploads the project with rsync excluding some files and folders.
- """
- excludes = ["*.pyc", "*.pyo", "*.db", ".DS_Store", ".coverage",
- "local_settings.py", "/static", "/.git", "/.hg"]
- local_dir = os.getcwd() + os.sep
- return rsync_project(remote_dir=env.proj_path, local_dir=local_dir,
- exclude=excludes)
-
-
-def vcs_upload():
- """
- Uploads the project with the selected VCS tool.
- """
- if env.deploy_tool == "git":
- remote_path = "ssh://%s@%s%s" % (env.user, env.host_string,
- env.repo_path)
- if not exists(env.repo_path):
- run("mkdir -p %s" % env.repo_path)
- with cd(env.repo_path):
- run("git init --bare")
- local("git push -f %s master" % remote_path)
- with cd(env.repo_path):
- run("GIT_WORK_TREE=%s git checkout -f master" % env.proj_path)
- run("GIT_WORK_TREE=%s git reset --hard" % env.proj_path)
- elif env.deploy_tool == "hg":
- remote_path = "ssh://%s@%s/%s" % (env.user, env.host_string,
- env.repo_path)
- with cd(env.repo_path):
- if not exists("%s/.hg" % env.repo_path):
- run("hg init")
- print(env.repo_path)
- with fab_settings(warn_only=True):
- push = local("hg push -f %s" % remote_path)
- if push.return_code == 255:
- abort()
- run("hg update")
-
-
-def db_pass():
- """
- Prompts for the database password if unknown.
- """
- if not env.db_pass:
- env.db_pass = getpass("Enter the database password: ")
- return env.db_pass
-
-
-@task
-def apt(packages):
- """
- Installs one or more system packages via apt.
- """
- return sudo("apt-get install -y -q " + packages)
-
-
-@task
-def pip(packages):
- """
- Installs one or more Python packages within the virtual environment.
- """
- with virtualenv():
- return run("pip install %s" % packages)
-
-
-def postgres(command):
- """
- Runs the given command as the postgres user.
- """
- show = not command.startswith("psql")
- return sudo(command, show=show, user="postgres")
-
-
-@task
-def psql(sql, show=True):
- """
- Runs SQL against the project's database.
- """
- out = postgres('psql -c "%s"' % sql)
- if show:
- print_command(sql)
- return out
-
-
-@task
-def backup(filename):
- """
- Backs up the project database.
- """
- tmp_file = "/tmp/%s" % filename
- # We dump to /tmp because user "postgres" can't write to other user folders
- # We cd to / because user "postgres" might not have read permissions
- # elsewhere.
- with cd("/"):
- postgres("pg_dump -Fc %s > %s" % (env.proj_name, tmp_file))
- run("cp %s ." % tmp_file)
- sudo("rm -f %s" % tmp_file)
-
-
-@task
-def restore(filename):
- """
- Restores the project database from a previous backup.
- """
- return postgres("pg_restore -c -d %s %s" % (env.proj_name, filename))
-
-
-@task
-def python(code, show=True):
- """
- Runs Python code in the project's virtual environment, with Django loaded.
- """
- setup = "import os;" \
- "os.environ[\'DJANGO_SETTINGS_MODULE\']=\'%s.settings\';" \
- "import django;" \
- "django.setup();" % env.proj_app
- full_code = 'python -c "%s%s"' % (setup, code.replace("`", "\\\`"))
- with project():
- if show:
- print_command(code)
- result = run(full_code, show=False)
- return result
-
-
-def static():
- """
- Returns the live STATIC_ROOT directory.
- """
- return python("from django.conf import settings;"
- "print(settings.STATIC_ROOT)", show=False).split("\n")[-1]
-
-
-@task
-def manage(command):
- """
- Runs a Django management command.
- """
- return run("%s %s" % (env.manage, command))
-
-
-###########################
-# Security best practices #
-###########################
-
-@task
-@log_call
-@hosts(["root@%s" % host for host in env.hosts])
-def secure(new_user=env.user):
- """
- Minimal security steps for brand new servers.
- Installs system updates, creates new user (with sudo privileges) for future
- usage, and disables root login via SSH.
- """
- run("apt-get update -q")
- run("apt-get upgrade -y -q")
- run("adduser --gecos '' %s" % new_user)
- run("usermod -G sudo %s" % new_user)
- run("sed -i 's:RootLogin yes:RootLogin no:' /etc/ssh/sshd_config")
- run("service ssh restart")
- print(green("Security steps completed. Log in to the server as '%s' from "
- "now on." % new_user, bold=True))
-
-
-#########################
-# Install and configure #
-#########################
-
-@task
-@log_call
-def install():
- """
- Installs the base system and Python requirements for the entire server.
- """
- # Install system requirements
- sudo("apt-get update -y -q")
- apt("nginx libjpeg-dev python-dev python-setuptools git-core "
- "postgresql libpq-dev memcached supervisor python-pip")
- run("mkdir -p /home/%s/logs" % env.user)
-
- # Install Python requirements
- sudo("pip install -U pip virtualenv virtualenvwrapper mercurial")
-
- # Set up virtualenv
- run("mkdir -p %s" % env.venv_home)
- run("echo 'export WORKON_HOME=%s' >> /home/%s/.bashrc" % (env.venv_home,
- env.user))
- run("echo 'source /usr/local/bin/virtualenvwrapper.sh' >> "
- "/home/%s/.bashrc" % env.user)
- print(green("Successfully set up git, mercurial, pip, virtualenv, "
- "supervisor, memcached.", bold=True))
-
-
-@task
-@log_call
-def create():
- """
- Creates the environment needed to host the project.
- The environment consists of: system locales, virtualenv, database, project
- files, SSL certificate, and project-specific Python requirements.
- """
- # Generate project locale
- locale = env.locale.replace("UTF-8", "utf8")
- with hide("stdout"):
- if locale not in run("locale -a"):
- sudo("locale-gen %s" % env.locale)
- sudo("update-locale %s" % env.locale)
- sudo("service postgresql restart")
- run("exit")
-
- # Create project path
- run("mkdir -p %s" % env.proj_path)
-
- # Set up virtual env
- run("mkdir -p %s" % env.venv_home)
- with cd(env.venv_home):
- if exists(env.proj_name):
- if confirm("Virtualenv already exists in host server: %s"
- "\nWould you like to replace it?" % env.proj_name):
- run("rm -rf %s" % env.proj_name)
- else:
- abort()
- run("virtualenv %s" % env.proj_name)
-
- # Upload project files
- if env.deploy_tool in env.vcs_tools:
- vcs_upload()
- else:
- rsync_upload()
-
- # Create DB and DB user
- pw = db_pass()
- user_sql_args = (env.proj_name, pw.replace("'", "\'"))
- user_sql = "CREATE USER %s WITH ENCRYPTED PASSWORD '%s';" % user_sql_args
- psql(user_sql, show=False)
- shadowed = "*" * len(pw)
- print_command(user_sql.replace("'%s'" % pw, "'%s'" % shadowed))
- psql("CREATE DATABASE %s WITH OWNER %s ENCODING = 'UTF8' "
- "LC_CTYPE = '%s' LC_COLLATE = '%s' TEMPLATE template0;" %
- (env.proj_name, env.proj_name, env.locale, env.locale))
-
- # Set up SSL certificate
- if not env.ssl_disabled:
- conf_path = "/etc/nginx/conf"
- if not exists(conf_path):
- sudo("mkdir %s" % conf_path)
- with cd(conf_path):
- crt_file = env.proj_name + ".crt"
- key_file = env.proj_name + ".key"
- if not exists(crt_file) and not exists(key_file):
- try:
- crt_local, = glob(join("deploy", "*.crt"))
- key_local, = glob(join("deploy", "*.key"))
- except ValueError:
- parts = (crt_file, key_file, env.domains[0])
- sudo("openssl req -new -x509 -nodes -out %s -keyout %s "
- "-subj '/CN=%s' -days 3650" % parts)
- else:
- upload_template(crt_local, crt_file, use_sudo=True)
- upload_template(key_local, key_file, use_sudo=True)
-
- # Install project-specific requirements
- upload_template_and_reload("settings")
- with project():
- if env.reqs_path:
- pip("-r %s/%s" % (env.proj_path, env.reqs_path))
- pip("gunicorn setproctitle psycopg2 "
- "django-compressor python-memcached")
- # Bootstrap the DB
- manage("createdb --noinput --nodata")
- python("from django.conf import settings;"
- "from django.contrib.sites.models import Site;"
- "Site.objects.filter(id=settings.SITE_ID).update(domain='%s');"
- % env.domains[0])
- for domain in env.domains:
- python("from django.contrib.sites.models import Site;"
- "Site.objects.get_or_create(domain='%s');" % domain)
- if env.admin_pass:
- pw = env.admin_pass
- user_py = ("from django.contrib.auth import get_user_model;"
- "User = get_user_model();"
- "u, _ = User.objects.get_or_create(username='admin');"
- "u.is_staff = u.is_superuser = True;"
- "u.set_password('%s');"
- "u.save();" % pw)
- python(user_py, show=False)
- shadowed = "*" * len(pw)
- print_command(user_py.replace("'%s'" % pw, "'%s'" % shadowed))
-
- return True
-
-
-@task
-@log_call
-def remove():
- """
- Blow away the current project.
- """
- if exists(env.venv_path):
- run("rm -rf %s" % env.venv_path)
- if exists(env.proj_path):
- run("rm -rf %s" % env.proj_path)
- for template in get_templates().values():
- remote_path = template["remote_path"]
- if exists(remote_path):
- sudo("rm %s" % remote_path)
- if exists(env.repo_path):
- run("rm -rf %s" % env.repo_path)
- sudo("supervisorctl update")
- psql("DROP DATABASE IF EXISTS %s;" % env.proj_name)
- psql("DROP USER IF EXISTS %s;" % env.proj_name)
-
-
-##############
-# Deployment #
-##############
-
-@task
-@log_call
-def restart():
- """
- Restart gunicorn worker processes for the project.
- If the processes are not running, they will be started.
- """
- pid_path = "%s/gunicorn.pid" % env.proj_path
- if exists(pid_path):
- run("kill -HUP `cat %s`" % pid_path)
- else:
- sudo("supervisorctl update")
-
-
-@task
-@log_call
-def deploy():
- """
- Deploy latest version of the project.
- Backup current version of the project, push latest version of the project
- via version control or rsync, install new requirements, sync and migrate
- the database, collect any new static assets, and restart gunicorn's worker
- processes for the project.
- """
- if not exists(env.proj_path):
- if confirm("Project does not exist in host server: %s"
- "\nWould you like to create it?" % env.proj_name):
- create()
- else:
- abort()
-
- # Backup current version of the project
- with cd(env.proj_path):
- backup("last.db")
- if env.deploy_tool in env.vcs_tools:
- with cd(env.repo_path):
- if env.deploy_tool == "git":
- run("git rev-parse HEAD > %s/last.commit" % env.proj_path)
- elif env.deploy_tool == "hg":
- run("hg id -i > last.commit")
- with project():
- static_dir = static()
- if exists(static_dir):
- run("tar -cf static.tar --exclude='*.thumbnails' %s" %
- static_dir)
- else:
- with cd(join(env.proj_path, "..")):
- excludes = ["*.pyc", "*.pio", "*.thumbnails"]
- exclude_arg = " ".join("--exclude='%s'" % e for e in excludes)
- run("tar -cf {0}.tar {1} {0}".format(env.proj_name, exclude_arg))
-
- # Deploy latest version of the project
- with update_changed_requirements():
- if env.deploy_tool in env.vcs_tools:
- vcs_upload()
- else:
- rsync_upload()
- with project():
- manage("collectstatic -v 0 --noinput")
- manage("syncdb --noinput")
- manage("migrate --noinput")
- for name in get_templates():
- upload_template_and_reload(name)
- restart()
- return True
-
-
-@task
-@log_call
-def rollback():
- """
- Reverts project state to the last deploy.
- When a deploy is performed, the current state of the project is
- backed up. This includes the project files, the database, and all static
- files. Calling rollback will revert all of these to their state prior to
- the last deploy.
- """
- with update_changed_requirements():
- if env.deploy_tool in env.vcs_tools:
- with cd(env.repo_path):
- if env.deploy_tool == "git":
- run("GIT_WORK_TREE={0} git checkout -f "
- "`cat {0}/last.commit`".format(env.proj_path))
- elif env.deploy_tool == "hg":
- run("hg update -C `cat last.commit`")
- with project():
- with cd(join(static(), "..")):
- run("tar -xf %s/static.tar" % env.proj_path)
- else:
- with cd(env.proj_path.rsplit("/", 1)[0]):
- run("rm -rf %s" % env.proj_name)
- run("tar -xf %s.tar" % env.proj_name)
- with cd(env.proj_path):
- restore("last.db")
- restart()
-
-
-@task
-@log_call
-def all():
- """
- Installs everything required on a new system and deploy.
- From the base software, up to the deployed project.
- """
- install()
- if create():
- deploy()
+++ /dev/null
-#!/usr/bin/env python
-import os
-import sys
-
-if __name__ == "__main__":
-
- from mezzanine.utils.conf import real_project_name
-
- settings_module = "%s.settings" % real_project_name("diggersdigest")
- os.environ.setdefault("DJANGO_SETTINGS_MODULE", settings_module)
-
- from django.core.management import execute_from_command_line
-
- execute_from_command_line(sys.argv)
+++ /dev/null
-from copy import deepcopy
-
-from django.contrib import admin
-from django.utils.translation import ugettext_lazy as _
-
-from cartridge.shop.models import Product, ProductImage, ProductVariation
-from cartridge.shop.admin import ProductAdmin, ProductImageAdmin, ProductVariationAdmin
-
-from mezzanine.blog.admin import BlogPostAdmin
-from mezzanine.blog.models import BlogPost
-
-# Register your models here.
-from .models import Gallery
-from .models import Grading
-from .models import Link
-from .models import Mix
-from .models import News
-from .models import Shop
-from .models import Theme
-from .models import User
-from .models import Artist
-from .models import Label
-from .models import Country
-from .models import Record
-from .models import Podcast
-from .models import ConditionGrading
-
-class RecordInline(admin.StackedInline):
- model = Record
- extra = 0
- max_num = 0
-
-list_display = ProductAdmin.list_display
-list_display.remove("sale_price")
-list_editable = ProductAdmin.list_editable
-list_editable.remove("sale_price")
-
-class RecordProductAdmin(ProductAdmin):
- inlines = [ProductImageAdmin, ProductVariationAdmin, RecordInline]
-
-class RecordAdmin(admin.ModelAdmin):
- search_fields = ["title", "artist__name", "label__name"]
- filter_horizontal = ["performers"]
-
-
-sale_fields = ("sale_price", "sale_from", "sale_to")
-variation_fields = ProductVariationAdmin.fields
-for field in sale_fields:
- variation_fields.remove(field)
-
-
-class myProductVariationAdmin(ProductVariationAdmin):
- fields = variation_fields
-
-blog_fieldsets = deepcopy(BlogPostAdmin.fieldsets)
-blog_fieldsets.insert(1, (_("Related products"), {
- "classes": ("collapse-closed",),
- "fields": ("related_products",)}))
-blog_filter_horizontal = BlogPostAdmin.filter_horizontal
-blog_filter_horizontal += ("related_products", )
-
-
-class MyBlogPostAdmin(BlogPostAdmin):
- fieldsets = blog_fieldsets
- filter_horizontal = blog_filter_horizontal
-
-admin.site.unregister(BlogPost)
-admin.site.register(BlogPost, MyBlogPostAdmin)
-
-
-admin.site.unregister(Product)
-admin.site.register(Product, RecordProductAdmin)
-
-admin.site.register(Gallery)
-admin.site.register(Grading)
-admin.site.register(Link)
-admin.site.register(Mix)
-admin.site.register(News)
-admin.site.register(Shop)
-admin.site.register(Theme)
-admin.site.register(User)
-admin.site.register(Artist)
-admin.site.register(Label)
-admin.site.register(Country)
-admin.site.register(Record, RecordAdmin)
-admin.site.register(Podcast)
-admin.site.register(ConditionGrading)
+++ /dev/null
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-from django.core.management.base import BaseCommand, CommandError
-
-# MYSQL command to restore the old SQL DB
-# chown -R mysql:mysql /var/lib/mysql/
-# mysqld_safe &
-# mysql -u digger -p diggersdigest < /var/lib/mysql/diggersdigest.sql
-
-
-import os
-from records import models as rec_models
-from cartridge.shop.models import Product, ProductVariation, Category, ProductImage
-import datetime
-from diggersdigest import settings
-
-
-import HTMLParser
-parser = HTMLParser.HTMLParser()
-import string
-
-import mezzanine.blog.models as blog_models
-from mezzanine.pages.models import Page
-
-
-# Clean Up DB
-try:
- obj = rec_models.Shop.objects.get(titre='nkvbhbjh')
- obj.delete()
-except rec_models.Shop.DoesNotExist:
- pass
-
-DOLLAR_TO_EURO = 0.898642152 # 04/09/2015
-
-RECORDS_TO_SKIP = [2734, 1006, 1393] # Doublons
-RECORDS_TO_SKIP.append(3323) # old Fake records = "We buy records" page
-
-OLD_SHOP_LIST = rec_models.Shop.objects.exclude(pk__in = RECORDS_TO_SKIP)
-
-
-# Check mp3 in media upload path
-def check_mp3(file_list, file_path):
- abs_file_path = os.path.join(settings.MEDIA_ROOT, file_path)
- file_exists = [os.path.exists(os.path.join(abs_file_path, file_name))
- for file_name in file_list]
-
- missing_files = [file_name for (file_name, ok) in zip(file_list, file_exists) if not ok]
- if missing_files:
- print "Missing files in path : %s\n" % file_path
- print '\n'.join(missing_files)
- else:
- print "No missing MP3 Mix files"
- return missing_files
-
-# Get year and decade for record metadata
-def get_year(date):
- if date == '197':
- date = date + '?'
- try:
- year = int(date)
- decade = (year // 10 ) * 10
- except ValueError:
- if (date == '196?') | (string.find(date, '60')>-1):
- year = None
- decade = '1960'
- elif (date == '197?') | (date=='197.') | (string.find(date, '70')>-1):
- year = None
- decade = '1970'
- elif (date == '198?') | (date == 'late 198') | (string.find(date, '80')>-1):
- year = None
- decade = 1980
- elif (date == '199?') | (string.find(date, '90')>-1):
- year = None
- decade = 1990
- else:
- year, decade = None, None
- return (year, decade)
-
-
-class Command(BaseCommand):
- help = 'Populate the new database from the original backup'
-
- ## def add_arguments(self, parser):
- ## parser.add_argument('poll_id', nargs='+', type=int)
-
- # Label
- def populate_label(self):
- old_labels = set([shop.label for shop in OLD_SHOP_LIST])
- count = 0
- for lab in old_labels:
- obj, created = rec_models.Label.objects.get_or_create(name = lab)
- if created:
- count += 1
-
- self.stdout.write('Labels\n------\n')
- self.stdout.write("\t%d new label objects" % count)
- self.stdout.write("\t%d labels in DB ( %d in old DB)" % (len(rec_models.Label.objects.all()), len(old_labels)))
-
- # Artist
- def populate_artist(self):
- Artist = rec_models.Artist
- old_artist = set([shop.artiste for shop in OLD_SHOP_LIST])
- count = 0
- for artist in old_artist:
- obj, created = Artist.objects.get_or_create(name = artist)
- if created:
- count += 1
- self.stdout.write('Artist\n------\n')
- self.stdout.write("\t%d new artist objects" % count)
- self.stdout.write("\t%d artists in DB ( %d in old DB)" % (len(Artist.objects.all()), len(old_artist)))
-
- # Country
- def populate_country(self):
- Country = rec_models.Country
- old_country = set([shop.pays for shop in OLD_SHOP_LIST])
- count = 0
- for country in old_country:
- obj, created = Country.objects.get_or_create(name = country)
- if created:
- count += 1
-
- self.stdout.write('Country\n------\n')
- self.stdout.write("\t%d new country objects" % count)
- self.stdout.write("\t%d countries in DB ( %d in old DB)" % (len(Country.objects.all()), len(old_country)))
-
-
-
-
- # PODCAST FROM MIX
- def populate_podcast(self, user):
- MIX_CATEGORY = 'Podcast'
- blog_models.BlogCategory.objects.get_or_create(title=MIX_CATEGORY)
-
- PODCAST_IMG_PATH = os.path.join('uploads/blog/mixes')
- PODCAST_AUDIO_PATH = os.path.join('uploads/audio/mixes')
-
- self.stdout.write('Podcast\n-------\n')
-
- # MP3 for mix
- mp3_mix_list = [mix.mp3 for mix in rec_models.Mix.objects.all()]
-
- check_mp3(mp3_mix_list, os.path.join(PODCAST_AUDIO_PATH))
-
- ordered_mix_list = sorted(rec_models.Mix.objects.all(), key=lambda mix: mix.ordre)
- count = 0
- for mix in ordered_mix_list:
- if mix.visu1:
- img_file = str(mix.id) + '.jpg'
- img_path = os.path.join(PODCAST_IMG_PATH, img_file)
- else:
- img_path = ''
-
- audio_path = os.path.join(PODCAST_AUDIO_PATH, mix.mp3)
- #status=mix.published+1,
- #featured_image=img_path,
- #user=digger)
- if mix.titre:
- obj, created = rec_models.Podcast.objects.get_or_create(pk=mix.pk,
- title=parser.unescape(mix.titre),
- user=user)
- if created:
- count += 1
- obj.audio=audio_path
- obj.genre=mix.genre
- obj.old_date=mix.date
- desc = parser.unescape(mix.desc)
- obj.description=desc
- obj.content=desc # duplicate description in content
- obj.status=mix.published+1
- obj.featured_image=img_path
- obj.save()
-
- self.stdout.write("\t%d new Podcast objects" % count)
- self.stdout.write("\t%d Podcast in DB ( %d in old DB)" % (len(rec_models.Podcast.objects.all()), len(ordered_mix_list)))
-
- ## audio = FileField(verbose_name=_("Audio File"), max_length=200, format="audio",
- ## upload_to=upload_to("records.Podcast.audio", "audio/mixes"))
- ## genre = models.CharField(max_length=128)
- ## # titre --> title
- ## date = models.CharField(max_length=64)
- ## # desc --> description
- ## # mp3 --> audio
- ## #visu1 = models.IntegerField() si 1 --> featured_image
- ## # ordre : on laisse tombé ?
- ## # published --> status / 0 --> CONTENT_STATUS_DRAFT = 1 / 1 CONTENT_STATUS_PUBLISHED = 2
-
- ## def populate_pages(self):
- ## obj, created = Page.objects.get_or_create(status=2,
- ## #"_order"= 3,
- ## title="Contact",
- ## titles= "Contact",
- ## content_model="form",
- ## in_menus=[1, 2, 3],
- ## slug="contact",
- ## description= "Fill in the form below to get in touch with us."
- ## )
- ## #obj.delete()
- ## #obj.description= "Fill in the form below to get in touch with us."
-
- # NEWS
- def populate_news(self):
- ## news fields :
- ## 'texte' --> content
- ## 'nomlien'
- ## 'ordre' --> _order, doublons à gérer
- ## 'id' --> pk
- ## 'titre' --> title
- ## 'typelien',
- ## 'position',
- ## 'adresslien',
- ## 'visu1',
- ## 'published']
- self.stdout.write('News\n-------\n')
-
- news_date = {
- 3: datetime.datetime(2007, 11, 8, 19, 21, 39),
- 5: datetime.datetime(2007, 12, 31, 0, 19, 13),
- 6: datetime.datetime(2008, 1, 17, 12, 44, 50),
- 7: datetime.datetime(2008, 2, 13, 13, 21, 19),
- 12: datetime.datetime(2008, 4, 16, 0, 14, 23),
- 13: datetime.datetime(2013, 6, 26, 1, 55, 4, 1817),
- 14: datetime.datetime(2008, 6, 12, 21, 43, 46),
- 16: datetime.datetime(2008, 6, 17, 17, 23, 36),
- 18: datetime.datetime(2008, 7, 15, 23, 7, 42),
- 19: datetime.datetime(2008, 8, 21, 15, 44, 30),
- 20: datetime.datetime(2013, 3, 8, 17, 51, 12, 601338),
- 28: datetime.datetime(2009, 2, 14, 0, 8, 36),
- 33: datetime.datetime(2009, 3, 26, 22, 21, 2),
- 35: datetime.datetime(2013, 11, 2, 22, 4, 45, 618265),
- 40: datetime.datetime(2010, 7, 6, 1, 44, 38, 980145),
- 41: datetime.datetime(2009, 7, 28, 13, 7, 52),
- 42: datetime.datetime(2009, 7, 28, 1, 58, 32),
- 43: datetime.datetime(2009, 8, 30, 13, 9, 53),
- 46: datetime.datetime(2009, 10, 12, 16, 35, 14),
- 50: datetime.datetime(2009, 11, 26, 14, 38, 49, 257703),
- 54: datetime.datetime(2010, 1, 7, 18, 3, 1, 864172),
- 56: datetime.datetime(2010, 2, 4, 16, 16, 32, 203171),
- 59: datetime.datetime(2010, 2, 26, 3, 16, 22, 23171),
- 61: datetime.datetime(2010, 3, 11, 1, 23, 19, 667171),
- 63: datetime.datetime(2010, 3, 24, 23, 23, 55, 850107),
- 65: datetime.datetime(2010, 6, 7, 22, 5, 40, 604645),
- 67: datetime.datetime(2010, 6, 23, 11, 24, 18, 44646),
- 70: datetime.datetime(2010, 9, 23, 8, 13, 3, 448061),
- 71: datetime.datetime(2010, 10, 21, 12, 19, 52, 648562),
- 72: datetime.datetime(2010, 11, 29, 10, 7, 31, 680399),
- 73: datetime.datetime(2010, 12, 1, 11, 54, 59, 408399),
- 75: datetime.datetime(2010, 12, 31, 12, 38, 46, 636398),
- 77: datetime.datetime(2011, 5, 9, 0, 58, 42, 968596),
- 78: datetime.datetime(2011, 1, 25, 17, 6, 58, 312900),
- 79: datetime.datetime(2011, 2, 6, 14, 23, 57, 556399),
- 80: datetime.datetime(2011, 3, 3, 1, 36, 13, 28095),
- 81: datetime.datetime(2011, 3, 3, 1, 38, 52, 756095),
- 82: datetime.datetime(2011, 4, 1, 22, 40, 39, 912095),
- 83: datetime.datetime(2011, 3, 25, 1, 17, 34, 408096),
- 84: datetime.datetime(2011, 4, 22, 18, 24, 10, 581095),
- 85: datetime.datetime(2011, 5, 16, 20, 46, 34, 176095),
- 86: datetime.datetime(2011, 6, 6, 21, 26, 10, 496720),
- 87: datetime.datetime(2011, 6, 17, 20, 8, 51, 122313),
- 88: datetime.datetime(2011, 7, 7, 21, 4, 15, 230314),
- 90: datetime.datetime(2011, 8, 19, 21, 46, 36, 158814),
- 92: datetime.datetime(2011, 9, 18, 23, 27, 12, 858075),
- 94: datetime.datetime(2011, 11, 9, 15, 16, 30, 512660),
- 96: datetime.datetime(2011, 12, 10, 20, 25, 45, 36660),
- 97: datetime.datetime(2012, 1, 7, 23, 9, 25, 836659),
- 98: datetime.datetime(2012, 1, 16, 7, 41, 1, 792660),
- 100: datetime.datetime(2012, 1, 26, 15, 6, 12, 256660),
- 101: datetime.datetime(2012, 2, 6, 13, 18, 23, 84660),
- 102: datetime.datetime(2012, 2, 18, 12, 31, 46, 536660),
- 103: datetime.datetime(2012, 3, 1, 13, 29, 11, 816662),
- 106: datetime.datetime(2012, 4, 2, 19, 35, 33, 540661),
- 107: datetime.datetime(2012, 4, 6, 20, 6, 14, 972661),
- 108: datetime.datetime(2012, 4, 18, 21, 6, 9, 708893),
- 109: datetime.datetime(2012, 5, 2, 23, 39, 54, 489173),
- 110: datetime.datetime(2012, 5, 12, 3, 29, 56, 220660),
- 111: datetime.datetime(2012, 5, 22, 13, 57, 14, 244660),
- 112: datetime.datetime(2013, 2, 28, 14, 45, 6, 540838),
- 113: datetime.datetime(2012, 6, 1, 1, 53, 31, 32661),
- 114: datetime.datetime(2012, 6, 14, 20, 10, 54, 108660),
- 115: datetime.datetime(2012, 7, 2, 14, 26, 30, 896721),
- 116: datetime.datetime(2012, 7, 18, 16, 35, 42, 440661),
- 117: datetime.datetime(2012, 8, 8, 10, 24, 52, 653338),
- 119: datetime.datetime(2012, 9, 12, 1, 23, 55, 604838),
- 120: datetime.datetime(2012, 10, 2, 0, 35, 16, 192839),
- 121: datetime.datetime(2012, 10, 23, 2, 2, 26, 948838),
- 122: datetime.datetime(2012, 11, 3, 15, 44, 35, 205838),
- 123: datetime.datetime(2012, 11, 16, 2, 1, 20, 904838),
- 124: datetime.datetime(2012, 11, 29, 11, 0, 21, 732838),
- 125: datetime.datetime(2012, 12, 15, 23, 32, 42, 336838),
- 126: datetime.datetime(2013, 1, 6, 2, 3, 38, 88839),
- 127: datetime.datetime(2013, 1, 15, 18, 43, 30, 624838),
- 128: datetime.datetime(2013, 1, 22, 12, 46, 44, 540839),
- 129: datetime.datetime(2013, 1, 29, 19, 24, 57, 692838),
- 130: datetime.datetime(2013, 2, 21, 23, 39, 9, 552838),
- 131: datetime.datetime(2013, 3, 7, 0, 42, 0, 20838),
- 132: datetime.datetime(2013, 3, 12, 11, 36, 25, 840838),
- 133: datetime.datetime(2013, 3, 27, 10, 46, 48, 676838),
- 134: datetime.datetime(2013, 4, 11, 5, 42, 2, 812839),
- 135: datetime.datetime(2013, 4, 21, 10, 42, 31, 628838),
- 136: datetime.datetime(2013, 5, 15, 23, 15, 54, 164838),
- 137: datetime.datetime(2013, 6, 4, 15, 34, 36, 68817),
- 138: datetime.datetime(2013, 6, 21, 14, 1, 29, 596317),
- 139: datetime.datetime(2013, 7, 3, 1, 6, 11, 880319),
- 140: datetime.datetime(2013, 7, 23, 15, 38, 2, 64317),
- 141: datetime.datetime(2013, 8, 27, 3, 41, 39, 824317),
- 142: datetime.datetime(2013, 9, 3, 7, 6, 29, 456317),
- 143: datetime.datetime(2013, 9, 26, 13, 48, 21, 418265),
- 144: datetime.datetime(2013, 10, 4, 14, 4, 13, 950265),
- 147: datetime.datetime(2013, 11, 5, 1, 46, 33, 818265),
- 148: datetime.datetime(2014, 1, 23, 8, 57, 4, 434265),
- 149: datetime.datetime(2013, 11, 28, 15, 40, 41, 6265),
- 150: datetime.datetime(2014, 1, 9, 12, 42, 44, 706265),
- 151: datetime.datetime(2014, 1, 23, 8, 46, 25, 882265),
- 152: datetime.datetime(2014, 2, 7, 23, 20, 0, 882265),
- 153: datetime.datetime(2014, 2, 27, 20, 17, 38, 938266),
- 154: datetime.datetime(2014, 3, 26, 9, 19, 12, 450265),
- 155: datetime.datetime(2014, 4, 21, 18, 46, 11, 314265),
- 156: datetime.datetime(2014, 5, 1, 18, 26, 7, 50265),
- 158: datetime.datetime(2014, 5, 26, 11, 42, 36, 783265),
- 159: datetime.datetime(2014, 6, 13, 21, 48, 29, 214265),
- 160: datetime.datetime(2014, 6, 30, 21, 20, 7, 518265),
- 161: datetime.datetime(2014, 7, 14, 19, 24, 40, 278265),
- 162: datetime.datetime(2014, 8, 20, 2, 38, 41, 39946),
- 163: datetime.datetime(2014, 9, 5, 19, 24, 46, 661639),
- 164: datetime.datetime(2014, 9, 15, 22, 50, 48, 370368),
- 165: datetime.datetime(2014, 10, 1, 12, 48, 31, 897806),
- 166: datetime.datetime(2014, 10, 16, 16, 50, 59, 149418),
- 167: datetime.datetime(2014, 11, 8, 20, 36, 14, 584649),
- 168: datetime.datetime(2014, 11, 18, 2, 40, 48, 864752),
- 169: datetime.datetime(2014, 12, 3, 11, 45, 31, 643276),
- 170: datetime.datetime(2014, 12, 20, 0, 8, 48, 732320),
- 171: datetime.datetime(2015, 1, 11, 11, 34, 36, 966855),
- 172: datetime.datetime(2015, 1, 23, 1, 22, 51, 954981),
- 173: datetime.datetime(2015, 2, 10, 9, 6, 39, 92265),
- 174: datetime.datetime(2015, 2, 22, 3, 50, 50, 127304),
- 175: datetime.datetime(2015, 3, 11, 12, 52, 56, 176986),
- 176: datetime.datetime(2015, 4, 22, 16, 10, 44, 140259),
- 177: datetime.datetime(2015, 4, 22, 16, 22, 47, 672255),
- 178: datetime.datetime(2015, 5, 22, 10, 18, 45, 146728),
- 179: datetime.datetime(2015, 6, 26, 1, 11, 8, 869148),
- 180: datetime.datetime(2015, 7, 7, 23, 30, 46, 789683)
- }
-
- ordered_news_list = sorted(rec_models.News.objects.all(), key=lambda news: news.ordre)
- blog_models.BlogCategory.objects.get_or_create(title='News')
- import parsedatetime
- cal = parsedatetime.Calendar()
- for n in ordered_news_list:
- if n.position==1:
- try:
- d = cal.parseDateText(n.titre)
- except AttributeError:
- d = ''
- print n.titre, ' - ', d
-
-
- # Theme -> Category
- def populate_category(self):
- # This has to be run once as category are mezzanine Pages
- # they would then be handle by a fixture for 'mezzanine pages' app
-
-
-
- shop_cat, created = Category.objects.get_or_create(title="Shop")
- unclassified_cat, created = Category.objects.get_or_create(
- title="Unclassified",
- content="Unclassified records",
- parent = shop_cat,
- in_menus = [1,2])
- showcase, created = Category.objects.get_or_create(
- title="Showcase",
- content="Category for product to be placed on the HomePage",
- parent = shop_cat,
- in_menus = [])
-
-
- theme_list = [theme for theme in rec_models.Theme.objects.all()
- if (theme.published==1) and not(theme.id==39)]
- count = 0
- for theme in theme_list:
- category, create = Category.objects.get_or_create(pk=theme.id)
- category.title = theme.nom
- category.parent = shop_cat
- category.in_menus = [1, 2] # Show only in header and left panel
- category.save()
- if create:
- count +=1
-
- self.stdout.write('Category\n-------\n')
- self.stdout.write("\t%d new Category objects" % count)
-
-
- # SHOPS TO RECORDS
- def populate_record(self):
- self.stdout.write('Records\n-------\n')
-
- AUDIO_PATH = 'uploads/audio/'
- RECORDS_PATH = os.path.join(AUDIO_PATH, "records")
- IMG_PATH = os.path.join('uploads/product')
-
- unclassified_cat, created = Category.objects.get(title="Unclassified")
- UNCLASS_ID = unclassified_cat.pk
-
- THEME_TO_CATEGORY = {
- # Published
- 1: 1, # Jazz
- 2: 2, # Prog / Psych / Rock
- 37: 37, # Antilles / West Indies
- 6: 6, # Experimental / Avant
- 7: 7, # Soundtracks
- 10: 10, # Electronic / Cosmic
- 13: 13, # Middle East & Oriental
- 15: 15, # Afro / Latin
- 19: 19, # Library / Euro Grooves
- 29: 29, # Prog / Psych / Pop 7
- 22: 22, # Jazz Funk / Fusion
- 24: 24, # French Sounds
- 28: 28, # Breaks & Samples
- 30: 30, # Selected Reissues
- 33: 33, # Soul / Funk
- 38: 38, # OUR PRODUCTION
- # Unpublished categories classified above
- 42: 37, # SOLD OUT ANTILLES WEST INDIES
- 16: 19, # SOLD OUT LIBRARY 0
- 41:1, # SOLD OUT JAZZ 0
- 25: 10, # SOLD OUT ELECTRO COSMIC
- # New category for old sold-out and unclass records
- UNCLASS_ID: UNCLASS_ID,
- # Unpublished and unclassified categories
- 17: UNCLASS_ID, #Â IN STOCK ->> UNCLASSIFIED
- 18: UNCLASS_ID, #Â SOLD OUT ->> UNCLASSIFIED
- 9: UNCLASS_ID, # Stuffs->> UNCLASSIFIED
- 27: UNCLASS_ID, # SOLD OUT DEPOT->> UNCLASSIFIED
- 40: UNCLASS_ID, # Brazilian Music->> UNCLASSIFIED
- 31: UNCLASS_ID, # NEW ! 20 € & UNDER->> UNCLASSIFIED
- # Fake records category --> turn into a Page in fixture
- #Â 39 WE BUY RECORDS
- }
-
- for shop in OLD_SHOP_LIST:
-
- # Get or Create record
- record, created = rec_models.Record.objects.get_or_create(pk=shop.id)
- # Set record metadata
- record.title = parser.unescape(shop.titre)
- record.country = rec_models.Country.objects.get(name = shop.pays)
- record.audio_file = os.path.join(RECORDS_PATH, shop.mp3)
- # product_id --> FK
-
- record.release_year , record.release_decade = get_year(shop.date)
- record.date_text = shop.date # To be deleted later ?
- record.record_status = shop.new
- record.cover_condition_id = shop.cover
- record.vinyl_condition_id = shop.vinyl
- record.label = rec_models.Label.objects.get(name = shop.label)
- record.artist = rec_models.Artist.objects.get(name = shop.artiste)
- record.save()
-
- self.stdout.write('------')
- self.stdout.write('Record %d - %d' % (record.pk,len(OLD_SHOP_LIST)))
-
- # --------------------------
- # Create associated Product
- # --------------------------
- if isinstance(record.product, Product):
- product = record.product
- else:
- product = Product.objects.create()
- # Fill records ForeignKey to Product
- record.product = product
- record.save()
-
-
- product.variations.manage_empty()
-
- # Metadata
- product.title = record.title
- product.content = shop.desc
-
- # Category
- theme = rec_models.Theme.objects.get(id=shop.theme)
- category_id = THEME_TO_CATEGORY[theme.pk]
- category = Category.objects.get(pk=category_id)
- product.categories.add(category)
-
- # Manage price / availability
- product.available = (theme.published == 1) & (shop.published==1)
- product.num_in_stock = int(product.available)
-
- if shop.devise == 3: #Euros
- product.unit_price = shop.prix
- elif shop.devise == 1: # Dollar
- product.price = round(shop.prix * DOLLAR_TO_EURO)
- product.sale_price = None # No sale / pas de soldes
-
- product.save() # Needed to copy the price fields to the default variation
-
- # Cover image
- img_file = os.path.join(IMG_PATH, str(shop.pk)+'.jpg')
- abs_img_file = os.path.join(settings.MEDIA_ROOT, img_file)
- if os.path.exists(abs_img_file):
- image, created = ProductImage.objects.get_or_create(
- file=img_file,
- product=product)
- product.variations.set_default_images([])
-
- product.copy_default_variation()
- product.save()
-
- default_variation = product.variations.get(default=True)
- default_variation.sku = "DD_REC_" + str(record.pk)
- default_variation.save()
-
- self.stdout.write('Product %d / %d --> %s' % (product.pk,len(OLD_SHOP_LIST), product.available))
-
- #self.stdout.write('\b\b\b\b%.4d' % record.pk)
- #print record.__dict__
-
- ## class Shop(models.Model):
- ## theme = models.IntegerField()
- ## artiste = models.CharField(max_length=128)
- ## new = models.IntegerField()
- ## titre = models.CharField(max_length=128)
- ## label = models.CharField(max_length=128)
- ## date = models.CharField(max_length=8)
- ## pays = models.CharField(max_length=128)
- ## desc = models.TextField()
- ## cover = models.IntegerField()
- ## vinyl = models.IntegerField()
- ## prix = models.IntegerField()
- ## devise = models.IntegerField()
- ## mp3 = models.CharField(max_length=128)
- ## visu1 = models.IntegerField()
- ## ordre = models.IntegerField()
- ## published = models.IntegerField()
-
- ## class Record(Product):
- ## """
- ## Model for Record
- ## """
-
-
- def handle(self, *args, **options):
- ## for poll_id in options['poll_id']:
- ## try:
- ## poll = Poll.objects.get(pk=poll_id)
- ## except Poll.DoesNotExist:
- ## raise CommandError('Poll "%s" does not exist' % poll_id)
-
- ## poll.opened = False
- ## poll.save()
-
- ## self.stdout.write('Successfully closed poll "%s"' % poll_id)
- from django.contrib.auth import models as auth_models
- digger, created = auth_models.User.objects.get_or_create(username=u'digger',
- password=u'admin',
- is_staff=True,
- email=u'')
-
- self.populate_category()
- self.populate_label()
- self.populate_artist()
- self.populate_country()
- #self.populate_podcast(user=digger)
- #self.populate_pages()
- #self.populate_news()
-
- self.populate_record()
-
-
-
-# MP3
-mp3_shop_list = [shop.mp3 for shop in OLD_SHOP_LIST]
-
-
-AUDIO_PATH = os.path.join(settings.MEDIA_ROOT, 'uploads/audio/')
-MIX_PATH = os.path.join(AUDIO_PATH, 'mixes')
-RECORDS_PATH = os.path.join(AUDIO_PATH, "records")
-
-
-
-
-
-# check_mp3(mp3_shop_list, RECORDS_PATH)
-
-
-# GRADING
-
-Grading_Dict = {
- 'SS': {
- 'name': "Still Sealed",
- 'description': "in perfect condition, no wear"},
- 'M' : {
- 'name': "Mint" ,
- 'description': "Still in new condition, no imperfections, a Perfect Copy !"},
- 'NM' : {
- 'name': "Near mint" ,
- 'description': "Imperceptible wear, full vinyl gloss"},
- 'EX' : {
- 'name': "Excellent",
- 'description': "Only very slight wear and paper scuffs, vinyl still glossy with very rare noise"},
- 'VG++' : {
- 'name': "Near Excellent",
- 'description': "Light surface noise and wear but fairly minor, vinyl still plays nicely"},
- 'VG+' : {
- 'name': "Very Very Good",
- 'description': "Evident groove wear or minor scuff marks, surface noise noticeable but does not really affect the playing"},
- 'VG' : {
- 'name': "Very Good",
- 'description': "Wear and scuffs are more evident and many surface noises are noticeable"},
- 'VG-' : {
- 'name': "Good to Very Good",
- 'description': "Heavy groove wear or scuffing, plays noisily"}
- }
-
-
-count = 0
-for grade in rec_models.Grading.objects.all():
- name = Grading_Dict[grade.nom]['name']
- desc = Grading_Dict[grade.nom]['description']
- obj, created = rec_models.ConditionGrading.objects.get_or_create(id=grade.id,
- abbr=grade.nom,
- name=name,
- description=desc)
-
- if created:
- print "Create new GradingCondition : %s" % obj.name
- count += 1
-
-
-print "%d fiches GradingCondition crées" % count
+++ /dev/null
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
-import django.db.models.deletion
-import mezzanine.core.fields
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('blog', '0002_auto_20150527_1555'),
- ]
-
- operations = [
- migrations.CreateModel(
- name='Gallery',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('titre', models.CharField(max_length=124)),
- ('visu1', models.IntegerField()),
- ('visu2', models.IntegerField()),
- ('visu3', models.IntegerField()),
- ('visu4', models.IntegerField()),
- ('visu5', models.IntegerField()),
- ('visu6', models.IntegerField()),
- ('visu7', models.IntegerField()),
- ('visu8', models.IntegerField()),
- ('visu9', models.IntegerField()),
- ('ordre', models.IntegerField()),
- ('published', models.IntegerField()),
- ],
- options={
- 'verbose_name': 'OLD_Gallery',
- 'db_table': 'gallery',
- 'managed': False,
- },
- ),
- migrations.CreateModel(
- name='Grading',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('nom', models.CharField(max_length=5)),
- ],
- options={
- 'verbose_name': 'OLD_Grading',
- 'db_table': 'grading',
- 'managed': False,
- },
- ),
- migrations.CreateModel(
- name='Link',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('section', models.IntegerField()),
- ('adress', models.CharField(max_length=124)),
- ('desc', models.TextField()),
- ('ordre', models.IntegerField()),
- ('published', models.IntegerField()),
- ],
- options={
- 'verbose_name': 'OLD_Link',
- 'db_table': 'links',
- 'managed': False,
- },
- ),
- migrations.CreateModel(
- name='Mix',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('genre', models.CharField(max_length=128)),
- ('titre', models.CharField(max_length=128)),
- ('date', models.CharField(max_length=64)),
- ('desc', models.TextField()),
- ('mp3', models.CharField(max_length=128)),
- ('visu1', models.IntegerField()),
- ('ordre', models.IntegerField()),
- ('published', models.IntegerField()),
- ],
- options={
- 'verbose_name': 'OLD_Mix',
- 'db_table': 'mix',
- 'managed': False,
- 'verbose_name_plural': 'OLD_Mixes',
- },
- ),
- migrations.CreateModel(
- name='News',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('titre', models.CharField(max_length=128)),
- ('texte', models.TextField()),
- ('visu1', models.IntegerField()),
- ('position', models.IntegerField()),
- ('nomlien', models.CharField(max_length=128)),
- ('adresslien', models.CharField(max_length=255)),
- ('typelien', models.IntegerField()),
- ('ordre', models.IntegerField()),
- ('published', models.IntegerField()),
- ],
- options={
- 'verbose_name': 'OLD_News',
- 'db_table': 'news',
- 'managed': False,
- 'verbose_name_plural': 'OLD_News',
- },
- ),
- migrations.CreateModel(
- name='Shop',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('theme', models.IntegerField()),
- ('artiste', models.CharField(max_length=128)),
- ('new', models.IntegerField()),
- ('titre', models.CharField(max_length=128)),
- ('label', models.CharField(max_length=128)),
- ('date', models.CharField(max_length=8)),
- ('pays', models.CharField(max_length=128)),
- ('desc', models.TextField()),
- ('cover', models.IntegerField()),
- ('vinyl', models.IntegerField()),
- ('prix', models.IntegerField()),
- ('devise', models.IntegerField()),
- ('mp3', models.CharField(max_length=128)),
- ('visu1', models.IntegerField()),
- ('ordre', models.IntegerField()),
- ('published', models.IntegerField()),
- ],
- options={
- 'verbose_name': 'OLD_Shop',
- 'db_table': 'shop',
- 'managed': False,
- },
- ),
- migrations.CreateModel(
- name='Theme',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('nom', models.CharField(max_length=124)),
- ('ordre', models.IntegerField()),
- ('published', models.IntegerField()),
- ],
- options={
- 'verbose_name': 'OLD_Theme',
- 'db_table': 'theme',
- 'managed': False,
- },
- ),
- migrations.CreateModel(
- name='User',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('username', models.CharField(max_length=10)),
- ('password', models.CharField(max_length=10)),
- ('type', models.IntegerField()),
- ],
- options={
- 'db_table': 'user',
- 'managed': False,
- 'verbose_name_plural': 'OLD_User',
- },
- ),
- migrations.CreateModel(
- name='Artist',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('name', models.CharField(max_length=128)),
- ],
- ),
- migrations.CreateModel(
- name='ConditionGrading',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('abbr', models.CharField(unique=True, max_length=5, verbose_name='abbreviation')),
- ('name', models.CharField(max_length=128, verbose_name='name')),
- ('description', models.TextField(verbose_name='description')),
- ],
- ),
- migrations.CreateModel(
- name='Country',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('name', models.CharField(max_length=128)),
- ],
- ),
- migrations.CreateModel(
- name='Label',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('name', models.CharField(max_length=128)),
- ],
- ),
- migrations.CreateModel(
- name='Podcast',
- fields=[
- ('blogpost_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='blog.BlogPost')),
- ('audio', mezzanine.core.fields.FileField(max_length=200, verbose_name='Audio File')),
- ('genre', models.CharField(max_length=128, null=True)),
- ('old_date', models.CharField(max_length=64, null=True)),
- ('mix_cloud_url', models.URLField(null=True)),
- ],
- options={
- 'abstract': False,
- },
- bases=('blog.blogpost',),
- ),
- migrations.CreateModel(
- name='Record',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('title', models.CharField(max_length=128)),
- ('record_status', models.IntegerField(default=1, verbose_name='record status', choices=[(0, ''), (1, 'New'), (2, 'On Hold'), (3, 'Just Sold')])),
- ('release_date', models.DateField(null=True, verbose_name='release date')),
- ('audio_file', mezzanine.core.fields.FileField(max_length=1024, null=True, verbose_name='audio file')),
- ('artist', models.ForeignKey(related_name='records_artists', on_delete=django.db.models.deletion.SET_NULL, verbose_name='artist', to='records.Artist', null=True)),
- ('country', models.ForeignKey(related_name='records', on_delete=django.db.models.deletion.SET_NULL, verbose_name='country', to='records.Country', null=True)),
- ('label', models.ForeignKey(related_name='records', on_delete=django.db.models.deletion.SET_NULL, verbose_name='label', to='records.Label', null=True)),
- ('performers', models.ManyToManyField(related_name='records_performers', verbose_name='performer', to='records.Artist')),
- ],
- ),
- ]
+++ /dev/null
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
-import django.db.models.deletion
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('shop', '0001_initial'),
- ('records', '0001_initial'),
- ]
-
- operations = [
- migrations.AddField(
- model_name='record',
- name='product',
- field=models.ForeignKey(related_name='records', on_delete=django.db.models.deletion.SET_NULL, verbose_name='product', to='shop.Product', null=True),
- ),
- migrations.AlterField(
- model_name='record',
- name='performers',
- field=models.ManyToManyField(related_name='records_performers', verbose_name='performers', to='records.Artist'),
- ),
- ]
+++ /dev/null
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('records', '0002_auto_20150831_1518'),
- ]
-
- operations = [
- migrations.AddField(
- model_name='record',
- name='date_text',
- field=models.CharField(max_length=8, null=True, verbose_name='date text'),
- ),
- ]
+++ /dev/null
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('records', '0003_record_date_text'),
- ]
-
- operations = [
- migrations.RemoveField(
- model_name='record',
- name='release_date',
- ),
- migrations.AddField(
- model_name='record',
- name='release_decade',
- field=models.CharField(max_length=8, null=True, verbose_name='release decade', choices=[(1920, '1920s'), (1930, '1930s'), (1940, '1940s'), (1950, '1950s'), (1960, '1960s'), (1970, '1970s'), (1980, '1980s'), (1990, '1990s'), (2000, '2000s'), (2010, '2010s'), (2020, '2020s')]),
- ),
- migrations.AddField(
- model_name='record',
- name='release_year',
- field=models.IntegerField(null=True, verbose_name='release year', choices=[(1920, 1920), (1921, 1921), (1922, 1922), (1923, 1923), (1924, 1924), (1925, 1925), (1926, 1926), (1927, 1927), (1928, 1928), (1929, 1929), (1930, 1930), (1931, 1931), (1932, 1932), (1933, 1933), (1934, 1934), (1935, 1935), (1936, 1936), (1937, 1937), (1938, 1938), (1939, 1939), (1940, 1940), (1941, 1941), (1942, 1942), (1943, 1943), (1944, 1944), (1945, 1945), (1946, 1946), (1947, 1947), (1948, 1948), (1949, 1949), (1950, 1950), (1951, 1951), (1952, 1952), (1953, 1953), (1954, 1954), (1955, 1955), (1956, 1956), (1957, 1957), (1958, 1958), (1959, 1959), (1960, 1960), (1961, 1961), (1962, 1962), (1963, 1963), (1964, 1964), (1965, 1965), (1966, 1966), (1967, 1967), (1968, 1968), (1969, 1969), (1970, 1970), (1971, 1971), (1972, 1972), (1973, 1973), (1974, 1974), (1975, 1975), (1976, 1976), (1977, 1977), (1978, 1978), (1979, 1979), (1980, 1980), (1981, 1981), (1982, 1982), (1983, 1983), (1984, 1984), (1985, 1985), (1986, 1986), (1987, 1987), (1988, 1988), (1989, 1989), (1990, 1990), (1991, 1991), (1992, 1992), (1993, 1993), (1994, 1994), (1995, 1995), (1996, 1996), (1997, 1997), (1998, 1998), (1999, 1999), (2000, 2000), (2001, 2001), (2002, 2002), (2003, 2003), (2004, 2004), (2005, 2005), (2006, 2006), (2007, 2007), (2008, 2008), (2009, 2009), (2010, 2010), (2011, 2011), (2012, 2012), (2013, 2013), (2014, 2014), (2015, 2015), (2016, 2016), (2017, 2017), (2018, 2018), (2019, 2019), (2020, 2020), (2021, 2021), (2022, 2022), (2023, 2023), (2024, 2024)]),
- ),
- ]
+++ /dev/null
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('records', '0004_auto_20150904_0733'),
- ]
-
- operations = [
- migrations.AlterField(
- model_name='record',
- name='release_decade',
- field=models.IntegerField(null=True, verbose_name='release decade', choices=[(1920, '1920s'), (1930, '1930s'), (1940, '1940s'), (1950, '1950s'), (1960, '1960s'), (1970, '1970s'), (1980, '1980s'), (1990, '1990s'), (2000, '2000s'), (2010, '2010s'), (2020, '2020s')]),
- ),
- ]
+++ /dev/null
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
-import django.db.models.deletion
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('records', '0005_auto_20150904_1309'),
- ]
-
- operations = [
- migrations.AddField(
- model_name='record',
- name='cover_condition',
- field=models.ForeignKey(related_name='records_cover_condition', on_delete=django.db.models.deletion.SET_NULL, verbose_name='cover condition', to='records.ConditionGrading', null=True),
- ),
- migrations.AddField(
- model_name='record',
- name='vinyl_condition',
- field=models.ForeignKey(related_name='records_vinyl_condition', on_delete=django.db.models.deletion.SET_NULL, verbose_name='vinyl condition', to='records.ConditionGrading', null=True),
- ),
- ]
+++ /dev/null
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
-import django.db.models.deletion
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('shop', '0003_auto_20150906_1911'),
- ('records', '0006_auto_20150907_0835'),
- ]
-
- operations = [
- migrations.AddField(
- model_name='record',
- name='image',
- field=models.ForeignKey(on_delete=django.db.models.deletion.SET_NULL, verbose_name='Image', blank=True, to='shop.ProductImage', null=True),
- ),
- ]
+++ /dev/null
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
-import django.db.models.deletion
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('records', '0007_record_image'),
- ]
-
- operations = [
- migrations.AlterField(
- model_name='record',
- name='performers',
- field=models.ManyToManyField(related_name='records_performers', verbose_name='performers', to='records.Artist', blank=True),
- ),
- migrations.AlterField(
- model_name='record',
- name='product',
- field=models.OneToOneField(related_name='record', null=True, on_delete=django.db.models.deletion.SET_NULL, verbose_name='product', to='shop.Product'),
- ),
- ]
+++ /dev/null
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('records', '0008_auto_20150909_0818'),
- ]
-
- operations = [
- migrations.RemoveField(
- model_name='record',
- name='image',
- ),
- ]
+++ /dev/null
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('records', '0009_remove_record_image'),
- ]
-
- operations = [
- migrations.AlterModelOptions(
- name='artist',
- options={'ordering': ['name']},
- ),
- ]
+++ /dev/null
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-from __future__ import unicode_literals
-
-from django.db import models
-from django.utils.translation import ugettext_lazy as _
-
-import datetime
-import os
-import fnmatch
-from importlib import import_module
-from diggersdigest import settings
-# from mezzanine.conf import settings
-
-from mezzanine.core.fields import FileField
-from mezzanine.core.models import CONTENT_STATUS_DRAFT, CONTENT_STATUS_PUBLISHED
-from mezzanine.blog.models import BlogPost
-from mezzanine.utils.models import upload_to
-
-from cartridge.shop.models import Product, Category, Cart, Order, ProductVariation, DiscountCode
-from paypal.standard.ipn.signals import payment_was_successful
-from paypal.standard.models import ST_PP_COMPLETED
-from paypal.standard.ipn.signals import valid_ipn_received
-
-
-# Auto-generated Django models with manage.py inspectdb on the old database
-# You'll have to do the following manually to clean this up:
-# * Make sure each model has one field with primary_key=True
-# * Remove `managed = False` lines if you wish to allow Django to create, modify, and delete the table
-# Feel free to rename the models, but don't rename db_table values or field names.
-
-class Gallery(models.Model):
- titre = models.CharField(max_length=124)
- visu1 = models.IntegerField()
- visu2 = models.IntegerField()
- visu3 = models.IntegerField()
- visu4 = models.IntegerField()
- visu5 = models.IntegerField()
- visu6 = models.IntegerField()
- visu7 = models.IntegerField()
- visu8 = models.IntegerField()
- visu9 = models.IntegerField()
- ordre = models.IntegerField()
- published = models.IntegerField()
-
- class Meta:
- verbose_name = 'OLD_Gallery'
- managed = False
- db_table = 'gallery'
-
- def __unicode__(self):
- return self.titre
-
-
-
-class Grading(models.Model):
- nom = models.CharField(max_length=5)
-
- class Meta:
- verbose_name = 'OLD_Grading'
- managed = False
- db_table = 'grading'
-
- def __unicode__(self):
- return self.nom
-
-
-
-class Link(models.Model):
- section = models.IntegerField()
- adress = models.CharField(max_length=124)
- desc = models.TextField()
- ordre = models.IntegerField()
- published = models.IntegerField()
-
- class Meta:
- verbose_name = 'OLD_Link'
- managed = False
- db_table = 'links'
-
- def __unicode__(self):
- return self.adress
-
-
-class Mix(models.Model):
- genre = models.CharField(max_length=128)
- titre = models.CharField(max_length=128)
- date = models.CharField(max_length=64)
- desc = models.TextField()
- mp3 = models.CharField(max_length=128)
- visu1 = models.IntegerField()
- ordre = models.IntegerField()
- published = models.IntegerField()
-
- class Meta:
- verbose_name = 'OLD_Mix'
- verbose_name_plural = 'OLD_Mixes'
- managed = False
- db_table = 'mix'
-
- def __unicode__(self):
- return self.titre
-
-
-class News(models.Model):
- titre = models.CharField(max_length=128)
- texte = models.TextField()
- visu1 = models.IntegerField()
- position = models.IntegerField()
- nomlien = models.CharField(max_length=128)
- adresslien = models.CharField(max_length=255)
- typelien = models.IntegerField()
- ordre = models.IntegerField()
- published = models.IntegerField()
-
- class Meta:
- verbose_name = 'OLD_News'
- verbose_name_plural = 'OLD_News'
- managed = False
- db_table = 'news'
-
- def __unicode__(self):
- return self.titre
-
-
-class Shop(models.Model):
- theme = models.IntegerField()
- artiste = models.CharField(max_length=128)
- new = models.IntegerField()
- titre = models.CharField(max_length=128)
- label = models.CharField(max_length=128)
- date = models.CharField(max_length=8)
- pays = models.CharField(max_length=128)
- desc = models.TextField()
- cover = models.IntegerField()
- vinyl = models.IntegerField()
- prix = models.IntegerField()
- devise = models.IntegerField()
- mp3 = models.CharField(max_length=128)
- visu1 = models.IntegerField()
- ordre = models.IntegerField()
- published = models.IntegerField()
-
- class Meta:
- verbose_name = 'OLD_Shop'
- managed = False
- db_table = 'shop'
-
- def __unicode__(self):
- return self.titre
-
-
-class Theme(models.Model):
- nom = models.CharField(max_length=124)
- ordre = models.IntegerField()
- published = models.IntegerField()
-
- class Meta:
- verbose_name = 'OLD_Theme'
- managed = False
- db_table = 'theme'
-
- def __unicode__(self):
- return self.nom
-
-
-class User(models.Model):
- username = models.CharField(max_length=10)
- password = models.CharField(max_length=10)
- type = models.IntegerField()
-
- class Meta:
- verbose_name_plural = 'OLD_User'
- managed = False
- db_table = 'user'
-
- def __unicode__(self):
- return self.username
-
-
-# New models for the 'records' app
-
-class Artist(models.Model):
- name = models.CharField(max_length=128)
- def __unicode__(self):
- return self.name
-
- class Meta:
- ordering = ['name']
-
-class Label(models.Model):
- name = models.CharField(max_length=128)
- def __unicode__(self):
- return self.name
-
- class Meta:
- ordering = ['name']
-
-class Country(models.Model):
- name = models.CharField(max_length=128)
- def __unicode__(self):
- return self.name
-
- class Meta:
- ordering = ['name']
-
-
-class ConditionGrading(models.Model):
-
- abbr = models.CharField(_('abbreviation'), max_length=5, unique=True)
- name = models.CharField(_('name'), max_length=128)
- description = models.TextField(_('description'))
-
- def __unicode__(self):
- return " = ".join([self.abbr, self.name])
-
-class Record(models.Model):
- """
- Model for Record
- """
-## # herited fields (from Product):
-## # title --> shop.titre
-## # categories --> shop.theme
-## # price --> shop.prix
-## # status --> shop.published
- NEW = 1
- ON_HOLD = 2
- JUST_SOLD = 3
- NOVELTY_CHOICES = (
- (0, ''),
- (NEW, 'New'),
- (ON_HOLD, 'On Hold'),
- (JUST_SOLD, 'Just Sold')
- )
-
- YEAR_START = 1920
-
- YEAR_STOP = datetime.datetime.now().year + 10
- DECADE_START = (YEAR_START // 10) * 10
- YEAR_CHOICES = [(y, y) for y in range(YEAR_START, YEAR_STOP)]
- DECADE_CHOICES = [(d, str(d)+'s') for d in range (DECADE_START, YEAR_STOP, 10)]
-
- title = models.CharField(max_length=128)
- artist = models.ForeignKey(Artist, verbose_name=_('artist'), related_name='records_artists', null=True, on_delete=models.SET_NULL)
- performers = models.ManyToManyField(Artist, verbose_name=_('performers'), related_name='records_performers', blank=True)
- record_status = models.IntegerField(_('record status'), choices=NOVELTY_CHOICES, default=NEW)
- label = models.ForeignKey(Label, verbose_name=_('label'), related_name='records', null=True, on_delete=models.SET_NULL)
- release_year = models.IntegerField(_('release year'), null=True, choices=YEAR_CHOICES)
- release_decade = models.IntegerField(_('release decade'), null=True, choices=DECADE_CHOICES)
- date_text = models.CharField(_('date text'), max_length=8, null=True)
- country = models.ForeignKey(Country, verbose_name=_('country'), related_name='records', null=True, on_delete=models.SET_NULL)
- cover_condition = models.ForeignKey(ConditionGrading, verbose_name=_('cover condition'), related_name='records_cover_condition', null=True, on_delete=models.SET_NULL)
- vinyl_condition = models.ForeignKey(ConditionGrading, verbose_name=_('vinyl condition'), related_name='records_vinyl_condition', null=True, on_delete=models.SET_NULL)
- audio_file = FileField(_("audio file"), max_length=1024, format="audio",
- upload_to=upload_to("records.Record.audio", "audio/records"), null=True)
- product = models.OneToOneField(Product, verbose_name=_('product'), related_name='record', null=True, on_delete=models.SET_NULL)
-
- def __unicode__(self):
- return " - ".join([self.artist.name, self.title])
-
- def get_candidate_images(self):
- candidates = []
- img_path = os.path.join(settings.MEDIA_ROOT, 'backup_images')
- patterns = []
- if self.artist:
- patterns.append(self.artist.name.strip().lower().replace(' ',''))
- if self.title:
- patterns.append(self.title.strip().lower().replace(' ',''))
- for root, dirnames, filenames in os.walk(img_path):
- for pattern in patterns:
- for filename in filenames:
- if fnmatch.fnmatch(filename.lower(), '*' + pattern + '*.jpg'):
- candidates.append(os.path.join(root, filename))
- return candidates
-
-
-class Podcast(BlogPost):
- audio = FileField(verbose_name=_("Audio File"), max_length=200, format="Audio",
- upload_to=upload_to("records.Podcast.audio", "audio/mixes"))
- genre = models.CharField(max_length=128, null=True)
- # titre --> title
- old_date = models.CharField(max_length=64, null=True)
- mix_cloud_url = models.URLField(null=True)
- # desc --> description
- # mp3 --> audio
- #visu1 = models.IntegerField()
- # ordre : on laisse tombé ?
- #Â published --> status / 0 --> CONTENT_STATUS_DRAFT = 1 / 1 CONTENT_STATUS_PUBLISHED = 2
-
-
-def payment_complete(sender, **kwargs):
- """Performs the same logic as the code in
- cartridge.shop.models.Order.complete(), but fetches the session,
- order, and cart objects from storage, rather than relying on the
- request object being passed in (which it isn't, since this is
- triggered on PayPal IPN callback)."""
-
- ipn_obj = sender
-
- if ipn_obj.custom and ipn_obj.invoice and ipn_obj.payment_status == ST_PP_COMPLETED:
- s_key, cart_pk = ipn_obj.custom.split(',')
- SessionStore = import_module(settings.SESSION_ENGINE) \
- .SessionStore
- session = SessionStore(s_key)
-
- try:
- cart = Cart.objects.get(id=cart_pk)
- try:
- order = Order.objects.get(
- transaction_id=ipn_obj.invoice)
- for field in order.session_fields:
- if field in session:
- del session[field]
- try:
- del session["order"]
- except KeyError:
- pass
-
- # Since we're manually changing session data outside of
- # a normal request, need to force the session object to
- # save after modifying its data.
- session.save()
-
- for item in cart:
- try:
- variation = ProductVariation.objects.get(
- sku=item.sku)
- except ProductVariation.DoesNotExist:
- pass
- else:
- variation.update_stock(item.quantity * -1)
- variation.product.actions.purchased()
-
- code = session.get('discount_code')
- if code:
- DiscountCode.objects.active().filter(code=code) \
- .update(uses_remaining=F('uses_remaining') - 1)
- cart.delete()
- except Order.DoesNotExist:
- pass
- except Cart.DoesNotExist:
- pass
-
-payment_was_successful.connect(payment_complete)
-valid_ipn_received.connect(payment_complete)
+++ /dev/null
-# This is an auto-generated Django model module.\r
-# You'll have to do the following manually to clean this up:\r
-# * Rearrange models' order\r
-# * Make sure each model has one field with primary_key=True\r
-# * Remove `managed = False` lines if you wish to allow Django to create, modify, and delete the table\r
-# Feel free to rename the models, but don't rename db_table values or field names.\r
-#\r
-# Also note: You'll have to insert the output of 'django-admin sqlcustom [app_label]'\r
-# into your database.\r
-from __future__ import unicode_literals\r
-\r
-from django.db import models\r
-\r
-\r
-class Gallery(models.Model):\r
- titre = models.CharField(max_length=124)\r
- visu1 = models.IntegerField()\r
- visu2 = models.IntegerField()\r
- visu3 = models.IntegerField()\r
- visu4 = models.IntegerField()\r
- visu5 = models.IntegerField()\r
- visu6 = models.IntegerField()\r
- visu7 = models.IntegerField()\r
- visu8 = models.IntegerField()\r
- visu9 = models.IntegerField()\r
- ordre = models.IntegerField()\r
- published = models.IntegerField()\r
-\r
- class Meta:\r
- managed = False\r
- db_table = 'gallery'\r
-\r
-\r
-class Grading(models.Model):\r
- nom = models.CharField(max_length=5)\r
-\r
- class Meta:\r
- managed = False\r
- db_table = 'grading'\r
-\r
-\r
-class Links(models.Model):\r
- section = models.IntegerField()\r
- adress = models.CharField(max_length=124)\r
- desc = models.TextField()\r
- ordre = models.IntegerField()\r
- published = models.IntegerField()\r
-\r
- class Meta:\r
- managed = False\r
- db_table = 'links'\r
-\r
-\r
-class Mix(models.Model):\r
- genre = models.CharField(max_length=128)\r
- titre = models.CharField(max_length=128)\r
- date = models.CharField(max_length=64)\r
- desc = models.TextField()\r
- mp3 = models.CharField(max_length=128)\r
- visu1 = models.IntegerField()\r
- ordre = models.IntegerField()\r
- published = models.IntegerField()\r
-\r
- class Meta:\r
- managed = False\r
- db_table = 'mix'\r
-\r
-\r
-class News(models.Model):\r
- titre = models.CharField(max_length=128)\r
- texte = models.TextField()\r
- visu1 = models.IntegerField()\r
- position = models.IntegerField()\r
- nomlien = models.CharField(max_length=128)\r
- adresslien = models.CharField(max_length=255)\r
- typelien = models.IntegerField()\r
- ordre = models.IntegerField()\r
- published = models.IntegerField()\r
-\r
- class Meta:\r
- managed = False\r
- db_table = 'news'\r
-\r
-\r
-class Shop(models.Model):\r
- theme = models.IntegerField()\r
- artiste = models.CharField(max_length=128)\r
- new = models.IntegerField()\r
- titre = models.CharField(max_length=128)\r
- label = models.CharField(max_length=128)\r
- date = models.CharField(max_length=8)\r
- pays = models.CharField(max_length=128)\r
- desc = models.TextField()\r
- cover = models.IntegerField()\r
- vinyl = models.IntegerField()\r
- prix = models.IntegerField()\r
- devise = models.IntegerField()\r
- mp3 = models.CharField(max_length=128)\r
- visu1 = models.IntegerField()\r
- ordre = models.IntegerField()\r
- published = models.IntegerField()\r
-\r
- class Meta:\r
- managed = False\r
- db_table = 'shop'\r
-\r
-\r
-class Theme(models.Model):\r
- nom = models.CharField(max_length=124)\r
- ordre = models.IntegerField()\r
- published = models.IntegerField()\r
-\r
- class Meta:\r
- managed = False\r
- db_table = 'theme'\r
-\r
-\r
-class User(models.Model):\r
- username = models.CharField(max_length=10)\r
- password = models.CharField(max_length=10)\r
- type = models.IntegerField()\r
-\r
- class Meta:\r
- managed = False\r
- db_table = 'user'\r
+++ /dev/null
-from django.db.models import Q
-
-from mezzanine import template
-from cartridge.shop.models import Product, Category
-
-register = template.Library()
-
-
-@register.as_tag
-def shop_recent_products(limit=5, category=None):
- """
- Put a list of recently published products into the template
- context. A tag title or slug, category title or slug or author's
- username can also be specified to filter the recent posts returned.
- Usage::
- {% blog_recent_posts 5 as recent_posts %}
- {% blog_recent_posts limit=5 tag="django" as recent_posts %}
- {% blog_recent_posts limit=5 category="python" as recent_posts %}
- """
- products = Product.objects.published().filter(available=True).order_by("-publish_date")
- title_or_slug = lambda s: Q(title=s) | Q(slug=s)
-
- if category is not None:
- try:
- category = Category.objects.get(title_or_slug(category))
- products = products.filter(categories=category)
- except Category.DoesNotExist:
- return []
-
- return list(products[:limit])
+++ /dev/null
-from django.test import TestCase
-
-# Create your tests here.
+++ /dev/null
-from django.shortcuts import render
-
-# Create your views here.
+++ /dev/null
-from django.contrib import admin
-
-# Register your models here.
-from .models import RecordProduct
+++ /dev/null
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('records', '0001_initial'),
- ('shop', '0001_initial'),
- ]
-
- operations = [
- migrations.CreateModel(
- name='RecordProduct',
- fields=[
- ('product_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='shop.Product')),
- ('record', models.ForeignKey(related_name='record', verbose_name='record', to='records.Record')),
- ],
- options={
- 'abstract': False,
- },
- bases=('shop.product',),
- ),
- ]
+++ /dev/null
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-from django.db import models
-from django.utils.translation import ugettext_lazy as _
-
-from cartridge.shop.models import Product, ProductVariation
-
-from records.models import Record
-
-class RecordProduct(Product):
- record = models.ForeignKey(Record, verbose_name=_('record'), related_name='record')
+++ /dev/null
-from django.test import TestCase
-
-# Create your tests here.
+++ /dev/null
-from django.shortcuts import render
-
-# Create your views here.
+++ /dev/null
-.container{
- background:url("../img/dotted_background.png"
- ) repeat;
-}
-
-.slim_margins{
- padding-right:1px;
- padding-left:1px;
-}
-
-body {
- padding-top: 182px;
-}
-
-hr {
- display: block;
- height: 2px;
- border: 0;
- border-top: 2px solid #000;
- margin: 1em 0;
- padding: 0;
-}
-
-.bg-white {
- background-color: white;
- padding: 5px;
-}
-
-.description {
- background-color: white;
- padding: 1em 1em 1em 2em;
- box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
- border: 1px solid #dddddd;
- border-radius: 4px;
-}
-
-.navbar-default {
- background: white;
- margin-bottom: 30px;
-}
-
-.price:only-child, .coming-soon {
- margin-top: 3px;
- display: block;
- font-weight: bold;
-}
-
-.navbar-collapse {
- margin-top: 50px;
-}
-
-#logo {
- float: left;
-}
-
-#user_panel_header {
- float: right;
- margin-top: -90px;
-}
-
-.audio {
- margin-top: 2em;
-}
+++ /dev/null
-{% extends "accounts/account_form.html" %}
-{% load i18n %}
-
-{% block account_form_actions %}
-{{ block.super }}
-<a class="btn btn-default btn-lg pull-left" href="{% url "shop_order_history" %}">{% trans "View past orders" %}</a>
-{% endblock %}
+++ /dev/null
-<!doctype html>
-<html lang="{{ LANGUAGE_CODE }}"{% if LANGUAGE_BIDI %} dir="rtl"{% endif %}>
-{% load pages_tags mezzanine_tags i18n staticfiles %}
-
-<head>
-<meta http-equiv="Content-type" content="text/html; charset=utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1.0">
-<meta name="keywords" content="{% block meta_keywords %}{% endblock %}">
-<meta name="description" content="{% block meta_description %}{% endblock %}">
-<title>{% block meta_title %}{% endblock %}{% if settings.SITE_TITLE %} | {{ settings.SITE_TITLE }}{% endif %}</title>
-<link rel="shortcut icon" href="{% static "img/favicon.ico" %}">
-
-{% ifinstalled mezzanine.blog %}
-<link rel="alternate" type="application/rss+xml" title="RSS" href="{% url "blog_post_feed" "rss" %}">
-<link rel="alternate" type="application/atom+xml" title="Atom" href="{% url "blog_post_feed" "atom" %}">
-{% endifinstalled %}
-
-{% compress css %}
-<link rel="stylesheet" href="{% static "css/bootstrap.css" %}">
-<link rel="stylesheet" href="{% static "css/mezzanine.css" %}">
-<link rel="stylesheet" href="{% static "css/bootstrap-theme.css" %}">
-{% if LANGUAGE_BIDI %}
-<link rel="stylesheet" href="{% static "css/bootstrap-rtl.css" %}">
-{% endif %}
-{% ifinstalled cartridge.shop %}
-<link rel="stylesheet" href="{% static "css/cartridge.css" %}">
-{% if LANGUAGE_BIDI %}
-<link rel="stylesheet" href="{% static "css/cartridge.rtl.css" %}">
-{% endif %}
-<link rel="stylesheet" href="{% static "css/dig2.css" %}">
-{% endifinstalled %}
-{% block extra_css %}{% endblock %}
-{% endcompress %}
-
-{% compress js %}
-<script src="{% static "mezzanine/js/"|add:settings.JQUERY_FILENAME %}"></script>
-<script src="{% static "js/bootstrap.js" %}"></script>
-<script src="{% static "js/bootstrap-extras.js" %}"></script>
-{% block extra_js %}{% endblock %}
-{% endcompress %}
-
-<!--[if lt IE 9]>
-<script src="{% static "js/html5shiv.js" %}"></script>
-<script src="{% static "js/respond.min.js" %}"></script>
-<![endif]-->
-
-<script>(function(d, s, id) {
- var js, fjs = d.getElementsByTagName(s)[0];
- if (d.getElementById(id)) return;
- js = d.createElement(s); js.id = id;
- js.src = "//connect.facebook.net/fr_FR/sdk.js#xfbml=1&version=v2.4&appId=348560078520326";
- fjs.parentNode.insertBefore(js, fjs);
- }(document, 'script', 'facebook-jssdk'));
-</script>
-
-{% block extra_head %}{% endblock %}
-</head>
-
-<body id="{% block body_id %}body{% endblock %}">
-<div class="navbar navbar-default navbar-fixed-top" role="navigation">
- <div class="container ">
- <div class="navbar-header">
- <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
- <span class="sr-only">{% trans "Toggle Navigation" %}</span>
- <span class="icon-bar"></span>
- <span class="icon-bar"></span>
- <span class="icon-bar"></span>
- </button>
- <div id="logo">
- {% if settings.SITE_TITLE %}<a class="navbar-brand" href="/"><img class="pull-left" width="180" src="{% static "img/diggersdigest_400.png" %}"alt={{ settings.SITE_TITLE }} ></a>{% endif %}
- {% if settings.SITE_TAGLINE %}<p class="navbar-text visible-lg">{{ settings.SITE_TAGLINE }}</p>{% endif %}
- </div>
- </div>
- <div>
- {% search_form "all" %}
- </div>
- <div class="navbar-collapse collapse">
- {% page_menu "pages/menus/dropdown.html" %}
- </div>
- <div id="user_panel_header">
- {% nevercache %}
- {% include "includes/language_selector.html" %}
- {% include "includes/user_panel_header.html" %}
- {% endnevercache %}
- </div>
- <hr>
-</div>
-
-</div>
-
-<div class="container">
-
-{% nevercache %}
-{% if messages %}
-<div class="messages">
-{% for message in messages %}
-<div class="alert alert-dismissable alert-{{ message.tags }}" data-alert="alert">
- <button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
- {{ message }}
-</div>
-{% endfor %}
-</div>
-{% endif %}
-{% endnevercache %}
-
-<h1>{% block title %}{% endblock %}</h1>
-
-{% comment - Remove breadcrumbs %}
-<ul class="breadcrumb">
-{% spaceless %}
-{% block breadcrumb_menu %}{% page_menu "pages/menus/breadcrumb.html" %}{% endblock %}
-{% endspaceless %}
-</ul>
-{% endcomment %}
-
-</div>
-
-<div class="container">
-<div class="row">
-
-{% comment - Remove left panel %}
-<div class="col-md-2 left">
- {% block left_panel %}
- <div class="panel panel-default tree">{% page_menu "pages/menus/tree.html" %}</div>
- {% endblock %}
-</div>
-{% endcomment %}
-
-<div class="col-md-12 middle">
- {% block main %}{% endblock %}
-</div>
-
-{% comment %}
-<div class="col-md-3 right">
- <div class="panel panel-default">
- <div class="panel-body">
- {% block right_panel %}
- {% ifinstalled mezzanine.twitter %}
- {% include "twitter/tweets.html" %}
- {% endifinstalled %}
- {% endblock %}
- </div>
- </div>
-</div>
-{% endcomment %}
-
-</div>
-</div>
-
-<footer>
-<div>
-<!-- {% page_menu "pages/menus/footer.html" %} -->
-
-<div>
-<p class="site-info text-center">
- {% trans "Coded by" %}
- <a href="http://www.parisson.com">Parisson</a>
- <span class="separator">|</span>
- {% trans "Powered by" %}
- <a href="http://mezzanine.jupo.org">Mezzanine</a>{% ifinstalled cartridge.shop %},
- <a href="http://cartridge.jupo.org">Cartridge</a>{% endifinstalled %}
- {% trans "and" %}
- <a href="http://www.djangoproject.com">Django</a>
- <span class="separator">|</span>
- {% trans "Theme by" %} <a target="_blank" href="http://getbootstrap.com">Bootstrap</a>
- {% ifinstalled mezzanine.mobile %}
- <span class="separator">|</span>
- <a href="{% url "set_device" "mobile" %}?next={{ request.path }}">{% trans "View Mobile Site" %}</a>
- {% endifinstalled %}
-</p>
-</div>
-<div class="fb-follow"></div>
-</div>
-
-</footer>
-
-{% include "includes/footer_scripts.html" %}
-
-</body>
-</html>
+++ /dev/null
-{% extends "blog/blog_post_list.html" %}
-{% load mezzanine_tags comment_tags keyword_tags rating_tags i18n disqus_tags %}
-
-{% block meta_title %}{{ blog_post.meta_title }}{% endblock %}
-
-{% block meta_keywords %}{% metablock %}
-{% keywords_for blog_post as tags %}
-{% for tag in tags %}{% if not forloop.first %}, {% endif %}{{ tag }}{% endfor %}
-{% endmetablock %}{% endblock %}
-
-{% block meta_description %}{% metablock %}
-{{ blog_post.description }}
-{% endmetablock %}{% endblock %}
-
-{% block title %}
-{% editable blog_post.title %}{{ blog_post.title }}{% endeditable %}
-{% endblock %}
-
-{% block breadcrumb_menu %}
-{{ block.super }}
-<li class="active">{{ blog_post.title }}</li>
-{% endblock %}
-
-{% block main %}
-
-{% block blog_post_detail_postedby %}
-{% editable blog_post.publish_date %}
-<h6 class="post-meta">
- {% trans "Posted by" %}:
- {% with blog_post.user as author %}
- <a href="{% url "blog_post_list_author" author %}">{{ author.get_full_name|default:author.username }}</a>
- {% endwith %}
- {% blocktrans with sometime=blog_post.publish_date|timesince %}{{ sometime }} ago{% endblocktrans %}
-</h6>
-{% endeditable %}
-{% endblock %}
-{% block blog_post_detail_commentlink %}
-<p>
- {% if blog_post.allow_comments %}
- {% if settings.COMMENTS_DISQUS_SHORTNAME %}
- (<a href="{{ blog_post.get_absolute_url }}#disqus_thread"
- data-disqus-identifier="{% disqus_id_for blog_post %}">{% spaceless %}
- {% trans "Comments" %}
- {% endspaceless %}</a>)
- {% else %}(<a href="#comments">{% spaceless %}
- {% blocktrans count comments_count=blog_post.comments_count %}{{ comments_count }} comment{% plural %}{{ comments_count }} comments{% endblocktrans %}
- {% endspaceless %}</a>)
- {% endif %}
- {% endif %}
-</p>
-{% endblock %}
-
-{% block blog_post_detail_featured_image %}
-{% if settings.BLOG_USE_FEATURED_IMAGE and blog_post.featured_image %}
-<p><img class="img-responsive" src="{{ MEDIA_URL }}{% thumbnail blog_post.featured_image 600 0 %}"></p>
-{% endif %}
-{% endblock %}
-
-{% if settings.COMMENTS_DISQUS_SHORTNAME %}
-{% include "generic/includes/disqus_counts.html" %}
-{% endif %}
-
-{% block blog_post_detail_content %}
-{% editable blog_post.content %}
-{{ blog_post.content|richtext_filters|safe }}
-{% endeditable %}
-{% endblock %}
-
-{% block blog_post_detail_keywords %}
-{% keywords_for blog_post as tags %}
-{% if tags %}
-{% spaceless %}
-<ul class="list-inline tags">
- <li>{% trans "Tags" %}:</li>
- {% for tag in tags %}
- <li><a href="{% url "blog_post_list_tag" tag.slug %}">{{ tag }}</a>{% if not forloop.last %}, {% endif %}</li>
- {% endfor %}
-</ul>
-{% endspaceless %}
-{% endif %}
-{% endblock %}
-
-<br/><br/>
-{% comment %}
-{% block blog_post_detail_rating %}
-<div class="panel panel-default rating">
- <div class="panel-body">
- {% rating_for blog_post %}
- </div>
-</div>
-{% endblock %}
-{% endcomment %}
-
-{% block blog_post_detail_sharebuttons %}
-{% set_short_url_for blog_post %}
-<a class="btn btn-sm share-twitter" target="_blank" href="http://twitter.com/home?status={{ blog_post.short_url|urlencode }}%20{{ blog_post.title|urlencode }}">{% trans "Share on Twitter" %}</a>
-<a class="btn btn-sm share-facebook" target="_blank" href="http://facebook.com/sharer.php?u={{ request.build_absolute_uri }}&t={{ blog_post.title|urlencode }}">{% trans "Share on Facebook" %}</a>
-{% endblock %}
-
-{% block blog_post_previous_next %}
-<ul class="pager">
-{% with blog_post.get_previous_by_publish_date as previous %}
-{% if previous %}
-<li class="previous">
- <a href="{{ previous.get_absolute_url }}">← {{ previous }}</a>
-</li>
-{% endif %}
-{% endwith %}
-{% with blog_post.get_next_by_publish_date as next %}
-{% if next %}
-<li class="next">
- <a href="{{ next.get_absolute_url }}">{{ next }} →</a>
-</li>
-{% endif %}
-{% endwith %}
-</ul>
-{% endblock %}
-
-{% block blog_post_detail_related_posts %}
-{% if related_posts %}
-<div id="related-posts">
-<h3>{% trans 'Related posts' %}</h3>
-<ul class="list-unstyled">
-{% for post in related_posts %}
- <li><a href="{{ post.get_absolute_url }}">{{ post.title }}</a></li>
-{% endfor %}
-</ul>
-</div>
-{% endif %}
-{% endblock %}
-
-{% block blog_post_detail_comments %}
-{% if blog_post.allow_comments %}{% comments_for blog_post %}{% endif %}
-{% endblock %}
-
-{% endblock %}
+++ /dev/null
-{% extends "base.html" %}
-{% load i18n mezzanine_tags blog_tags keyword_tags disqus_tags %}
-
-{% block meta_title %}{% if page %}{{ page.meta_title }}{% else %}{% trans "Blog" %}{% endif %}{% endblock %}
-
-{% block meta_keywords %}{% metablock %}
-{% keywords_for page as keywords %}
-{% for keyword in keywords %}
- {% if not forloop.first %}, {% endif %}
- {{ keyword }}
-{% endfor %}
-{% endmetablock %}{% endblock %}
-
-{% block meta_description %}{% metablock %}
-{{ page.description }}
-{% endmetablock %}{% endblock %}
-
-{% block title %}
-{% if page %}
-{% editable page.title %}{{ page.title }}{% endeditable %}
-{% else %}
-{% trans "Blog" %}
-{% endif %}
-{% endblock %}
-
-{% block breadcrumb_menu %}
-{{ block.super }}
-{% if tag or category or year or month or author %}
-<li>{% spaceless %}
-{% if tag %}
- {% trans "Tag:" %} {{ tag }}
-{% else %}{% if category %}
- {% trans "Category:" %} {{ category }}
-{% else %}{% if year or month %}
- {% if month %}{{ month }}, {% endif %}{{ year }}
-{% else %}{% if author %}
- {% trans "Author:" %} {{ author.get_full_name|default:author.username }}
-{% endif %}{% endif %}{% endif %}{% endif %}
-{% endspaceless %}
-</li>
-{% endif %}
-{% endblock %}
-
-{% block main %}
-
-{% if tag or category or year or month or author %}
- {% block blog_post_list_filterinfo %}
- <p>
- {% if tag %}
- {% trans "Viewing posts tagged" %} {{ tag }}
- {% else %}{% if category %}
- {% trans "Viewing posts for the category" %} {{ category }}
- {% else %}{% if year or month %}
- {% trans "Viewing posts from" %} {% if month %}{{ month }}, {% endif %}
- {{ year }}
- {% else %}{% if author %}
- {% trans "Viewing posts by" %}
- {{ author.get_full_name|default:author.username }}
- {% endif %}{% endif %}{% endif %}{% endif %}
- {% endblock %}
- </p>
-{% else %}
- {% if page %}
- {% block blog_post_list_pagecontent %}
- {% if page.get_content_model.content %}
- {% editable page.get_content_model.content %}
- {{ page.get_content_model.content|richtext_filters|safe }}
- {% endeditable %}
- {% endif %}
- {% endblock %}
- {% endif %}
-{% endif %}
-
-{% for blog_post in blog_posts.object_list %}
-{% block blog_post_list_post_title %}
-{% editable blog_post.title %}
-<h2>
- <a href="{{ blog_post.get_absolute_url }}">{{ blog_post.title }}</a>
-</h2>
-{% endeditable %}
-{% endblock %}
-{% block blog_post_list_post_metainfo %}
-{% editable blog_post.publish_date %}
-<h6 class="post-meta">
- {% trans "Posted by" %}:
- {% with blog_post.user as author %}
- <a href="{% url "blog_post_list_author" author %}">{{ author.get_full_name|default:author.username }}</a>
- {% endwith %}
- {% with blog_post.categories.all as categories %}
- {% if categories %}
- {% trans "in" %}
- {% for category in categories %}
- <a href="{% url "blog_post_list_category" category.slug %}">{{ category }}</a>{% if not forloop.last %}, {% endif %}
- {% endfor %}
- {% endif %}
- {% endwith %}
- {% blocktrans with sometime=blog_post.publish_date|timesince %}{{ sometime }} ago{% endblocktrans %}
-</h6>
-{% endeditable %}
-{% endblock %}
-
-{% if settings.BLOG_USE_FEATURED_IMAGE and blog_post.featured_image %}
-{% block blog_post_list_post_featured_image %}
-<a href="{{ blog_post.get_absolute_url }}">
- <img class="img-thumbnail pull-left" src="{{ MEDIA_URL }}{% thumbnail blog_post.featured_image 90 90 %}">
-</a>
-{% endblock %}
-{% endif %}
-
-{% block blog_post_list_post_content %}
-{% editable blog_post.content %}
-{{ blog_post.description_from_content|safe }}
-{% endeditable %}
-{% endblock %}
-
-{% block blog_post_list_post_links %}
-<div class="blog-list-detail">
- {% keywords_for blog_post as tags %}
- {% if tags %}
- <ul class="list-inline tags">
- {% trans "Tags" %}:
- {% spaceless %}
- {% for tag in tags %}
- <li><a href="{% url "blog_post_list_tag" tag.slug %}" class="tag">{{ tag }}</a>{% if not forloop.last %}, {% endif %}</li>
- {% endfor %}
- {% endspaceless %}
- </ul>
- {% endif %}
- <p>
- <a href="{{ blog_post.get_absolute_url }}">{% trans "read more" %}</a>
- {% if blog_post.allow_comments %}
- /
- {% if settings.COMMENTS_DISQUS_SHORTNAME %}
- <a href="{{ blog_post.get_absolute_url }}#disqus_thread"
- data-disqus-identifier="{% disqus_id_for blog_post %}">
- {% trans "Comments" %}
- </a>
- {% else %}
- <a href="{{ blog_post.get_absolute_url }}#comments">
- {% blocktrans count comments_count=blog_post.comments_count %}{{ comments_count }} comment{% plural %}{{ comments_count }} comments{% endblocktrans %}
- </a>
- {% endif %}
- {% endif %}
- </p>
-</div>
-{% endblock %}
-{% endfor %}
-
-{% pagination_for blog_posts %}
-
-{% if settings.COMMENTS_DISQUS_SHORTNAME %}
-{% include "generic/includes/disqus_counts.html" %}
-{% endif %}
-
-{% endblock %}
-
-{% block right_panel %}
-{% include "blog/includes/filter_panel.html" %}
-{% endblock %}
+++ /dev/null
-{% load blog_tags keyword_tags mezzanine_tags i18n %}
-
-{% block blog_recent_posts %}
-{% blog_recent_posts 5 as recent_posts %}
-{% if recent_posts %}
-<h3>{% trans "Recent Posts" %}</h3>
-<ul class="list-unstyled recent-posts">
-{% for recent_post in recent_posts %}
-<li>
- {% spaceless %}
- <a href="{{ recent_post.get_absolute_url }}">
- {% if settings.BLOG_USE_FEATURED_IMAGE and recent_post.featured_image %}
- <img src="{{ MEDIA_URL }}{% thumbnail recent_post.featured_image 24 24 %}">
- {% endif %}
- {{ recent_post.title }}
- </a>
- {% endspaceless %}
-</li>
-{% endfor %}
-</ul>
-{% endif %}
-{% endblock %}
-
-{% block blog_months %}
-{% blog_months as months %}
-{% if months %}
-<h3>{% trans "Archive" %}</h3>
-{% for month in months %}
- {% ifchanged month.date.year %}
- {% if not forloop.first %}</ul>{% endif %}
- <h6>{{ month.date.year }}</h6><ul class="list-unstyled">
- {% endifchanged %}
- <li><a href="{% url "blog_post_list_month" year=month.date.year month=month.date.month %}"
- >{{ month.date|date:"F" }}</a> ({{ month.post_count }})</li>
-{% endfor %}
-</ul>
-{% endif %}
-{% endblock %}
-
-{% block blog_categories %}
-{% blog_categories as categories %}
-{% if categories %}
-<h3>{% trans "Categories" %}</h3>
-<ul class="list-unstyled">
-{% for category in categories %}
-<li><a href="{% url "blog_post_list_category" category.slug %}"
- >{{ category }}</a> ({{ category.post_count }})</li>
-{% endfor %}
-</ul>
-{% endif %}
-{% endblock %}
-
-{% block blog_keywords %}
-{% keywords_for blog.blogpost as tags %}
-{% if tags %}
-<h3>{% trans "Tags" %}</h3>
-<ul class="list-inline tag-cloud">
-{% for tag in tags %}
-<li>
- <a href="{% url "blog_post_list_tag" tag.slug %}"
- class="tag-weight-{{ tag.weight }}">{{ tag }}</a>
- ({{ tag.item_count }})
-</li>
-{% endfor %}
-</ul>
-{% endif %}
-{% endblock %}
-
-{% block blog_authors %}
-{% blog_authors as authors %}
-{% if authors %}
-<h3>{% trans "Authors" %}</h3>
-<ul class="list-unstyled">
-{% for author in authors %}
- <li><a href="{% url "blog_post_list_author" author.username %}"
- >{{ author.get_full_name|default:author.username }}</a>
- ({{ author.post_count }})</li>
-{% endfor %}
-</ul>
-{% endif %}
-{% endblock %}
-
-{% block blog_feeds %}
-<h3>{% trans "Feeds" %}</h3>
-{% if tag %}
- <a href="{% url "blog_post_feed_tag" tag.slug "rss" %}">{% trans "RSS" %}</a> /
- <a href="{% url "blog_post_feed_tag" tag.slug "atom" %}">{% trans "Atom" %}</a>
-{% endif %}
-{% if category %}
- <a href="{% url "blog_post_feed_category" category.slug "rss" %}">{% trans "RSS" %}</a> /
- <a href="{% url "blog_post_feed_category" category.slug "atom" %}">{% trans "Atom" %}</a>
-{% endif %}
-{% if author %}
- <a href="{% url "blog_post_feed_author" author.username "rss" %}">{% trans "RSS" %}</a> /
- <a href="{% url "blog_post_feed_author" author.username "atom" %}">{% trans "Atom" %}</a>
-{% endif %}
-{% if not tag and not category and not author %}
- <a href="{% url "blog_post_feed" "rss" %}">{% trans "RSS" %}</a> /
- <a href="{% url "blog_post_feed" "atom" %}">{% trans "Atom" %}</a>
-{% endif %}
-{% endblock %}
+++ /dev/null
-{% load i18n %}
-{% get_current_language_bidi as LANGUAGE_BIDI %}
-
-{% block main %}
-{% endblock %}
+++ /dev/null
-{% block main %}{% endblock %}
-
-http://{{ request.get_host }}
+++ /dev/null
-{% extends "email/base.html" %}
-{% load i18n %}
-
-
-{% block main %}
-
-{% if not LANGUAGE_BIDI %}
- {% include "email/receipt.html" %}
-{% else %}
- {% include "email/receipt_rtl.html" %}
-{% endif %}
-
-{% endblock %}
+++ /dev/null
-{% extends "email/base.txt" %}
-{% load shop_tags i18n %}
-
-{% block main %}
-{% trans "Dear" %} {{ order.billing_detail_first_name }},
-
-{% trans "Your order has been successful, details are below." %}
-
-{% trans "Order ID:" %} #{{ order.id }}
-
-{% trans "Billing Details:" %}
-{% for field, value in order_billing_detail_fields %}
-{{ field }}: {{ value }}
-{% endfor %}
-
-{% trans "Shipping Details:" %}
-{% for field, value in order_shipping_detail_fields %}
-{{ field }}: {{ value }}
-{% endfor %}
-
-{% trans "Items Ordered:" %}
-{% for item in order_items %}
-{{ item.quantity }} x {{ item.description }} {{ item.unit_price|currency }} {% trans "each" %}
-{% endfor %}
-
-{% order_totals_text %}
-{% endblock %}
+++ /dev/null
-{% load shop_tags i18n %}
-
-<p>{% trans "Dear" %} {{ order.billing_detail_first_name }},</p>
-<p>{% trans "Your order has been successful, details are below." %}</p>
-{% include "shop/includes/order_details.html" %}
-
+++ /dev/null
-{% load shop_tags i18n %}
-
-<p align="right">,{% trans "Dear" %} {{ order.billing_detail_first_name }}</p>
-<p align="right">{% trans "Your order has been successful, details are below." %}</p>
-{% include "shop/includes/order_details_rtl.html" %}
-
+++ /dev/null
-{% extends "base.html" %}
-
-{% load i18n %}
-
-{% block meta_title %}
-{% trans "Page not found" %}
-{% endblock %}
-
-{% block title %}
-{% trans "Page not found" %}
-{% endblock %}
-
-{% block main %}
-<div class="panel panel-danger">
- <div class="panel-heading"><h3 class="panel-title">{% trans "Page not found" %}</h3></div>
- <div class="panel-body">{% trans "The page you requested does not exist." %}</div>
-</div>
-{% endblock %}
+++ /dev/null
-{% extends "base.html" %}
-
-{% load i18n %}
-
-{% block meta_title %}
-{% trans "Error" %}
-{% endblock %}
-
-{% block title %}
-{% trans "Error" %}
-{% endblock %}
-
-{% block main %}
-<div class="panel panel-danger">
- <div class="panel-heading"><h3 class="panel-title">{% trans "Error" %}</h3></div>
- <div class="panel-body">{% trans "Sorry, an error occurred." %}</div>
-</div>
-{% endblock %}
+++ /dev/null
-{% load i18n %}
-
-{# Edit form #}
-<form style="display:none;" class="editable-form" method="post"
- action="{% url "edit" %}" id="{{ editable_form.uuid }}"
- {% if editable_form.is_multipart %} enctype="multipart/form-data"{% endif %}>
- {% csrf_token %}
- {% for field in editable_form %}
- <p{% if field.is_hidden %} style="display:none;"{% endif %}>
- {{ field.label_tag }}<br />{{ field }}{{ field.errors }}
- {% if field.help_text %}
- <span class="helptext">{{ field.help_text }}</span>
- {% endif %}
- </p>
- {% endfor %}
- <input type="submit" value="{% trans "Save" %}" class="btn btn-primary btn-lg">
- <input type="button" value="{% trans "Cancel" %}" class="btn btn-default btn-lg">
-</form>
-
-{# Original content wrapped in span #}
-<div class="editable-original">{{ original }}</div>
-
-{# Edit link #}
-<a style="visibility:hidden;" class="editable-link" href="#"
- rel="#{{ editable_form.uuid }}">{% trans "Edit" %}</a>
-
-{# Edit highlight #}
-<div style="visibility:hidden;" class="editable-highlight"></div>
+++ /dev/null
-{% load i18n staticfiles %}
-
-{% if has_site_permission %}
-<link rel="stylesheet" href="{% static "mezzanine/css/editable.css" %}">
-{{ richtext_media|safe }}
-<script>
-{% url "fb_browse" as fb_browse_url %}
-{% url "static_proxy" as static_proxy_url %}
-{% get_current_language as LANGUAGE_CODE %}
-window.__filebrowser_url = '{{ fb_browse_url }}';
-window.__toolbar_html = '{{ toolbar|escapejs }}';
-window.__static_proxy = '{{ static_proxy_url }}';
-window.__language_code = '{{ LANGUAGE_CODE }}';
-window.__tinymce_css = '{% static "mezzanine/css/tinymce.css" %}';
-</script>
-<script src="{% static "mezzanine/js/jquery.tools.toolbox.expose.js" %}"></script>
-<script src="{% static "mezzanine/js/jquery.tools.overlay.js" %}"></script>
-<script src="{% static "mezzanine/js/jquery.form.js" %}"></script>
-<script src="{% static "mezzanine/js/editable.js" %}"></script>
-{% endif %}
+++ /dev/null
-{% load i18n staticfiles %}
-
-<div id="editable-toolbar" method="POST" action="{% url "admin:logout" %}">
- {% url "admin:index" as admin_index_url %}
- {% url "admin:logout" as admin_logout_url %}
- {% url "logout" as accounts_logout_url %}
- <a id="editable-toolbar-toggle" href="#"></a>
- <a href="{{ editable_obj.get_admin_url|default:admin_index_url }}">{% trans "Admin" %}</a>
- <a href="{{ accounts_logout_url|default:admin_logout_url }}?{{ REDIRECT_FIELD_NAME }}={{ request.path }}">{% trans "Log out" %}</a>
-</div>
-
-<img id="editable-loading" src="{% static "mezzanine/img/loadingAnimation.gif" %}">
-
+++ /dev/null
-{% load mezzanine_tags %}
-
-{% editable_loader %}
-
-<script>
-{% if settings.GOOGLE_ANALYTICS_ID and not request.user.is_staff %}
-var _gaq = _gaq || [['_trackPageview']];
-_gaq.unshift(['_setAccount', '{{ settings.GOOGLE_ANALYTICS_ID }}']);
-(function(d, t) {
- var g = d.createElement(t),
- s = d.getElementsByTagName(t)[0];
- g.async = true;
- g.src = '//www.google-analytics.com/ga.js';
- s.parentNode.insertBefore(g, s);
-})(document, 'script');
-{% endif %}
-</script>
+++ /dev/null
-{% load i18n %}
-
-{% if form.non_field_errors or form.errors %}
-<div class="form-errors">
- {% for error in form.non_field_errors %}
- <div class="alert alert-danger non-field-error">{{ error }}</div>
- {% empty %}
- <div class="alert alert-danger field-error">{% trans "Please correct the errors below." %}</div>
- {% endfor %}
-</div>
-{% endif %}
+++ /dev/null
-{% load mezzanine_tags %}
-
-{% nevercache %}
-<input type="hidden" name="referrer" value="{{ request.META.HTTP_REFERER }}">
-{% csrf_token %}
-{% endnevercache %}
-
-{% for field in form_for_fields %}
-{% if field.is_hidden %}
-{{ field }}
-{% else %}
-<div class="form-group input_{{ field.id_for_label }} {{ field.field.type }}
- {% if field.errors %} has-error{% endif %}">
- {% if field.label %}<label class="control-label" for="{{ field.auto_id }}">{{ field.label }}</label>{% endif %}
- {{ field }}
- {% if field.errors %}
- <p class="help-block">
- {% for e in field.errors %}
- {% if not forloop.first %} / {% endif %}{{ e }}
- {% endfor %}
- </p>
- {% elif field.help_text %}
- <p class="help-block">{{ field.help_text }}</p>
- {% endif %}
-</div>
-{% endif %}
-{% endfor %}
+++ /dev/null
-{% load i18n %}
-{% get_language_info_list for LANGUAGES as languages %}
-{% if settings.USE_MODELTRANSLATION and languages|length > 1 %}
-{# hide submit button if browser has javascript support and can react to onchange event #}
-<script>$(document).ready(function(){$('#language_selector_form').change(function(){this.submit();});$('#language_selector_form input').hide();});</script>
-<div>
-<form action="{% url "set_language" %}" method="post" id="language_selector_form">
- {% csrf_token %}
- <div class="form-group">
- <select name="language" class="form-control">
- {% for language in languages %}
- <option value="{{ language.code }}"
- {% if language.code == LANGUAGE_CODE %}selected="selected"{% endif %}>
- {{ language.name_local }}
- </option>
- {% endfor %}
- </select>
- </div>
- <input type="submit" class="btn btn-default" value="{% trans "Change" %}" />
-</form>
-</div>
-{% endif %}
+++ /dev/null
-{% load i18n %}
-
-{% if current_page.has_previous or current_page.has_next %}
-<ul class="pagination">
-
-<li class="page-info">
- <span>{% trans "Page" %} {{ current_page.number }} {% trans "of" %} {{ current_page.paginator.num_pages }}</span>
-</li>
-<li class="prev previous{% if not current_page.has_previous %} disabled{% endif %}">
- <a{% if current_page.has_previous %} href="?{{ page_var }}={{ current_page.previous_page_number }}{% if querystring %}&{{ querystring }}{% endif %}"{% endif %}>←</a>
-</li>
-{% for page in current_page.visible_page_range %}
-<li{% if page == current_page.number %} class="active"{% endif %}>
- <a href="?{{ page_var }}={{ page }}{% if querystring %}&{{ querystring }}{% endif %}">{{ page }}</a>
-</li>
-{% endfor %}
-<li class="next{% if not current_page.has_next %} disabled{% endif %}">
- <a{% if current_page.has_next %} href="?{{ page_var }}={{ current_page.next_page_number }}{% if querystring %}&{{ querystring }}{% endif %}"{% endif %}>→</a>
-</li>
-
-</ul>
-{% endif %}
+++ /dev/null
-{% load mezzanine_tags i18n %}
-<form action="{% url "search" %}" class="navbar-form navbar-right" role="search">
-
-<div class="form-group">
- <input class="form-control" placeholder="{% trans "Search" %}" type="text" name="q" value="{{ request.REQUEST.q }}">
-</div>
-
-{% if search_model_choices %}
- {% if search_model_choices|length == 1 %}
- <input type="hidden" name="type" value="{{ search_model_choices.0.1 }}">
- {% else %}
- <div class="form-group">
- <select class="form-control" name="type">
- <option value="">{% trans "Everything" %}</option>
- {% for verbose_name, model in search_model_choices %}
- <option value="{{ model }}"
- {% if model == request.REQUEST.type %}selected{% endif %}>
- {{ verbose_name }}
- </option>
- {% endfor %}
- </select>
- </div>
- {% endif %}
-{% endif %}
-
-<input type="submit" class="btn btn-default" value="{% trans "Go" %}">
-
-</form>
+++ /dev/null
-{% load mezzanine_tags %}
-<div class="panel panel-default user-panel">
-<div class="panel-body">
-{% ifinstalled cartridge.shop %}
-{% include "shop/includes/user_panel.html" %}
-{% endifinstalled %}
-{% ifinstalled mezzanine.accounts %}
-{% ifinstalled cartridge.shop %}<br>{% endifinstalled %}
-{% include "accounts/includes/user_panel.html" %}
-{% endifinstalled %}
-</div>
-</div>
+++ /dev/null
-{% load mezzanine_tags %}
-<div class="">
-{% ifinstalled cartridge.shop %}
-{% include "shop/includes/user_panel_header.html" %}
-{% endifinstalled %}
-{% ifinstalled mezzanine.accounts %}
-{% ifinstalled cartridge.shop %}<br>{% endifinstalled %}
-{% include "accounts/includes/user_panel.html" %}
-{% endifinstalled %}
-</div>
+++ /dev/null
-{% extends "base.html" %}
-{% load i18n %}
-{% load blog_tags records_tags keyword_tags i18n mezzanine_tags %}
-
-{% block meta_title %}{% trans "Home" %}{% endblock %}
-{% comment %}
-{% block title %}{% trans "Home" %}{% endblock %}
-{% endcomment %}
-
-{% block breadcrumb_menu %}
-<li class="active">{% trans "Home" %}</li>
-{% endblock %}
-
-{% block main %}
-
-<div class="col-xs-6 col-md-6"><!-- Showcase-->
-{% shop_recent_products limit=2 category="Showcase" as recent_products %}
-{% if recent_products %}
-<h2><span class="bg-white">{% trans "Featured" %}</span></h2>
-<div class="row">
- {% for product in recent_products %}
- <div class="col-xs-12 col-md-12 product-thumb ">
- <a href="{{ product.get_absolute_url }}" class="thumbnail">
- {% if product.image %}
- <img src="{{ MEDIA_URL }}{% thumbnail product.image 512 512 %}">
- {% else %}
- <div class="placeholder"></div>
- {% endif %}
- <div class="caption">
- <h6>{{ product }}</h6>
- {% with product.variations.all as variations %}
- {% include "shop/includes/price.html" %}
- {% endwith %}
- </div>
- </a>
- </div>
-{% endfor %}
-</div>
-{% endif %}
-
-</div><!-- /Showcase -->
-
-<div class="col-xs-6 col-md-6"><!-- Latest Releases -->
-{% shop_recent_products 9 as recent_products %}
-{% if recent_products %}
-<h2><span class="bg-white">{% trans "Latest Releases" %}</span></h2>
-<div class="row">
- {% for product in recent_products %}
- <div class="col-xs-4 col-md-4 product-thumb slim_margins">
- <a href="{{ product.get_absolute_url }}" class="thumbnail">
- {% if product.image %}
- <img src="{{ MEDIA_URL }}{% thumbnail product.image 148 148 %}">
- {% else %}
- <div class="placeholder"></div>
- {% endif %}
- <div class="caption">
- <h6>{{ product.record }}</h6>
- </div>
- </a>
- </div>
-{% endfor %}
-</div>
-{% endif %}
-</div><!-- /Latest Releases -->
-
-<div><!-- Recent Posts -->
-{% blog_recent_posts 5 as recent_posts %}
-{% if recent_posts %}
-<h2>{% trans "Recent Posts" %}</h2>
-{% for recent_post in recent_posts %}
-{% if settings.BLOG_USE_FEATURED_IMAGE and recent_post.featured_image %}
- {% block recent_post_list_post_featured_image %}
- <a href="{{ recent_post.get_absolute_url }}">
- <img class="img-thumbnail pull-left" src="{{ MEDIA_URL }}{% thumbnail recent_post.featured_image 90 90 %}">
- </a>
- {% endblock %}
- {% endif %}
-<h3><a href="{{ recent_post.get_absolute_url }}"
- >{{ recent_post.title }}</a></h3>
-
- <h4>{{ recent_post.publish_date|timesince }} {% trans "ago" %}</h4>
-<div class="recent-summary">
-{{ recent_post.description_from_content|safe }}
-
- <a href="{{ recent_post.get_absolute_url }}" class="btn btn-info btn-mini">{% trans "read more" %}</a>
- <hr>
- {% if recent_post.categories %}
- {{ recent_post.categories. }}
- {% endif %}
-
-</div><!-- /recent-summary -->
-{% endfor %}
-{% endif %}
-
-</div><!-- /Recent Posts -->
-
-
-{% endblock %}
+++ /dev/null
-{% extends "pages/page.html" %}
-
-{% load mezzanine_tags shop_tags i18n %}
-{% block body_id %}category{% endblock %}
-
-{% block main %}{{ block.super }}
-
-{% editable page.category.content %}
-{{ page.category.content|safe }}
-{% endeditable %}
-
-{% if child_categories %}
-<div class="row shop-category-list">
-{% if settings.SHOP_CATEGORY_USE_FEATURED_IMAGE %}
- {% for category in child_categories %}
- <div class="col-xs-6 col-sm-4 col-lg-3">
- <a href="{{ category.get_absolute_url }}" class="thumbnail">
- {% if category.featured_image %}
- <img src="{{ MEDIA_URL }}{% thumbnail category.featured_image 148 148 %}" />
- {% else %}
- <div class="placeholder"></div>
- {% endif %}
- <div class="caption">
- <h4>{{ category.title }}</h4>
- </div>
- </a>
- </div>
- {% endfor %}
-{% else %}
- {% for category in child_categories %}
- <div class="col-xs-6 col-sm-4 col-lg-3">
- <a href="{{ category.get_absolute_url }}" class="thumbnail">
- <div class="caption"><h4>{{ category.title }}</h4></div>
- </a>
- </div>
- {% endfor %}
-{% endif %}
-</div>
-{% endif %}
-
-{% if products.paginator.count != 0 %}
-
-<form class="product-sorting" role="form">
- <div class="form-group">
- <label class="control-label" for="sorting-select">{% trans "Sort by" %}</label>
- <select onchange="location.href = this[this.selectedIndex].value;" class="form-control" id="sorting-select">
- {% for name, option in settings.SHOP_PRODUCT_SORT_OPTIONS %}
- {% if "rating" not in option or settings.SHOP_USE_RATINGS %}
- <option{% if option == products.sort_by %} selected{% endif %}
- value="{{ category.get_absolute_url }}?sort={{ option }}{{ querystring }}">
- {{ name }}
- </option>
- {% endif %}
- {% endfor %}
- </select>
- </div>
-</form>
-
-<div class="row product-list">
-{% for product in products.object_list %}
- <div class="col-xs-6 col-sm-4 col-lg-3 product-thumb slim_margins">
- <a href="{{ product.get_absolute_url }}" class="thumbnail">
- {% if product.image %}
- <img src="{{ MEDIA_URL }}{% thumbnail product.image 148 148 %}">
- {% else %}
- <div class="placeholder"></div>
- {% endif %}
- <div class="caption">
- <h6>{{ product }}</h6>
- <div class="price-info">
- {% if product.has_price %}
- {% if product.on_sale %}
- <span class="old-price">{{ product.unit_price|currency }}</span>
- {% trans "On sale:" %}
- {% endif %}
- <span class="price">{{ product.price|currency }}</span>
- {% else %}
- <span class="coming-soon">{% trans "Coming soon" %}</span>
- {% endif %}
- </div>
- </div>
- </a>
- </div>
-{% endfor %}
-</div>
-
-{% pagination_for products %}
-
-{% endif %}
-
-{% endblock %}
+++ /dev/null
-{% extends "pages/richtextpage.html" %}
-
-{% block main %}
-<!--
-This template is provided as a custom template for the homepage, for
-when it is configured as an editable page in the navigation tree. Feel
-free to modify it.
--->
-{{ block.super }}
-{% endblock %}
+++ /dev/null
-{% load pages_tags i18n staticfiles %}
-
-<ol>
- {% for page in page_branch %}
- <li id="ordering_{{ page.id }}">
- <div class="{% cycle 'row1' 'row2' %}">
- <a href="#" class="tree-toggle" id="page-{{ page.id }}"
- {% if not page.has_children %}style="visibility:hidden;"{% endif %}>
- <span class="icon open">+</span>
- <span class="icon close">-</span>
- </a>
- {% set_page_permissions page %}
- {% if page.perms.delete %}
- <a href="{% url "admin:pages_page_delete" page.id %}?fromtree" class="delete"></a>
- {% else %}
- <span class="delete" style="background:none;"></span>
- {% endif %}
- {% if page.perms.change %}
- <a href="{% url "admin:pages_page_change" page.id %}{% if not page.is_primary %}?parent={{ page.parent_id }}{% endif %}"
- class="changelink">{{ page.title.strip|default:" " }}</a>
- {% else %}
- <span class="uneditable">{{ page.title }}</span>
- {% endif %}
- <span class="ordering"{% if not page.perms.change %}
- style="visibility:hidden;"{% endif %}>
- <img src="{% static settings.MEZZANINE_ADMIN_PREFIX|add:"img/admin/arrow-up.gif" %}">
- <img src="{% static settings.MEZZANINE_ADMIN_PREFIX|add:"img/admin/arrow-down.gif" %}">
- </span>
- {% if page.perms.add %}
- <select class="addlist" id="addlink-{{ page.id }}">
- <option value="">{% trans "Add" %} ...</option>
- {% for model in page_models %}
- {% if model.perms.add %}
- <option value="{{ model.add_url }}?parent={{ page.id }}"
- >{{ model.meta_verbose_name|capfirst }}</option>
- {% endif %}
- {% endfor %}
- </select>
- {% endif %}
-
- </div>
- <br style="clear:both;">
- {% if page.has_children %}{% page_menu page %}{% endif %}
- </li>
- {% endfor %}
-</ol>
+++ /dev/null
-{% load i18n pages_tags %}
-
-{% if on_home %}
-<li>{% trans "Home" %}</li>
-{% else %}
-{% for page in page_branch %}
-
- {% if not has_home and page.is_primary and forloop.first %}
- <li id="breadcrumb-menu-home">
- <a href="{% url "home" %}">{% trans "Home" %}</a>
- </li>
- {% endif %}
-
- {% if page.is_current_or_ascendant %}
- {% if page.is_current %}
- <li id="breadcrumb-menu-{{ page.html_id }}"
- class="active">{{ page.title }}</li>
- {% else %}
- <li id="breadcrumb-menu-{{ page.html_id }}">
- <a href="{{ page.get_absolute_url }}">{{ page.title }}</a>
- </li>
- {% endif %}
- {% if page.has_children %}{% page_menu page %}{% endif %}
- {% endif %}
-
-{% endfor %}
-{% endif %}
+++ /dev/null
-{% load i18n pages_tags %}
-{% spaceless %}
-{% if page_branch_in_menu %}
-
-{% if branch_level == 0 %}
-<ul class="nav navbar-nav">
- {% for page in page_branch %}
- {% if not has_home and page.is_primary and forloop.first %}
- <li{% if on_home %} class="active"{% endif %} id="dropdown-menu-home">
- <a href="{% url "home" %}">{% trans "Home" %}</a>
- </li>
- {% endif %}
- {% if page.in_menu %}
- <li class="{% if page.has_children_in_menu %}dropdown{% endif %}
- {% if page.is_current_or_ascendant %}active{% endif %}"
- id="{{ page.html_id }}">
- <a href="{{ page.get_absolute_url }}"
- {% if page.has_children_in_menu %}
- class="dropdown-toggle disabled" data-toggle="dropdown"
- {% endif %}>
- {{ page.title }}
- {% if page.has_children_in_menu %}<b class="caret"></b>{% endif %}
- </a>
- {% if page.has_children_in_menu %}{% page_menu page %}{% endif %}
- </li>
- {% endif %}
- {% endfor %}
-</ul>
-
-{% else %}
-<ul class="dropdown-menu">
- {% for page in page_branch %}
- {% if page.in_menu %}
- <li class="{% if page.has_children_in_menu %}dropdown-submenu{% endif %}
- {% if page.is_current_or_ascendant %}active{% endif %}"
- id="{{ page.html_id }}">
- <a href="{{ page.get_absolute_url }}">{{ page.title }}</a>
- {% if page.has_children_in_menu %}{% page_menu page %}{% endif %}
- </li>
- {% endif %}
- {% endfor %}
-</ul>
-{% endif %}
-
-{% endif %}
-{% endspaceless %}
+++ /dev/null
-{% load i18n pages_tags %}
-
-{% spaceless %}
-{% if page_branch_in_menu %}
-
-{% for page in page_branch %}
- {% if page.is_primary %}
- {% if forloop.first %}
- <div class="nav-footer">
- {% endif %}
- {% if page.in_menu %}
- <ul class="list-unstyled">
- {% endif %}
- {% endif %}
-
- {% if page.in_menu %}
- {% if forloop.first and not page.parent.in_menu and not page.is_primary %}
- <ul class="list-unstyled">
- {% endif %}
- <li {% if page.is_current_or_ascendant %}class="active"{% endif %}
- id="footer-menu-{{ page.html_id }}">
- <a href="{{ page.get_absolute_url }}">{{ page.title }}</a></li>
- {% endif %}
-
- {% if page.in_menu and page.has_children_in_menu %}{% page_menu page %}{% endif %}
-
- {% if page.in_menu %}
- {% if forloop.first and not page.parent.in_menu and not page.is_primary %}
- </li></ul>
- {% endif %}
- {% endif %}
-
- {% if page.is_primary %}
- {% if page.in_menu %}
- </ul>
- {% endif %}
- {% if forloop.last %}
- </div>
- {% endif %}
- {% endif %}
-
-{% endfor %}
-
-{% endif %}
-{% endspaceless %}
+++ /dev/null
-{% load i18n pages_tags %}
-
-{% spaceless %}
-{% if page_branch_in_menu %}
-<ul class="footer-tree-menu-level-{{ branch_level }}">
- {% for page in page_branch %}
-
- {% if not has_home and page.is_primary and forloop.first %}
- <li class="first{% if on_home %} active{% endif %}"
- id="footer-tree-menu-home">
- <a href="{% url "home" %}">{% trans "Home" %}</a>
- </li>
- {% endif %}
-
- {% if page.in_menu %}
- <li class="{% if page.is_current_or_ascendant %}active{% endif %}
- {% if not top_level and forloop.first %} first{% endif %}
- {% if forloop.last %} last{% endif %}"
- id="footer-tree-menu-{{ page.html_id }}">
- <a href="{{ page.get_absolute_url }}">{{ page.title }}</a>
- {# remove this if tag to always show all nav items #}
- {% if page.is_current_or_ascendant and page.has_children_in_menu %}
- {% page_menu page %}
- {% endif %}
- </li>
- {% endif %}
-
- {% endfor %}
-</ul>
-{% endif %}
-{% endspaceless %}
+++ /dev/null
-{% load i18n pages_tags %}
-
-{% spaceless %}
-{% if page_branch %}
-{% for page in page_branch %}
-
- {% if not has_home and page.is_primary and forloop.first %}
- <ul class="mobile-menu">
- <li><a class="home" href="{% url "home" %}"
- id="tree-menu-home">{% trans "Home" %}</a></li>
- {% endif %}
-
- {% if page.is_current_or_ascendant and not page.is_current_child %}
- {% if page.has_children_in_menu %}{% page_menu page %}{% endif %}
- {% endif %}
-
- {% if page.is_current_child %}
- <li class="
- {% if forloop.first %} first{% endif %}
- {% if forloop.last %} last{% endif %}"
- id="mobile-menu-{{ page.html_id }}">
- <a href="{{ page.get_absolute_url }}">{{ page.title }}</a>
- </li>
- {% endif %}
-
- {% if page.is_primary and forloop.last %}
- </ul>
- {% endif %}
-
-{% endfor %}
-{% endif %}
-{% endspaceless %}
+++ /dev/null
-{% load pages_tags i18n %}
-
-{% spaceless %}
-<ul id="primary-menu" class="nav pull-right">
- {% for page in page_branch %}
- {% if not has_home and page.is_primary and forloop.first %}
- <li id="primary-menu-home" class="first{% if on_home %} active{% endif %}">
- <a href="{% url "home" %}">{% trans "Home" %}</a>
- </li>
- {% endif %}
- {% if page.in_menu %}
- <li id="primary-menu-{{ page.html_id }}"
- class="{% if page.is_current_or_ascendant %}active{% endif %}{% if forloop.last %} last{% endif %}">
- <a href="{{ page.get_absolute_url }}">{{ page.title }}</a>
- </li>
- {% endif %}
- {% endfor %}
- <li class="divider-vertical"></li>
-</ul>
-{% endspaceless %}
+++ /dev/null
-{% load i18n pages_tags %}
-
-{% spaceless %}
-{% if page_branch_in_menu %}
-<ul class="nav nav-list navlist-menu-level-{{ branch_level }}">
- {% for page in page_branch %}
- {% if not has_home and page.is_primary and forloop.first %}
- <li{% if on_home %} class="active"{% endif %} id="tree-menu-home">
- <a href="{% url "home" %}">{% trans "Home" %}</a>
- </li>
- {% endif %}
- {% if page.in_menu %}
- <li class="
- {% if page.is_current %} active{% endif %}
- {% if page.is_current_or_ascendant %} active-branch{% endif %}
- " id="tree-menu-{{ page.html_id }}">
- <a href="{{ page.get_absolute_url }}">{{ page.title }}</a>
- {# wrap the next line with 'if page.is_current_or_ascendant' #}
- {# to only show child pages in the menu for the current page #}
- {% if page.is_current_or_ascendant %}{% page_menu page %}{% endif %}
- </li>
- {% endif %}
- {% endfor %}
-</ul>
-{% endif %}
-{% endspaceless %}
+++ /dev/null
-{% extends "base.html" %}
-{% load mezzanine_tags keyword_tags %}
-
-{% block meta_title %}{{ page.meta_title }}{% endblock %}
-
-{% block meta_keywords %}{% metablock %}
-{% keywords_for page as keywords %}
-{% for keyword in keywords %}
- {% if not forloop.first %}, {% endif %}
- {{ keyword }}
-{% endfor %}
-{% endmetablock %}{% endblock %}
-
-{% block meta_description %}{% metablock %}
-{{ page.description }}
-{% endmetablock %}{% endblock %}
-
-{% block title %}
-{% editable page.title %}{{ page.title }}{% endeditable %}
-{% endblock %}
-
-{% block main %}
-{% endblock %}
+++ /dev/null
-{% extends "pages/page.html" %}
-
-{% load mezzanine_tags %}
-
-{% block main %}{{ block.super }}
-
-{% editable page.richtextpage.content %}
-{{ page.richtextpage.content|richtext_filters|safe }}
-{% endeditable %}
-
-{% endblock %}
+++ /dev/null
-{% extends "base.html" %}
-
-{% load i18n mezzanine_tags %}
-
-{% block meta_title %}{% trans "Search Results" %}{% endblock %}
-{% block title %}{% trans "Search Results" %}{% endblock %}
-{% block extra_head %}
-<meta name="robots" content="noindex">
-{% endblock %}
-
-{% block breadcrumb_menu %}
-<li>
- <a href="{% url "home" %}">{% trans "Home" %}</a>
-</li>
-<li class="active">{% trans "Search Results" %}</li>
-{% endblock %}
-
-{% block main %}
-
-<p>
-{% if results.paginator.count == 0 %}
-{% blocktrans %}
-No results were found in {{ search_type }} matching your query: {{ query }}
-{% endblocktrans %}
-{% else %}
-{% blocktrans with start=results.start_index end=results.end_index total=results.paginator.count %}
-Showing {{ start }} to {{ end }} of {{ total }} results in {{ search_type }} matching your query: {{ query }}
-{% endblocktrans %}
-{% endif %}
-</p>
-
-<div id="search-results">
-{% for result in results.object_list %}
-{% with result.get_absolute_url as result_url %}
- <h5>
- {{ forloop.counter0|add:results.start_index }})
- {% if result_url %}
- <a href="{{ result_url }}">{{ result }}</a>
- {% else %}
- {{ result }}
- {% endif %}
- </h5>
- {% if result.description != result|stringformat:"s" %}
- <p>{{ result.description|truncatewords_html:20|safe }}</p>
- {% endif %}
- {% if result_url %}
- <a href="{{ result_url }}">{% trans "read more" %}</a>
- {% endif %}
-{% endwith %}
-{% endfor %}
-</div>
-
-{% pagination_for results %}
-
-{% endblock %}
+++ /dev/null
-{% extends "base.html" %}
+++ /dev/null
-{% extends "shop/checkout.html" %}
-{% load staticfiles i18n mezzanine_tags %}
-
-{% block extra_head %}
-{{ block.super }}
-<script src="{% static "cartridge/js/shipping_fields.js" %}"></script>
-{% endblock %}
-
-{% block fields %}
-{% if request.cart.has_items %}
-{% if not request.user.is_authenticated %}
-{% ifinstalled mezzanine.accounts %}
-<p>
-{% url "login" as login_url %}
-{% url "signup" as signup_url %}
-{% with request.path as next %}
-{% blocktrans %}
-If you have an existing account or would like to create one, please
-<a href="{{ login_url }}?next={{ next }}">log in</a> or
-<a href="{{ signup_url }}?next={{ next }}">sign up</a>.
-{% endblocktrans %}
-{% endwith %}
-</p>
-{% endifinstalled %}
-{% endif %}
-
-{% errors_for form %}
-
-<fieldset>
- <legend>{% trans "Billing Details" %}</legend>
- {% fields_for form.billing_detail_fields %}
-</fieldset>
-
-<fieldset>
- <legend>{% trans "Delivery Details" %}</legend>
- {% fields_for form.same_billing_shipping_field %}
- <div id="shipping_fields">{% fields_for form.shipping_detail_fields %}</div>
- {% fields_for form.additional_instructions_field %}
- {% fields_for form.remember_field %}
-</fieldset>
-
-{% if not settings.SHOP_CHECKOUT_STEPS_SPLIT and settings.SHOP_PAYMENT_STEP_ENABLED %}
-{% include "shop/includes/payment_fields.html" %}
-{% endif %}
-
-{% fields_for form.other_fields %}
-
-{% endif %}
-{% endblock %}
+++ /dev/null
-{% extends "shop/base.html" %}
-{% load mezzanine_tags shop_tags i18n %}
-
-{% block meta_title %}{% trans "Your Cart" %}{% endblock %}
-{% block title %}{% trans "Your Cart" %}{% endblock %}
-{% block body_id %}cart{% endblock %}
-
-{% block breadcrumb_menu %}
-{{ block.super }}
-<li>{% trans "Your Cart" %}</li>
-{% endblock %}
-
-{% block main %}
-{% if cart_formset.forms %}
-<form method="post" class="cart-form">
-{% csrf_token %}
-{% if cart_formset.errors %}
-{% for error in cart_formset.errors %}
-{% if error.values.0 %}{{ error.values.0 }}{% endif %}
-{% endfor %}
-{% endif %}
-{{ cart_formset.management_form }}
-<table class="table table-striped">
- <thead>
- <tr>
- <th colspan="2" class="left">{% trans "Item" %}</th>
- <th>{% trans "Unit Price" %}</th>
- <th class="center">{% trans "Qty" %}</th>
- <th>{% trans "Price" %}</th>
- <th class="center">{% trans "Remove?" %}</th>
- </tr>
- </thead>
- <tbody>
- {% for form in cart_formset.forms %}
- {% with form.instance as item %}
- <tr>
- <td width="30">
- {{ form.id }}
- {% if item.image %}
- <a href="{{ item.get_absolute_url }}">
- <img alt="{{ item.description }}" src="{{ MEDIA_URL }}{% thumbnail item.image 30 30 %}">
- </a>
- {% endif %}
- </td>
- <td class="left">
- <a href="{{ item.get_absolute_url }}">{{ item.description }}</a>
- </td>
- <td>{{ item.unit_price|currency }}</td>
- <td class="quantity">{{ form.quantity }}</td>
- <td>{{ item.total_price|currency }}</td>
- <td class="center">{{ form.DELETE }}</td>
- </tr>
- {% endwith %}
- {% endfor %}
- <tr>
- <td colspan="5">{% order_totals %}</td>
- <td> </td>
- </tr>
- </tbody>
-</table>
-
-<div class="form-actions">
- <a href="{% url "shop_checkout" %}" class="btn btn-primary btn-lg pull-right">
- {% if request.session.order.step %}{% trans "Return to Checkout" %}{% else %}{% trans "Go to Checkout" %}{% endif %}
- </a>
- <input type="submit" name="update_cart" class="btn btn-default btn-lg pull-left" value="{% trans "Update Cart" %}">
-</div>
-</form>
-
-{% if discount_form %}
-<form method="post" class="discount-form col-md-12 text-right">
- {% fields_for discount_form %}
- <input type="submit" class="btn btn-default" value="{% trans "Apply" %}">
-</form>
-{% endif %}
-
-{% if settings.SHOP_USE_UPSELL_PRODUCTS %}
-{% with request.cart.upsell_products as upsell_products %}
-{% if upsell_products %}
-<h2>{% trans "You may also like:" %}</h2>
-<div class="row">
- {% for product in upsell_products %}
- <div class="col-xs-6 col-sm-4 col-md-3 product-thumb">
- <a class="thumbnail" href="{{ product.get_absolute_url }}">
- {% if product.image %}
- <img src="{{ MEDIA_URL }}{% thumbnail product.image 90 90 %}">
- {% endif %}
- <div class="caption">
- <h6>{{ product }}</h6>
- <div class="price-info">
- {% if product.has_price %}
- {% if product.on_sale %}
- <span class="old-price">{{ product.unit_price|currency }}</span>
- {% trans "On sale:" %}
- {% endif %}
- <span class="price">{{ product.price|currency }}</span>
- {% else %}
- <span class="coming-soon">{% trans "Coming soon" %}</span>
- {% endif %}
- </div>
- </div>
- </a>
- </div>
- {% endfor %}
-</div>
-{% endif %}
-{% endwith %}
-{% endif %}
-
-{% else %}
-<p>{% trans "Your Cart is empty." %}</p>
-{% endif %}
-{% endblock %}
+++ /dev/null
-{% extends "shop/base.html" %}
-{% load shop_tags mezzanine_tags i18n %}
-
-{% block meta_title %}{% trans "Checkout" %} - {{ step_title }}{% endblock %}
-{% block title %}{% trans "Checkout" %} - {% trans "Step" %} {{ step }} {% trans "of" %} {{ steps|length }}{% endblock %}
-{% block body_id %}checkout{% endblock %}
-
-{% block extra_head %}
-<script>
-var _gaq = [['_trackPageview', '{{ request.path }}{{ step_url }}/']];
-$(function() {$('.middle :input:visible:enabled:first').focus();});
-</script>
-{% endblock %}
-
-{% block breadcrumb_menu %}
-{% for step in steps %}
-<li>
- {% if step.title == step_title %}
- <strong>{{ step.title }}</strong>
- {% else %}
- {{ step.title }}
- {% endif %}
-</li>
-{% endfor %}
-<li>{% trans "Complete" %}</li>
-{% endblock %}
-
-{% block main %}
-
-{% block before-form %}{% endblock %}
-<div class="row">
-<form method="post" class="col-md-8 checkout-form">
- {% csrf_token %}
-
- {% block fields %}{% endblock %}
-
- {% block nav-buttons %}
- {% if request.cart.has_items %}
- <div class="form-actions">
- <input type="submit" class="btn btn-lg btn-primary pull-right" value="{% trans "Next" %}">
- {% if not CHECKOUT_STEP_FIRST %}
- <input type="submit" class="btn btn-lg btn-default pull-left" name="back" value="{% trans "Back" %}">
- {% endif %}
- </div>
- {% else %}
- <p>{% trans "Your cart is empty." %}</p>
- <p>{% trans "This may be due to your session timing out after a period of inactivity." %}</p>
- <p>{% trans "We apologize for the inconvenience." %}</p>
- <br>
- <p><a class="btn btn-lg btn-primary" href="{% url "page" "shop" %}">{% trans "Continue Shopping" %}</a></p>
- {% endif %}
- {% endblock %}
-
-</form>
-
-{% if request.cart.has_items %}
-<div class="col-md-4">
- <div class="panel panel-default checkout-panel">
- <div class="panel-body">
- <ul class="media-list">
- {% for item in request.cart %}
- <li class="media">
- {% if item.image %}
- <img class="pull-left" alt="{{ item.description }}" src="{{ MEDIA_URL }}{% thumbnail item.image 30 30 %}">
- {% endif %}
- <div class="media-body">
- {{ item.quantity }} x {{ item.description }}
- <span class="price">{{ item.total_price|currency }}</span>
- </div>
- </li>
- {% endfor %}
- </ul>
- {% order_totals %}
- <br style="clear:both;">
- <a class="btn btn-default" href="{% url "shop_cart" %}">{% trans "Edit Cart" %}</a>
- </div>
- </div>
-</div>
-{% endif %}
-
-{% block after-form %}{% endblock %}
-</div>
-{% endblock %}
+++ /dev/null
-{% extends "shop/base.html" %}
-{% load i18n %}
-
-{% block body_id %}complete{% endblock %}
-
-{% block meta_title %}{% trans "Order Complete" %}{% endblock %}
-
-{% block extra_head %}
-{{ block.super }}
-{% if settings.GOOGLE_ANALYTICS_ID %}
-<script>
-
-var decimal = function(amount) {
- if (amount.toString().indexOf('.') == -1) {
- amount += '.00';
- }
- return String(amount);
-};
-
-var _gaq = [['_trackPageview'], ['_addTrans',
- // order ID - required
- '{{ order.id }}',
- // affiliation or store name
- '',
- // total - required
- decimal({{ order.item_total }}{% if order.discount_total %} - {{ order.discount_total }}{% endif %}),
- // tax
- decimal({% if order.tax_total %}{{ order.tax_total }}{% else %}0{% endif %}),
- // shipping
- decimal({{ order.shipping_total }}),
- // city
- '{{ order.billing_detail_city|escapejs }}',
- // state or province
- '{{ order.billing_detail_state|escapejs }}',
- // country
- '{{ order.billing_detail_country|escapejs }}'
-]];
-
-{% for item in items %}
-_gaq.push(['_addItem',
- // order ID - required
- '{{ order.id }}',
- // SKU/code - required
- '{{ item.sku }}',
- // product name
- '{{ item.name|escapejs }}',
- // category or variation
- '{{ item.description|escapejs }}',
- // unit price - required
- decimal({{ item.unit_price }}),
- // quantity - required
- '{{ item.quantity }}'
-]);
-{% endfor %}
-
-// submits transaction to the Analytics servers
-_gaq.push(['_trackTrans']);
-
-</script>
-{% endif %}
-{% endblock %}
-
-{% block title %}{% trans "Order Complete" %}{% endblock %}
-
-{% block breadcrumb_menu %}
-{% for step in steps %}
-<li>{{ step.title }}</li>
-{% endfor %}
-<li><strong>{% trans "Complete" %}</strong></li>
-{% endblock %}
-
-
-{% block main %}
-<p>{% trans "Thank you for shopping with us, your order is complete." %}</p>
-<p>{% trans "We've sent you a receipt via email." %}</p>
-<p>{% trans "You can also view your invoice using one of the links below." %}</p>
-<br>
-<form class="order-complete-form" method="post" action="{% url "shop_invoice_resend" order.id %}?next={{ request.path }}">
- {% csrf_token %}
- {% if has_pdf %}
- <a class="btn btn-primary" href="{% url "shop_invoice" order.id %}?format=pdf">{% trans "Download PDF invoice" %}</a>
- {% endif %}
- <a class="btn btn-default" target="_blank" href="{% url "shop_invoice" order.id %}">{% trans "View invoice in your browser" %}</a>
- <input type="submit" class="btn btn-default" value="{% trans "Re-send order email" %}">
-</form>
-{% endblock %}
+++ /dev/null
-{% extends "shop/checkout.html" %}
-{% load i18n shop_tags %}
-
-{% block fields %}
-{% if request.cart.has_items %}
-
-<div class="confirmation col-md-6">
- <div class="panel panel-default">
- <div class="panel-body">
- <h3>{% trans "Billing Details" %}</h3>
- <ul class="list-unstyled">
-
- {% for field, value in form.billing_detail_fields.values %}
- <li><label>{{ field }}:</label> {{ value }}</li>
- {% endfor %}
-
- </ul>
- </div>
- </div>
-</div>
-
-<div class="confirmation col-md-6">
- <div class="panel panel-default">
- <div class="panel-body">
- <h3>{% trans "Shipping Details" %}</h3>
- <ul class="list-unstyled">
-
- {% for field, value in form.shipping_detail_fields.values %}
- <li><label>{{ field }}:</label> {{ value }}</li>
- {% endfor %}
-
- {% for field, value in form.additional_instructions_field.values %}
- <li><label>{{ field }}:</label> {{ value }}</li>
- {% endfor %}
-
- </ul>
- </div>
- </div>
-</div>
-{% if settings.SHOP_PAYMENT_STEP_ENABLED %}
-{% comment %}
-<br style="clear:both;">
-<div class="confirmation col-md-6">
- <div class="panel panel-default">
- <div class="panel-body">
- <h3>{% trans "Payment Details" %}</h3>
- <ul class="list-unstyled">
-
- {% for field, value in form.card_name_field.values %}
- <li><label>{{ field }}:</label> {{ value }}</li>
- {% endfor %}
-
- {% for field, value in form.card_type_field.values %}
- <li><label>{{ field }}:</label> {{ value }}</li>
- {% endfor %}
-
- <li>
- {% with form.card_expiry_fields.values as expiry_fields %}
- {% with expiry_fields.next as month_field %}
- <label>{{ month_field.0 }}:</label> {{ month_field.1 }}/{{ expiry_fields.next.1 }}
- {% endwith %}
- {% endwith %}
- </li>
-
- {% for field, value in form.card_fields.values %}
- <li><label>{{ field }}:</label> {{ value }}</li>
- {% endfor %}
-
- </ul>
- </div>
- </div>
-</div>
-{% endcomment %}
-{% endif %}
-<br style="clear:both;">
-
-{% for field in form %}{{ field }}{% endfor %}
-
-{% endif %}
-{% endblock %}
+++ /dev/null
-{% load shop_tags i18n %}
-
-<h1>{{ settings.SITE_TITLE }}</h1>
-
-<table width="100%" border="0">
- <tr>
- <td>{% trans "Order ID:" %} {{ order.id }}</td>
- <td align="right">{{ order.time }}</td>
- </tr>
-</table>
-
-<h2>{% trans "Your Details" %}</h2>
-<table width="100%" border="1" cellspacing="0" cellpadding="10">
-<tr>
- <th align="left" width="50%">{% trans "Billing Details" %}</th>
- <th align="left" width="50%">{% trans "Shipping Details" %}</th>
-</tr>
-<tr>
- <td valign="top">
- <table border="0">
- {% for field, value in order_billing_detail_fields %}
- <tr><td>{{ field }}: </td><td>{{ value }}</td></tr>
- {% endfor %}
- </table>
- </td>
- <td valign="top">
- <table border="0">
- {% for field, value in order_shipping_detail_fields %}
- <tr><td>{{ field }}: </td><td>{{ value }}</td></tr>
- {% endfor %}
- </table>
- </td>
-</tr>
-</table>
-
-<h2>{% trans "Items Ordered" %}</h2>
-<table width="100%" border="1" cellspacing="0" cellpadding="10">
- <tr>
- <th align="left">{% trans "Item" %}</th>
- <th align="right">{% trans "Unit Price" %}</th>
- <th align="right">{% trans "Qty" %}</th>
- <th align="right">{% trans "Price" %}</th>
- </tr>
- {% for item in order.items.all %}
- <tr>
- <td>{{ item.description }}</td>
- <td align="right" valign="top">{{ item.unit_price|currency }}</td>
- <td align="right" valign="top">{{ item.quantity }}</td>
- <td align="right" valign="top">{{ item.total_price|currency }}</td>
- </tr>
- {% endfor %}
- <tr>
- <td colspan="4" align="right">{% order_totals %}</td>
- </tr>
-</table>
+++ /dev/null
-{% load shop_tags i18n %}
-
-<h1 align="right">{{ settings.SITE_TITLE }}</h1>
-
-<table width="100%" border="0">
- <tr>
- <td align="left">{{ order.time }}</td>
- <td align="right">{% trans "Order ID:" %} {{ order.id }}</td>
- </tr>
-</table>
-
-<h2 align="right">{% trans "Your Details" %}</h2>
-<table width="100%" border="1" cellspacing="0" cellpadding="10">
-<tr>
- <th align="right" width="50%">{% trans "Billing Details" %}</th>
- <th align="right" width="50%">{% trans "Shipping Details" %}</th>
-</tr>
-<tr>
- <td valign="top" align="right">
- <table border="0">
- {% for field, value in order_billing_detail_fields %}
- <tr><td>{{ value }}</td><td> : {{ field }}</td></tr>
- {% endfor %}
- </table>
- </td>
- <td valign="top" align="right">
- <table border="0" align="right">
- {% for field, value in order_shipping_detail_fields %}
- <tr><td>{{ value }}</td><td> : {{ field }}</td></tr>
- {% endfor %}
- </table>
- </td>
-</tr>
-</table>
-
-<h2 align="right">{% trans "Items Ordered" %}</h2>
-<table width="100%" border="1" cellspacing="0" cellpadding="10">
- <tr>
-
-
-
- <th align="left">{% trans "Price" %}</th>
- <th align="left">{% trans "Qty" %}</th>
- <th align="left">{% trans "Unit Price" %}</th>
- <th align="right">{% trans "Item" %}</th>
- </tr>
- {% for item in order.items.all %}
- <tr>
- <td align="left" valign="top">{{ item.total_price|currency }}</td>
- <td align="left" valign="top">{{ item.quantity }}</td>
- <td align="left" valign="top">{{ item.unit_price|currency }}</td>
- <td align="right">{{ item.description }}</td>
-
-
-
- </tr>
- {% endfor %}
- <tr>
- <td colspan="4" align="left">{% order_totals %}</td>
- </tr>
-</table>
+++ /dev/null
-{% load shop_tags i18n %}
-<div class="order-totals">
- {% if discount_total or shipping_total %}
- <div><label>{% trans "Sub total" %}:</label> <span>{{ item_total|currency }}</span></div>
- {% endif %}
- {% if discount_total %}
- <div>
- <label>
- {% if discount_type %}
- {{ discount_type }}:
- {% else %}
- {% trans "Discount" %}:
- {% endif %}
- </label> <span>{{ discount_total|currency }}</span>
- </div>
- {% endif %}
- {% if shipping_type or shipping_total %}
- <div>
- <label>
- {% if shipping_type %}
- {{ shipping_type }}:
- {% else %}
- {% trans "Shipping" %}:
- {% endif %}
- </label> <span>{{ shipping_total|currency }}</span>
- </div>
- {% endif %}
- {% if tax_total %}
- <div>
- <label>
- {% if tax_type %}
- {{ tax_type }}:
- {% else %}
- {% trans "Tax" %}:
- {% endif %}
- </label> <span>{{ tax_total|currency }}</span>
- </div>
- {% endif %}
- <div class="total"><label>{% trans "Total" %}:</label> <span>{{ order_total|currency }}</span></div>
-</div>
+++ /dev/null
-{% load shop_tags i18n %}{% if discount_total or shipping_total %}
-{% trans "Sub total" %}: {{ item_total|currency }}
-{% endif %}{% if discount_total %}
-{% if discount_type %}{{ discount_type }}{% else %}{% trans "Discount" %}{% endif %}: {{ discount_total|currency }}
-{% endif %}{% if shipping_type or shipping_total %}
-{% if shipping_type %}{{ shipping_type }}{% else %}{% trans "Shipping" %}{% endif %}: {{ shipping_total|currency }}
-{% endif %} {% if tax_total %}
-{% if tax_type %}{{ tax_type }}{% else %}{% trans "Tax" %}{% endif %}: {{ tax_total|currency }}
-{% endif %}{% trans "Total" %}: {{ order_total|currency }}
-
-
+++ /dev/null
-{% load i18n mezzanine_tags multipayment_forms %}
-
-{% if PRIMARY_PAYMENT_PROCESSOR_IN_USE %}
- <fieldset>
- <legend>{% trans "Payment Details" %}</legend>
- {% fields_for form.card_name_field %}
- {% fields_for form.card_type_field %}
- {% with form.card_expiry_fields as card_expiry_fields %}
- <div class="control-group card-expiry-fields{% if card_expiry_fields.errors.card_expiry_year %} error{% endif %}">
- <label>{% trans "Card Expiry" %}</label>
- {% fields_for card_expiry_fields %}
- </div>
- {% endwith %}
- {% fields_for form.card_fields %}
- </fieldset>
-{% endif %}
+++ /dev/null
-{% load staticfiles mezzanine_tags shop_tags records_tags rating_tags i18n %}
-
-<ul id="variations" class="list-unstyled">
- {% for variation in variations %}
- <li id="variation-{{ variation.sku }}"
- {% if not variation.default %}style="display:none;"{% endif %}>
- {% if variation.has_price %}
- {% if variation.on_sale %}
- <span class="old-price">{{ variation.unit_price|currency }}</span>
- {% trans "On sale:" %}
- {% endif %}
- <span class="price">{% trans "Price" %}: {{ variation.price|currency }}</span>
- {% else %}
- {% if has_available_variations %}
- <span class="error-msg">
- {% trans "The selected options are currently unavailable." %}
- </span>
- {% endif %}
- {% endif %}
- </li>
- {% endfor %}
-</ul>
+++ /dev/null
-{% load i18n shop_tags mezzanine_tags %}
-{% spaceless %}
-<a href="{% url "shop_cart" %}">
-<span class="glyphicon glyphicon-shopping-cart"></span>
-{% blocktrans count request.cart.total_quantity as cart_quantity %}1 item{% plural %}{{ cart_quantity }} items{% endblocktrans %}
-{% trans "in cart" %}:
-{{ request.cart.total_price|currency }}</a><br>
-{% if request.cart.total_quantity != 0 %}
-<a href="{% url "shop_checkout" %}" class="btn btn-primary">
- {% if request.session.order.step %}{% trans "Return to Checkout" %}{% else %}{% trans "Go to Checkout" %}{% endif %}
-</a><br>
-{% endif %}
-{% if settings.SHOP_USE_WISHLIST %}
-<a href="{% url "shop_wishlist" %}" class="btn-wishlist">
-<span class="glyphicon glyphicon-star"></span>
-{% blocktrans count request.wishlist|length as wishlist_count %}Wishlist contains 1 item{% plural %} Wishlist contains {{ wishlist_count }} items{% endblocktrans %}</a>
-{% endif %}
-{% endspaceless %}
+++ /dev/null
-{% load i18n shop_tags mezzanine_tags %}
-{% spaceless %}
-<a href="{% url "shop_cart" %}">
-<span class="glyphicon glyphicon-shopping-cart"></span>
-{% blocktrans count request.cart.total_quantity as cart_quantity %}1 item{% plural %}{{ cart_quantity }} items{% endblocktrans %}
-{% trans "in cart" %}:
-{{ request.cart.total_price|currency }}</a><br>
-{% if request.cart.total_quantity != 0 %}
-<a href="{% url "shop_checkout" %}" class="btn btn-primary">
- {% if request.session.order.step %}{% trans "Return to Checkout" %}{% else %}{% trans "Go to Checkout" %}{% endif %}
-</a><br>
-{% endif %}
-{% if settings.SHOP_USE_WISHLIST %}
-<a href="{% url "shop_wishlist" %}" class="btn-wishlist">
-<span class="glyphicon glyphicon-star"></span>
-{% blocktrans count request.wishlist|length as wishlist_count %}Wishlist contains 1 item{% plural %} Wishlist contains {{ wishlist_count }} items{% endblocktrans %}</a>
-{% endif %}
-{% endspaceless %}
+++ /dev/null
-{% extends "shop/base.html" %}
-{% load mezzanine_tags shop_tags i18n %}
-
-{% block meta_title %}{% trans "Order History" %}{% endblock %}
-{% block title %}{% trans "Order History" %}{% endblock %}
-
-{% block breadcrumb_menu %}
-{{ block.super }}
-<li>{% trans "Order History" %}</li>
-{% endblock %}
-
-{% block main %}
-
-{% if orders %}
-
-<table class="table table-striped order-history">
- <thead>
- <th class="left">ID</th>
- <th class="left">{% trans "Date" %}</th>
- <th class="right">{% trans "Qty" %}</th>
- <th class="right">{% trans "Paid" %}</th>
- <th> </th>
- </thead>
- <tbody>
- {% for order in orders.object_list %}
- <tr>
- <td class="left">{{ order.id }}</td>
- <td class="left">{{ order.time|date:"SHORT_DATE_FORMAT" }}</td>
- <td class="right">{{ order.quantity_total }}</td>
- <td class="right">{{ order.total|currency }}</td>
- <td class="right">
- <form class="order-history-form" method="post" action="{% url "shop_invoice_resend" order.id %}?next={{ request.path }}">
- {% csrf_token %}
- {% if has_pdf %}
- <a class="btn btn-sm btn-primary" href="{% url "shop_invoice" order.id %}?format=pdf">{% trans "Download PDF" %}</a>
- {% endif %}
- <a class="btn btn-sm btn-default" target="_blank" href="{% url "shop_invoice" order.id %}">{% trans "View invoice" %}</a>
- <input type="submit" class="btn btn-sm btn-default" value="{% trans "Re-send order email" %}">
- </form>
- </td>
- </tr>
- {% endfor %}
- </tbody>
-</table>
-{% pagination_for orders %}
-
-{% else %}
-<p>{% trans "You have not ordered anything from us yet." %}</p>
-{% endif %}
-
-{% endblock %}
+++ /dev/null
-{% if not LANGUAGE_BIDI %}
- {% include "shop/includes/order_details.html" %}
-{% else %}
- {% include "shop/includes/order_details_rtl.html" %}
-{% endif %}
+++ /dev/null
-{% extends "shop/order_invoice.html" %}
+++ /dev/null
-{% extends "shop/checkout.html" %}
-
-{% load i18n multipayment_forms %}
-
-
-<div class="form-actions clearfix">
- <div class="form-actions-wrap">
- <input type="submit" value="Next" class="btn btn-large btn-primary">
-
- </div>
- </div>
-
-{% block before-form %}
- {% if request.cart.has_items %}
- {% multipayment_forms request form as multipayment_forms %}
- {% if multipayment_forms %}
- <div class="form-actions clearfix">
- <div class="form-actions-wrap">
- {% for name,form in multipayment_forms %}<form method="post" action="{{ form.action }}">
- {{ form.as_p }}
- <input type="submit" value="{% trans name %}" class="btn btn-large">
- </form>{% endfor %}
- </div>
- </div>
- {% endif %}
- {% endif %}
-{% endblock %}
-
-{% block fields %}
- {% if request.cart.has_items %}
- {% include "shop/includes/payment_fields.html" %}
- {% if not PRIMARY_PAYMENT_PROCESSOR_IN_USE %}<div style="display:none">{% endif %}
- {{ form.other_fields.as_ul }}
- {% if not PRIMARY_PAYMENT_PROCESSOR_IN_USE %}</div>{% endif %}
- {% endif %}
-{% endblock %}
-
-
-{% block nav-buttons %}
- {% if request.cart.has_items %}
- <div class="form-actions clearfix">
- <div class="form-actions-wrap">
- {% if PRIMARY_PAYMENT_PROCESSOR_IN_USE %}
- <input type="submit" class="btn btn-large btn-primary" value="{% trans "Next" %}">
- {% endif %}
- {% if not CHECKOUT_STEP_FIRST %}
- <input type="submit" class="btn btn-large" name="back" value="{% trans "Back" %}">
- {% endif %}
- </div>
- </div>
- {% else %}
- {{ block.super }}
- {% endif %}
-{% endblock %}
\ No newline at end of file
+++ /dev/null
-{% extends "shop/base.html" %}
-{% load staticfiles mezzanine_tags shop_tags records_tags rating_tags i18n %}
-
-{% block meta_title %}{{ product.meta_title }}{% endblock %}
-{% block body_id %}category{% endblock %}
-
-{% block meta_keywords %}{% metablock %}
-{% for keyword in product.keywords.all %}
- {% if not forloop.first %}, {% endif %}
- {{ keyword }}
-{% endfor %}
-{% endmetablock %}{% endblock %}
-
-{% block meta_description %}{% metablock %}
-{{ product.description }}
-{% endmetablock %}{% endblock %}
-
-{% block extra_css %}
-{{ block.super }}
-<link rel="stylesheet" href="{% static "mezzanine/css/magnific-popup.css" %}">
-{% endblock %}
-
-{% block extra_js %}
-{{ block.super }}
-<script src="{% static "mezzanine/js/magnific-popup.js" %}"></script>
-<script>
-$(document).ready(function() {
- $('#product-images-large').magnificPopup({
- delegate: 'a',
- type: 'image',
- gallery: {
- enabled: true,
- }
- });
-});
-</script>
-<script>
-$(function () {
- $('[data-toggle="popover"]').popover()
-})
-</script>
-
-{% endblock %}
-
-{% block extra_head %}
-{{ block.super }}
-<script>var variations = {{ variations_json|safe }};</script>
-<script src="{% static "cartridge/js/product_variations.js" %}"></script>
-{% endblock %}
-
-{% block breadcrumb_menu %}
-{{ block.super }}
-<li>{{ product.title }}</li>
-{% endblock %}
-
-{% block title %}
-<span class="bg-white">
-{% editable product.title %}{{ product.title }}{% endeditable %}
-</span>
-{% endblock %}
-
-{% block main %}
-
-<div class="row" style="padding-top: 1em;">
-
-<div class="col-md-5">
-{% if images %}
-{% spaceless %}
-<ul id="product-images-large" class="list-unstyled list-inline">
- {% for image in images %}
- <li id="image-{{ image.id }}-large"{% if not forloop.first %}style="display:none;"{% endif %}>
- <a class="product-image-large" href="{{ MEDIA_URL }}{{ image.file }}">
- <img alt="{{ image.description }}" src="{{ MEDIA_URL }}{% thumbnail image.file 0 300 %}" class="img-thumbnail img-responsive col-xs-12">
- </a>
- </li>
- {% endfor %}
-</ul>
-
-{% if images|length != 1 %}
-<ul id="product-images-thumb" class="list-unstyled list-inline">
- {% for image in images %}
- <li>
- <a class="thumbnail" id="image-{{ image.id }}" href="{{ MEDIA_URL }}{{ image.file }}">
- <img alt="{{ image.description }}" src="{{ MEDIA_URL }}{% thumbnail image.file 75 75 %}">
- </a>
- </li>
- {% endfor %}
-</ul>
-{% endif %}
-
-{% endspaceless %}
-{% endif %}
-</div>
-
-<div class="col-md-6">
-<ul class="description">
- <li><strong>{{ product.record.artist }}</strong></li>
- <li><em>{{ product.record.title }}</em></li>
- <li>
- {% trans "Label:" %}
- {{ product.record.label }}
- </li>
- <li>
- {% trans "Country:" %}
- {{ product.record.country }}
- </li>
- {% if product.record.release_year %}
- <li>
- {% trans "Release year:" %}
- {{ product.record.release_year }}
- </li>
- {% else %}
- <li>
- {% trans "Release decade:" %}
- {{ product.record.release_decade }}</li>
- {% endif %}
- <li>
- {% trans "Cover:" %}
- <a class="badge" tabindex="0" role="button" data-toggle="popover" data-trigger="hover focus"
- title="{{ product.record.cover_condition.name }}"
- data-content="{{ product.record.cover_condition.description }}">
- {{ product.record.cover_condition.abbr }}
- </a>
- </li>
- <li>
- {% trans " Vinyl:" %}
- <a class="badge" tabindex="0" role="button" data-toggle="popover" data-trigger="hover focus"
- title="{{ product.record.vinyl_condition.name }}"
- data-content="{{ product.record.cover_condition.description }}">
- {{ product.record.vinyl_condition.abbr }}
- </a>
- </li>
- <li>{% include "shop/includes/price.html" %}</li>
-</ul>
-
-<div class="audio">
-{% if product.record.audio_file %}
-<audio controls>
- <source src="{{ MEDIA_URL }}{{ product.record.audio_file }}">
-</audio>
-</div>
-{% endif %}
-
-</div>
-</div>
-
-<div class="description">
-{% editable product.content %}
-{{ product.content|richtext_filters|safe }}
-{% endeditable %}
-</div>
-
-{% if product.available and has_available_variations %}
-
-{% errors_for add_product_form %}
-
-<form method="post" id="add-cart" class="shop-form">{% csrf_token %}
- <div style="display: none;">
- {% fields_for add_product_form %}
- </div>
- <div class="form-actions">
- <input type="submit" class="btn btn-primary btn-lg pull-right" name="add_cart" value="{% trans "Add to cart" %}">
- {% if settings.SHOP_USE_WISHLIST %}
- <input type="submit" class="btn btn-default btn-lg pull-left" name="add_wishlist" value="{% trans "Save for later" %}">
- {% endif %}
- </div>
-</form>
-{% else %}
-<p class="error-msg">{% trans "This product is currently unavailable." %}</p>
-{% endif %}
-
-{% if settings.SHOP_USE_RATINGS %}
-<div class="panel panel-default rating">
- <div class="panel-body">{% rating_for product %}</div>
-</div>
-{% endif %}
-
-{% if settings.SHOP_USE_RELATED_PRODUCTS and related_products %}
-<h2>{% trans "Related Products" %}</h2>
-<div class="row related-products">
- {% for product in related_products %}
- <div class="col-xs-6 col-sm-4 col-md-3 product-thumb">
- <a class="thumbnail" href="{{ product.get_absolute_url }}">
- {% if product.image %}
- <img src="{{ MEDIA_URL }}{% thumbnail product.image 90 90 %}">
- {% endif %}
- <div class="caption">
- <h6>{{ product }}</h6>
- <div class="price-info">
- {% if product.has_price %}
- {% if product.on_sale %}
- <span class="old-price">{{ product.unit_price|currency }}</span>
- {% trans "On sale:" %}
- {% endif %}
- <span class="price">{{ product.price|currency }}</span>
- {% else %}
- <span class="coming-soon">{% trans "Coming soon" %}</span>
- {% endif %}
- </div>
- </div>
- </a>
- </div>
- {% endfor %}
-</div>
-{% endif %}
-
-{% endblock %}
+++ /dev/null
-{% extends "shop/base.html" %}
-{% load mezzanine_tags shop_tags i18n %}
-
-{% block meta_title %}{% trans "Your Wishlist" %}{% endblock %}
-{% block title %}{% trans "Your Wishlist" %}{% endblock %}
-
-{% block breadcrumb_menu %}
-{{ block.super }}
-<li>{% trans "Your Wishlist" %}</li>
-{% endblock %}
-
-{% block main %}
-{% if error %}{{ error }}{% endif %}
-{% if request.wishlist %}
-<table class="table table-striped wishlist">
- {% for item in wishlist_items %}
- <tr>
- <td width="30">
- {% if item.image %}
- <a href="{{ item.get_absolute_url }}"><img alt="{{ item }}" src="{{ MEDIA_URL }}{% thumbnail item.image.file 30 30 %}"></a>
- {% else %}
-
- {% endif %}
- </td>
- <td>
- <a href="{{ item.get_absolute_url }}">{{ item }}</a>
- </td>
- <td class="wishlist-actions">
- <form method="post">
- {{ item.unit_price|currency }}
- {% csrf_token %}
- <input type="hidden" name="sku" value="{{ item.sku }}">
- <input type="hidden" name="quantity" value="1">
- <input type="submit" class="btn btn-sm btn-primary" name="add_cart" value="{% trans "Buy" %}">
- <input type="submit" class="btn btn-sm btn-default" name="remove_wishlist" value="{% trans "Remove" %}">
- </form>
- </td>
- </tr>
- {% endfor %}
-</table>
-{% else %}
-<p>{% trans "Your wishlist is empty." %}</p>
-<br>
-<p><a class="btn btn-large btn-primary" href="{% url "page" "shop" %}">{% trans "Continue Shopping" %}</a></p>
-{% endif %}
-{% endblock %}
-dbdata:
- image: mysql
+media:
+ image: debian
volumes:
- - ./mysql:/var/lib/mysql
- entrypoint: /bin/echo
- command: data only container for db
+ - ./media/:/opt/media
+ - ./static/:/opt/static
+ command: "true"
db:
image: mysql
- MYSQL_DATABASE=diggersdigest
- MYSQL_USER=digger
- MYSQL_PASSWORD=admin
- volumes_from:
- - dbdata
+ volumes:
+ - ./mysql:/var/lib/mysql
-web:
+app:
build: .
- command: /bin/sh diggersdigest/deploy/start_app.sh
+ command: /bin/sh app/deploy/start_app.sh
volumes:
- - .:/code
+ - .:/opt/app
+ volumes_from:
+ - media
ports:
- "8000:8000"
links:
- db
+
+nginx:
+ image: nginx
+ ports:
+ - "80:80"
+ volumes:
+ - ./app/deploy/nginx-app.conf:/etc/nginx/conf.d/default.conf
+ - /var/log/nginx
+ volumes_from:
+ - media
+ links:
+ - app
django-uuidfield==0.5.0
django-newsletter==0.5.2
parsedatetime==1.5
+watchdog
+uwsgi