Skip to content
Browse files

endd

  • Loading branch information...
1 parent 411199f commit 0c051f64f3f24ea47ddeb9e52bdbee6fa147c44d @ButuzGOL committed
View
722 accounts/fixtures/initial_data.json
@@ -0,0 +1,722 @@
+[
+ {
+ "pk": 49,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "add_userprofile",
+ "name": "Can add user profile",
+ "content_type": 17
+ }
+ },
+ {
+ "pk": 50,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "change_userprofile",
+ "name": "Can change user profile",
+ "content_type": 17
+ }
+ },
+ {
+ "pk": 51,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "delete_userprofile",
+ "name": "Can delete user profile",
+ "content_type": 17
+ }
+ },
+ {
+ "pk": 28,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "add_logentry",
+ "name": "Can add log entry",
+ "content_type": 10
+ }
+ },
+ {
+ "pk": 29,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "change_logentry",
+ "name": "Can change log entry",
+ "content_type": 10
+ }
+ },
+ {
+ "pk": 30,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "delete_logentry",
+ "name": "Can delete log entry",
+ "content_type": 10
+ }
+ },
+ {
+ "pk": 4,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "add_group",
+ "name": "Can add group",
+ "content_type": 2
+ }
+ },
+ {
+ "pk": 10,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "add_message",
+ "name": "Can add message",
+ "content_type": 4
+ }
+ },
+ {
+ "pk": 1,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "add_permission",
+ "name": "Can add permission",
+ "content_type": 1
+ }
+ },
+ {
+ "pk": 7,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "add_user",
+ "name": "Can add user",
+ "content_type": 3
+ }
+ },
+ {
+ "pk": 5,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "change_group",
+ "name": "Can change group",
+ "content_type": 2
+ }
+ },
+ {
+ "pk": 11,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "change_message",
+ "name": "Can change message",
+ "content_type": 4
+ }
+ },
+ {
+ "pk": 2,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "change_permission",
+ "name": "Can change permission",
+ "content_type": 1
+ }
+ },
+ {
+ "pk": 8,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "change_user",
+ "name": "Can change user",
+ "content_type": 3
+ }
+ },
+ {
+ "pk": 6,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "delete_group",
+ "name": "Can delete group",
+ "content_type": 2
+ }
+ },
+ {
+ "pk": 12,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "delete_message",
+ "name": "Can delete message",
+ "content_type": 4
+ }
+ },
+ {
+ "pk": 3,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "delete_permission",
+ "name": "Can delete permission",
+ "content_type": 1
+ }
+ },
+ {
+ "pk": 9,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "delete_user",
+ "name": "Can delete user",
+ "content_type": 3
+ }
+ },
+ {
+ "pk": 70,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "add_card",
+ "name": "Can add card",
+ "content_type": 24
+ }
+ },
+ {
+ "pk": 71,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "change_card",
+ "name": "Can change card",
+ "content_type": 24
+ }
+ },
+ {
+ "pk": 72,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "delete_card",
+ "name": "Can delete card",
+ "content_type": 24
+ }
+ },
+ {
+ "pk": 37,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "add_cartitem",
+ "name": "Can add cart item",
+ "content_type": 13
+ }
+ },
+ {
+ "pk": 38,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "change_cartitem",
+ "name": "Can change cart item",
+ "content_type": 13
+ }
+ },
+ {
+ "pk": 39,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "delete_cartitem",
+ "name": "Can delete cart item",
+ "content_type": 13
+ }
+ },
+ {
+ "pk": 31,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "add_category",
+ "name": "Can add category",
+ "content_type": 11
+ }
+ },
+ {
+ "pk": 34,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "add_product",
+ "name": "Can add product",
+ "content_type": 12
+ }
+ },
+ {
+ "pk": 58,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "add_productreview",
+ "name": "Can add product review",
+ "content_type": 20
+ }
+ },
+ {
+ "pk": 32,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "change_category",
+ "name": "Can change category",
+ "content_type": 11
+ }
+ },
+ {
+ "pk": 35,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "change_product",
+ "name": "Can change product",
+ "content_type": 12
+ }
+ },
+ {
+ "pk": 59,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "change_productreview",
+ "name": "Can change product review",
+ "content_type": 20
+ }
+ },
+ {
+ "pk": 33,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "delete_category",
+ "name": "Can delete category",
+ "content_type": 11
+ }
+ },
+ {
+ "pk": 36,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "delete_product",
+ "name": "Can delete product",
+ "content_type": 12
+ }
+ },
+ {
+ "pk": 60,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "delete_productreview",
+ "name": "Can delete product review",
+ "content_type": 20
+ }
+ },
+ {
+ "pk": 43,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "add_order",
+ "name": "Can add order",
+ "content_type": 15
+ }
+ },
+ {
+ "pk": 46,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "add_orderitem",
+ "name": "Can add order item",
+ "content_type": 16
+ }
+ },
+ {
+ "pk": 44,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "change_order",
+ "name": "Can change order",
+ "content_type": 15
+ }
+ },
+ {
+ "pk": 47,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "change_orderitem",
+ "name": "Can change order item",
+ "content_type": 16
+ }
+ },
+ {
+ "pk": 45,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "delete_order",
+ "name": "Can delete order",
+ "content_type": 15
+ }
+ },
+ {
+ "pk": 48,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "delete_orderitem",
+ "name": "Can delete order item",
+ "content_type": 16
+ }
+ },
+ {
+ "pk": 13,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "add_contenttype",
+ "name": "Can add content type",
+ "content_type": 5
+ }
+ },
+ {
+ "pk": 14,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "change_contenttype",
+ "name": "Can change content type",
+ "content_type": 5
+ }
+ },
+ {
+ "pk": 15,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "delete_contenttype",
+ "name": "Can delete content type",
+ "content_type": 5
+ }
+ },
+ {
+ "pk": 25,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "add_error",
+ "name": "Can add error",
+ "content_type": 9
+ }
+ },
+ {
+ "pk": 22,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "add_errorbatch",
+ "name": "Can add Error summary",
+ "content_type": 8
+ }
+ },
+ {
+ "pk": 26,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "change_error",
+ "name": "Can change error",
+ "content_type": 9
+ }
+ },
+ {
+ "pk": 23,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "change_errorbatch",
+ "name": "Can change Error summary",
+ "content_type": 8
+ }
+ },
+ {
+ "pk": 27,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "delete_error",
+ "name": "Can delete error",
+ "content_type": 9
+ }
+ },
+ {
+ "pk": 24,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "delete_errorbatch",
+ "name": "Can delete Error summary",
+ "content_type": 8
+ }
+ },
+ {
+ "pk": 40,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "add_flatpage",
+ "name": "Can add flat page",
+ "content_type": 14
+ }
+ },
+ {
+ "pk": 41,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "change_flatpage",
+ "name": "Can change flat page",
+ "content_type": 14
+ }
+ },
+ {
+ "pk": 42,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "delete_flatpage",
+ "name": "Can delete flat page",
+ "content_type": 14
+ }
+ },
+ {
+ "pk": 67,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "add_redirect",
+ "name": "Can add redirect",
+ "content_type": 23
+ }
+ },
+ {
+ "pk": 68,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "change_redirect",
+ "name": "Can change redirect",
+ "content_type": 23
+ }
+ },
+ {
+ "pk": 69,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "delete_redirect",
+ "name": "Can delete redirect",
+ "content_type": 23
+ }
+ },
+ {
+ "pk": 52,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "add_searchterm",
+ "name": "Can add search term",
+ "content_type": 18
+ }
+ },
+ {
+ "pk": 53,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "change_searchterm",
+ "name": "Can change search term",
+ "content_type": 18
+ }
+ },
+ {
+ "pk": 54,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "delete_searchterm",
+ "name": "Can delete search term",
+ "content_type": 18
+ }
+ },
+ {
+ "pk": 16,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "add_session",
+ "name": "Can add session",
+ "content_type": 6
+ }
+ },
+ {
+ "pk": 17,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "change_session",
+ "name": "Can change session",
+ "content_type": 6
+ }
+ },
+ {
+ "pk": 18,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "delete_session",
+ "name": "Can delete session",
+ "content_type": 6
+ }
+ },
+ {
+ "pk": 19,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "add_site",
+ "name": "Can add site",
+ "content_type": 7
+ }
+ },
+ {
+ "pk": 20,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "change_site",
+ "name": "Can change site",
+ "content_type": 7
+ }
+ },
+ {
+ "pk": 21,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "delete_site",
+ "name": "Can delete site",
+ "content_type": 7
+ }
+ },
+ {
+ "pk": 55,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "add_productview",
+ "name": "Can add product view",
+ "content_type": 19
+ }
+ },
+ {
+ "pk": 56,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "change_productview",
+ "name": "Can change product view",
+ "content_type": 19
+ }
+ },
+ {
+ "pk": 57,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "delete_productview",
+ "name": "Can delete product view",
+ "content_type": 19
+ }
+ },
+ {
+ "pk": 61,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "add_tag",
+ "name": "Can add tag",
+ "content_type": 21
+ }
+ },
+ {
+ "pk": 64,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "add_taggeditem",
+ "name": "Can add tagged item",
+ "content_type": 22
+ }
+ },
+ {
+ "pk": 62,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "change_tag",
+ "name": "Can change tag",
+ "content_type": 21
+ }
+ },
+ {
+ "pk": 65,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "change_taggeditem",
+ "name": "Can change tagged item",
+ "content_type": 22
+ }
+ },
+ {
+ "pk": 63,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "delete_tag",
+ "name": "Can delete tag",
+ "content_type": 21
+ }
+ },
+ {
+ "pk": 66,
+ "model": "auth.permission",
+ "fields": {
+ "codename": "delete_taggeditem",
+ "name": "Can delete tagged item",
+ "content_type": 22
+ }
+ },
+ {
+ "pk": 1,
+ "model": "auth.user",
+ "fields": {
+ "username": "ButuzGOL",
+ "first_name": "",
+ "last_name": "",
+ "is_active": 1,
+ "is_superuser": 1,
+ "is_staff": 1,
+ "last_login": "2010-04-21 10:19:33",
+ "groups": [],
+ "user_permissions": [],
+ "password": "sha1$c8196$3895b93e8cb725aa0fd005fe14f91865d3e5a276",
+ "email": "butuzgol@gmail.com",
+ "date_joined": "2010-04-16 23:22:12"
+ }
+ },
+ {
+ "pk": 2,
+ "model": "auth.user",
+ "fields": {
+ "username": "Fog",
+ "first_name": "",
+ "last_name": "",
+ "is_active": 1,
+ "is_superuser": 0,
+ "is_staff": 0,
+ "last_login": "2010-04-19 11:37:11",
+ "groups": [],
+ "user_permissions": [],
+ "password": "sha1$f3f9b$4e3d4bd4dadeda3d7784f912e05d0f4ba7ae8047",
+ "email": "",
+ "date_joined": "2010-04-19 11:37:11"
+ }
+ },
+ {
+ "pk": 3,
+ "model": "auth.user",
+ "fields": {
+ "username": "Gol",
+ "first_name": "",
+ "last_name": "",
+ "is_active": 1,
+ "is_superuser": 0,
+ "is_staff": 0,
+ "last_login": "2010-04-19 11:57:24",
+ "groups": [],
+ "user_permissions": [],
+ "password": "sha1$193aa$5427897a7b8ecb23122faa5248217cc4efafaa70",
+ "email": "",
+ "date_joined": "2010-04-19 11:57:24"
+ }
+ },
+ {
+ "pk": 4,
+ "model": "auth.user",
+ "fields": {
+ "username": "Opa",
+ "first_name": "",
+ "last_name": "",
+ "is_active": 1,
+ "is_superuser": 0,
+ "is_staff": 0,
+ "last_login": "2010-04-21 09:12:09",
+ "groups": [],
+ "user_permissions": [],
+ "password": "sha1$90dc5$7862531aba3a0c7c7a88c27afc4e4647d8c56456",
+ "email": "ron9.gol@gmail.com",
+ "date_joined": "2010-04-21 09:12:09"
+ }
+ }
+]
View
16 accounts/forms.py
@@ -1,8 +1,24 @@
from django import forms
from ecomstore.accounts.models import UserProfile
+from django.contrib.auth.forms import UserCreationForm
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
exclude = ('user',)
+
+class RegistrationForm(UserCreationForm):
+ password1 = forms.RegexField(label="Password", regex=r'^(?=.*\W+).*$',
+ help_text='Password must be six characters \
+ long and contain at least one \
+ non-alphanumeric character.',
+ widget=forms.PasswordInput, min_length=6,
+ #render_value=False
+ )
+ password2 = forms.RegexField(label="Password confirmation",
+ regex=r'^(?=.*\W+).*$',
+ widget=forms.PasswordInput, min_length=6,
+ #render_value=False
+ )
+ email = forms.EmailField(max_length="50")
View
12 accounts/views.py
@@ -3,6 +3,7 @@
from django.shortcuts import render_to_response, get_object_or_404
from django.core import urlresolvers
from django.http import HttpResponseRedirect
+from ecomstore.accounts.forms import UserProfileForm, RegistrationForm
from ecomstore.checkout.models import Order, OrderItem
from django.contrib.auth.decorators import login_required
@@ -10,9 +11,13 @@
def register(request, template_name="registration/register.html"):
if request.method == 'POST':
postdata = request.POST.copy()
- form = UserCreationForm(postdata)
+ #form = UserCreationForm(postdata)
+ form = RegistrationForm(postdata)
if form.is_valid():
- form.save()
+ user = form.save(commit=False)
+ user.email = postdata.get('email','')
+ user.save()
+ #form.save()
un = postdata.get('username', '')
pw = postdata.get('password1', '')
from django.contrib.auth import login, authenticate
@@ -22,7 +27,8 @@ def register(request, template_name="registration/register.html"):
url = urlresolvers.reverse('my_account')
return HttpResponseRedirect(url)
else:
- form = UserCreationForm()
+ form = RegistrationForm()
+ #form = UserCreationForm()
page_title = 'User Registration'
return render_to_response(template_name, locals(),
context_instance=RequestContext(request))
View
14 apache/django.wsgi
@@ -0,0 +1,14 @@
+import os, sys
+# path to directory of the .wsgi file ('apache/')
+wsgi_dir = os.path.abspath(os.path.dirname(__file__))
+# path to project root directory (parent of 'apache/')
+project_dir = os.path.dirname(wsgi_dir)
+# add project directory to system’s PATH
+sys.path.append(project_dir)
+# add the settings.py file to your system's PATH
+project_settings = os.path.join(project_dir,'settings')
+# explicitly define the DJANGO_SETTINGS_MODULE
+os.environ['DJANGO_SETTINGS_MODULE'] = 'ecomstore.settings'
+
+import django.core.handlers.wsgi
+application = django.core.handlers.wsgi.WSGIHandler()
View
0 billing/__init__.py
No changes.
View
36 billing/forms.py
@@ -0,0 +1,36 @@
+from ecomstore.billing.models import Card
+from django import forms
+from datetime import datetime
+
+month_choice = [ ]
+
+# month_choice.append(('','- Month -'))
+for i in range(1, 13):
+ if len(str(i)) == 1:
+ numeric = '0' + str(i)
+ else:
+ numeric = str(i)
+ month_choice.append((numeric, datetime(2009, i, 1).strftime('%B')))
+MONTHS = tuple(month_choice)
+calendar_years = [ ]
+
+# calendar_years.append(('','- Year -'))
+for i in range(datetime.now().year, datetime.now().year + 10):
+ calendar_years.append((i,i))
+YEARS = tuple(calendar_years)
+
+class CardForm(forms.ModelForm):
+ CARD_TYPES = (('Visa', 'Visa'),
+ ('Amex', 'Amex'),
+ ('Discover', 'Discover'),
+ ('Mastercard', 'Mastercard'),)
+
+ class Meta:
+ model = Card
+ exclude = ('data','num', 'user')
+
+ cardholder_name = forms.CharField(max_length=100)
+ card_number = forms.CharField(max_length=20)
+ card_type = forms.ChoiceField(choices=CARD_TYPES)
+ card_expire_month = forms.ChoiceField(choices=MONTHS)
+ card_expire_year = forms.ChoiceField(choices=YEARS)
View
14 billing/models.py
@@ -0,0 +1,14 @@
+from django.db import models
+from django.contrib.auth.models import User
+
+class Card(models.Model):
+ data = models.CharField(max_length=500)
+ user = models.ForeignKey(User)
+ num = models.CharField(max_length=4)
+
+ @property
+ def display_number(self):
+ return u'xxxx-xxxx-xxxx-' + unicode(self.num)
+
+ def __unicode__(self):
+ return unicode(self.user.username) + ' - ' + self.display_number
View
16 billing/passkey.py
@@ -0,0 +1,16 @@
+from ecomstore.settings import CURRENT_PATH
+from keyczar import keyczar
+import os
+
+KEY_PATH = os.path.join(CURRENT_PATH, 'keys')
+
+def encrypt(plaintext):
+ crypter = _get_crypter()
+ return crypter.Encrypt(plaintext)
+
+def decrypt(ciphertext):
+ crypter = _get_crypter()
+ return crypter.Decrypt(ciphertext)
+
+def _get_crypter():
+ return keyczar.Crypter.Read(KEY_PATH)
View
9 billing/tests.py
@@ -0,0 +1,9 @@
+from django.test import TestCase, Client
+from ecomstore.billing.passkey import encrypt, decrypt
+
+class EncryptionTestCase(TestCase):
+
+ def test_encrypt_decrypt(self):
+ to_encrypt = 'Some text here'
+ self.failUnlessEqual(to_encrypt, decrypt(encrypt(to_encrypt)))
+ self.failIfEqual(to_encrypt, encrypt(to_encrypt))
View
5 billing/urls.py
@@ -0,0 +1,5 @@
+from django.conf.urls.defaults import *
+
+urlpatterns = patterns('ecomstore.billing.views',
+ (r'^add_card/$', 'add_card'),
+)
View
32 billing/views.py
@@ -0,0 +1,32 @@
+from django.shortcuts import render_to_response
+from django.core import serializers
+from django.utils import simplejson
+from django.template import RequestContext
+from django.contrib.auth.decorators import login_required
+from ecomstore.billing.forms import CardForm
+from ecomstore.billing import passkey
+
+@login_required
+def add_card(request):
+ if request.method == 'POST':
+ post_data = request.POST.copy()
+ # convert the POST variables into JSON format
+ post_data.__delitem__('csrfmiddlewaretoken')
+ json_data = simplejson.dumps(post_data)
+ # encrypt the JSON
+ encrypted_json = passkey.encrypt(json_data)
+ # retrieve the encrypted JSON
+ decrypted_json = passkey.decrypt(encrypted_json)
+ # convert the decrypted JSON into a dictionary
+ decrypted_data = simplejson.loads(decrypted_json)
+ # store the newly encrypted data as a Card instance
+ form = CardForm(post_data)
+ card = form.save(commit=False)
+ card.user = request.user
+ card.num = post_data.get('card_number')[-4:]
+ card.data = encrypted_json
+ card.save()
+ else:
+ form = CardForm()
+ return render_to_response("billing/add_card.html", locals(),
+ context_instance=RequestContext(request))
View
0 caching/__init__.py
No changes.
View
10 caching/caching.py
@@ -0,0 +1,10 @@
+from django.core.cache import cache
+from ecomstore.settings import CACHE_TIMEOUT
+
+def cache_update(sender, **kwargs):
+ item = kwargs.get('instance')
+ cache.set(item.cache_key, item, CACHE_TIMEOUT)
+
+def cache_evict(sender, **kwargs):
+ item = kwargs.get('instance')
+ cache.delete(item.cache_key)
View
3 caching/models.py
@@ -0,0 +1,3 @@
+from django.db import models
+
+# Create your models here.
View
23 caching/tests.py
@@ -0,0 +1,23 @@
+"""
+This file demonstrates two different styles of tests (one doctest and one
+unittest). These will both pass when you run "manage.py test".
+
+Replace these with more appropriate tests for your application.
+"""
+
+from django.test import TestCase
+
+class SimpleTest(TestCase):
+ def test_basic_addition(self):
+ """
+ Tests that 1 + 1 always equals 2.
+ """
+ self.failUnlessEqual(1 + 1, 2)
+
+__test__ = {"doctest": """
+Another way to test that 1 + 1 is equal to 2.
+
+>>> 1 + 1 == 2
+True
+"""}
+
View
1 caching/views.py
@@ -0,0 +1 @@
+# Create your views here.
View
21 cart/cart.py
@@ -96,3 +96,24 @@ def empty_cart(request):
user_cart = get_cart_items(request)
user_cart.delete()
+
+from django.conf import settings
+from django.db.models import Max
+from ecomstore.settings import SESSION_AGE_DAYS
+from datetime import datetime, timedelta
+
+def remove_old_cart_items():
+ print "Removing old carts"
+ # calculate date of SESSION_AGE_DAYS days ago
+ remove_before = datetime.now() + timedelta(days=-settings.SESSION_AGE_DAYS)
+ cart_ids = [ ]
+ old_items = CartItem.objects.values('cart_id'). \
+ annotate(last_change=Max('date_added')). \
+ filter(last_change__lt=remove_before).order_by()
+ # create a list of cart IDs that havent been modified
+ for item in old_items:
+ cart_ids.append(item['cart_id'])
+ to_remove = CartItem.objects.filter(cart_id__in=cart_ids)
+ # delete those CartItem instances
+ to_remove.delete()
+ print str(len(cart_ids)) + " carts were removed"
View
0 cart/management/__init__.py
No changes.
View
0 cart/management/commands/__init__.py
No changes.
View
9 cart/management/commands/delete_old_carts.py
@@ -0,0 +1,9 @@
+from django.core.management.base import NoArgsCommand
+from ecomstore.cart import cart
+
+class Command(NoArgsCommand):
+
+ help = "Delete shopping cart items more than SESSION_AGE_DAYS days old"
+
+ def handle_noargs(self, **options):
+ cart.remove_old_cart_items()
View
88 cart/tests.py
@@ -1,23 +1,71 @@
-"""
-This file demonstrates two different styles of tests (one doctest and one
-unittest). These will both pass when you run "manage.py test".
+from ecomstore.catalog.models import Product
+from ecomstore.cart.models import CartItem
+from ecomstore.cart import cart
+from django.test import TestCase, Client
+from django.core import urlresolvers
+from django.db import IntegrityError
+from django.contrib import csrf
+from django.conf import settings
+import httplib
-Replace these with more appropriate tests for your application.
-"""
+class CartTestCase(TestCase):
+ def setUp(self):
+ self.client = Client()
+ self.product = Product.active.all()[0]
+
+ def test_cart_id(self):
+ home_url = urlresolvers.reverse('catalog_home')
+ self.client.get(home_url)
+ # check that there is a cart_id set in session
+ # after a page with cart box has been requested
+ self.failUnless(self.client.session.get(cart.CART_ID_SESSION_KEY, ''))
+
+ def test_add_product(self):
+ QUANTITY = 2
+ product_url = self.product.get_absolute_url()
+ response = self.client.get(product_url)
+ self.assertEqual(response.status_code, httplib.OK )
+ # store count in cart_count variable
+ cart_item_count = self.get_cart_item_count()
+ # assert that the cart item count is zero
+ self.failUnlessEqual(cart_item_count, 0)
+ # perform the post of adding to the cart
+ cookie = self.client.cookies[settings.SESSION_COOKIE_NAME]
+ csrf_token = csrf.middleware._make_token(cookie.value)
+ postdata = {'product_slug': self.product.slug,
+ 'quantity': QUANTITY,
+ 'csrfmiddlewaretoken': csrf_token }
+ response = self.client.post(product_url, postdata )
+ # assert redirected to cart page - 302 then 200
+ cart_url = urlresolvers.reverse('show_cart')
+ self.assertRedirects(response, cart_url, status_code=httplib.FOUND,
+ target_status_code=httplib.OK)
+ # assert cart item count is incremented by one
+ self.assertEqual(self.get_cart_item_count(), cart_item_count + 1)
+ cart_id = self.get_cart_id()
+ last_item = CartItem.objects.filter(cart_id=cart_id). \
+ latest('date_added')
+ # assert the latest cart item has a quantity of two
+ self.failUnlessEqual(last_item.quantity, QUANTITY)
+ # assert the latest cart item is the correct product
+ self.failUnlessEqual(last_item.product, self.product)
+
+ def get_cart_item_count(self):
+ cart_id = self.get_cart_id()
+ return CartItem.objects.filter(cart_id=cart_id).count()
+
+ def get_cart_id(self):
+ return self.client.session.get(cart.CART_ID_SESSION_KEY)
-from django.test import TestCase
-
-class SimpleTest(TestCase):
- def test_basic_addition(self):
- """
- Tests that 1 + 1 always equals 2.
- """
- self.failUnlessEqual(1 + 1, 2)
-
-__test__ = {"doctest": """
-Another way to test that 1 + 1 is equal to 2.
-
->>> 1 + 1 == 2
-True
-"""}
+ def test_add_to_cart_fails_csrf(self):
+ quantity = 2
+ product_url = self.product.get_absolute_url()
+ response = self.client.get(product_url)
+ self.assertEqual(response.status_code, httplib.OK )
+ # perform the post of adding to the cart
+ postdata = {'product_slug': self.product.slug,
+ 'quantity': quantity }
+ response = self.client.post(product_url, postdata )
+ # assert forbidden error due to missing CSRF input
+ self.assertEqual(response.status_code, httplib.FORBIDDEN )
View
2 cart/urls.py
@@ -2,4 +2,4 @@
urlpatterns = patterns('ecomstore.cart.views',
(r'^$', 'show_cart', { 'template_name': 'cart/cart.html' }, 'show_cart'),
-)
+)
View
2 cart/views.py
@@ -21,4 +21,4 @@ def show_cart(request, template_name):
# for Google Checkout button
merchant_id = settings.GOOGLE_CHECKOUT_MERCHANT_ID
return render_to_response(template_name, locals(),
- context_instance=RequestContext(request))
+ context_instance=RequestContext(request))
View
98 catalog/fixtures/initial_data.json
@@ -0,0 +1,98 @@
+[
+ {
+ "pk": 3,
+ "model": "catalog.category",
+ "fields": {
+ "meta_description": "Electric guitar",
+ "meta_keywords": "Electric, guitar",
+ "description": "Electric guitars",
+ "created_at": "2010-04-18 00:29:00",
+ "is_active": 1,
+ "updated_at": "2010-04-18 00:29:00",
+ "slug": "electric-guitars",
+ "name": "Electric guitars"
+ }
+ },
+ {
+ "pk": 2,
+ "model": "catalog.category",
+ "fields": {
+ "meta_description": "Acoustic guitars",
+ "meta_keywords": "Acoustic, guitars",
+ "description": "Acoustic guitars and nothing!",
+ "created_at": "2010-04-18 00:28:18",
+ "is_active": 1,
+ "updated_at": "2010-04-18 00:28:18",
+ "slug": "acoustic-guitars",
+ "name": "Acoustic guitars"
+ }
+ },
+ {
+ "pk": 2,
+ "model": "catalog.product",
+ "fields": {
+ "sku": "123",
+ "meta_description": "12",
+ "is_featured": 0,
+ "meta_keywords": "123",
+ "name": "Fen",
+ "is_active": 1,
+ "brand": "Philips",
+ "description": "123",
+ "old_price": "0.00",
+ "updated_at": "2010-04-21 07:47:32",
+ "slug": "fen",
+ "thumbnail": "images/products/thumbnails/1240046973_bulb_yellow.png",
+ "is_bestseller": 0,
+ "image": "images/products/main/1240045204_agt_update_misc.png",
+ "image_caption": "123",
+ "created_at": "2010-04-19 15:31:59",
+ "price": "123.00",
+ "categories": [
+ 3
+ ],
+ "quantity": 123
+ }
+ },
+ {
+ "pk": 1,
+ "model": "catalog.product",
+ "fields": {
+ "sku": "15973",
+ "meta_description": "Ruby Axe Guitar",
+ "is_featured": 0,
+ "meta_keywords": "Ruby, Axe, Guitar, 123",
+ "name": "Ruby Axe Guitar",
+ "is_active": 1,
+ "brand": "Rails",
+ "description": "Let\u2019s walk through a request step by step, and review the way our code is handling all of this. A request to\r\nthe site is first routed through the urls.py file in our root directory, and the requests to the homepage,\r\ncategory, and product views are now being routed through the one line with our include() function in\r\nit:\r\n",
+ "old_price": "0.00",
+ "updated_at": "2010-04-21 23:58:25",
+ "slug": "ruby-axe-guitar",
+ "thumbnail": "images/products/thumbnails/IE-64.png",
+ "is_bestseller": 0,
+ "image": "images/products/main/Firefox-64.png",
+ "image_caption": "ie",
+ "created_at": "2010-04-18 00:32:28",
+ "price": "249.99",
+ "categories": [
+ 3,
+ 2
+ ],
+ "quantity": 20
+ }
+ },
+ {
+ "pk": 1,
+ "model": "catalog.productreview",
+ "fields": {
+ "rating": 5,
+ "product": 2,
+ "is_approved": 1,
+ "title": "Go",
+ "content": "Go 1",
+ "user": 1,
+ "date": "2010-04-21 07:03:18"
+ }
+ }
+]
View
16 catalog/models.py
@@ -1,6 +1,9 @@
from django.db import models
from django.contrib.auth.models import User
+from django.db.models.signals import post_save, post_delete
+from ecomstore.caching.caching import cache_update, cache_evict
+
class ActiveCategoryManager(models.Manager):
def get_query_set(self):
return super(ActiveCategoryManager, self).get_query_set(). \
@@ -33,6 +36,10 @@ def get_absolute_url(self):
objects = models.Manager()
active = ActiveCategoryManager()
+
+ @property
+ def cache_key(self):
+ return self.get_absolute_url()
class ActiveProductManager(models.Manager):
def get_query_set(self):
@@ -90,6 +97,10 @@ def sale_price(self):
active = ActiveProductManager()
featured = FeaturedProductManager()
+ @property
+ def cache_key(self):
+ return self.get_absolute_url()
+
def cross_sells(self):
from ecomstore.checkout.models import Order, OrderItem
orders = Order.objects.filter(orderitem__product=self)
@@ -143,3 +154,8 @@ class ProductReview(models.Model):
tagging.register(Product)
except tagging.AlreadyRegistered:
pass
+
+post_save.connect(cache_update, sender=Product)
+post_delete.connect(cache_evict, sender=Product)
+post_save.connect(cache_update, sender=Category)
+post_delete.connect(cache_evict, sender=Category)
View
8 catalog/templatetags/catalog_tags.py
@@ -4,6 +4,8 @@
from ecomstore.catalog.models import Category
from django.contrib.flatpages.models import FlatPage
+from django.core.cache import cache
+from ecomstore.settings import CACHE_TIMEOUT
register = template.Library()
@@ -14,7 +16,11 @@ def cart_box(request):
@register.inclusion_tag("tags/category_list.html")
def category_list(request_path):
- active_categories = Category.objects.filter(is_active=True)
+ list_cache_key = 'active_category_link_list'
+ active_categories = cache.get(list_cache_key)
+ if not active_categories:
+ active_categories = Category.active.all()
+ cache.set(list_cache_key, active_categories, CACHE_TIMEOUT)
return {
'active_categories': active_categories,
'request_path': request_path
View
116 catalog/tests.py
@@ -1,23 +1,105 @@
-"""
-This file demonstrates two different styles of tests (one doctest and one
-unittest). These will both pass when you run "manage.py test".
+from django.test import TestCase, Client
+from django.core import urlresolvers
+import httplib
+from ecomstore.catalog.models import Category, Product
+from django.views.defaults import page_not_found
+from decimal import Decimal
-Replace these with more appropriate tests for your application.
-"""
+class NewUserTestCase(TestCase):
+ fixtures = ['products', 'categories']
+ def test_view_homepage(self):
+ client = Client()
+ home_url = urlresolvers.reverse('catalog_home')
+ response = client.get(home_url)
+ # check that we did get a response
+ self.failUnless(response)
+ # check that status code of response was success
+ # (httplib.OK = 200)
+ self.assertEqual(response.status_code, httplib.OK)
+
+ def test_view_category(self):
+ category = Category.active.all()[0]
+ category_url = category.get_absolute_url()
+ # get the template_name arg from URL entry
+ url_entry = urlresolvers.resolve(category_url)
+ template_name = url_entry[2]['template_name']
+ # test loading of category page
+ response = self.client.get(category_url)
+ # test that we got a response
+ self.failUnless(response)
+ # test that the HTTP status code was "OK"
+ self.assertEqual(response.status_code, httplib.OK)
+ # test that we used the category.html template in response
+ self.assertTemplateUsed(response, template_name)
+ # test that category page contains category information
+ self.assertContains(response, category.name)
+ self.assertContains(response, category.description)
+
+ def test_view_product(self):
+ """ test product view loads """
+ product = Product.active.all()[0]
+ product_url = product.get_absolute_url()
+ url_entry = urlresolvers.resolve(product_url)
+ template_name = url_entry[2]['template_name']
+ response = self.client.get(product_url)
+ self.failUnless(response)
+ self.assertEqual(response.status_code, httplib.OK)
+ self.assertTemplateUsed(response, template_name)
+ self.assertContains(response, product.name)
+ self.assertContains(response, product.description)
-from django.test import TestCase
+class ActiveProductManagerTestCase(TestCase):
+
+ def setUp(self):
+ self.client = Client()
+
+ def test_inactive_product_returns_404(self):
+ """ test that inactive product returns a 404 error """
+ inactive_product = Product.objects.filter(is_active=False)[0]
+ inactive_product_url = inactive_product.get_absolute_url()
+ # load the template file used to render the product page
+ url_entry = urlresolvers.resolve(inactive_product_url)
+ template_name = url_entry[2]['template_name']
+ # load the name of the default django 404 template file
+ django_404_template = page_not_found.func_defaults[0]
+ response = self.client.get(inactive_product_url)
+ self.assertTemplateUsed(response, django_404_template)
+ self.assertTemplateNotUsed(response, template_name)
-class SimpleTest(TestCase):
- def test_basic_addition(self):
- """
- Tests that 1 + 1 always equals 2.
- """
- self.failUnlessEqual(1 + 1, 2)
+class ProductTestCase(TestCase):
+
+ def setUp(self):
+ self.product = Product.active.all()[0]
+ self.product.price = Decimal('199.99')
+ self.product.save()
+ self.client = Client()
+
+ def test_sale_price(self):
+ self.product.old_price = Decimal('220.00')
+ self.product.save()
+ self.failIfEqual(self.product.sale_price, None)
+ self.assertEqual(self.product.sale_price, self.product.price)
+
+ def test_no_sale_price(self):
+ self.product.old_price = Decimal('0.00')
+ self.product.save()
+ self.failUnlessEqual(self.product.sale_price, None)
-__test__ = {"doctest": """
-Another way to test that 1 + 1 is equal to 2.
+ def test_permalink(self):
+ url = self.product.get_absolute_url()
+ response = self.client.get(url)
+ self.failUnless(response)
+ self.assertEqual(response.status_code, httplib.OK)
+
+ def test_unicode(self):
+ self.assertEqual(self.product.__unicode__(), self.product.name)
->>> 1 + 1 == 2
-True
-"""}
+from ecomstore.catalog.models import ProductReview
+from django.db import IntegrityError
+
+class ProductReviewTestCase(TestCase):
+
+ def test_orphaned_product_review(self):
+ pr = ProductReview()
+ self.assertRaises(IntegrityError, pr.save)
View
18 catalog/views.py
@@ -12,6 +12,9 @@
from ecomstore.stats import stats
from ecomstore.settings import PRODUCTS_PER_ROW
+from django.core.cache import cache
+from ecomstore.settings import CACHE_TIMEOUT
+
def index(request, template_name="catalog/index.html"):
search_recs = stats.recommended_from_search(request)
featured = Product.featured.all()[0:PRODUCTS_PER_ROW]
@@ -23,7 +26,11 @@ def index(request, template_name="catalog/index.html"):
def show_category(request, category_slug,
template_name="catalog/category.html"):
- c = get_object_or_404(Category, slug=category_slug)
+ category_cache_key = request.path
+ c = cache.get(category_cache_key)
+ if not c:
+ c = get_object_or_404(Category.active, slug=category_slug)
+ cache.set(category_cache_key, c, CACHE_TIMEOUT)
products = c.product_set.all()
page_title = c.name
meta_keywords = c.meta_keywords
@@ -33,7 +40,14 @@ def show_category(request, category_slug,
# new product view, with POST vs GET detection
def show_product(request, product_slug, template_name="catalog/product.html"):
- p = get_object_or_404(Product, slug=product_slug)
+ product_cache_key = request.path
+ # get product from cache
+ p = cache.get(product_cache_key)
+ # if a cache miss, fall back on database query
+ if not p:
+ p = get_object_or_404(Product.active, slug=product_slug)
+ # store in cache for next time
+ cache.set(product_cache_key, p, CACHE_TIMEOUT)
stats.log_product_view(request, p)
categories = p.categories.all()
page_title = p.name
View
58 checkout/tests.py
@@ -1,23 +1,39 @@
-"""
-This file demonstrates two different styles of tests (one doctest and one
-unittest). These will both pass when you run "manage.py test".
+from django.test import TestCase, Client
+from django.core import urlresolvers
+from ecomstore.checkout.forms import CheckoutForm
+from ecomstore.checkout.models import Order, OrderItem
+from ecomstore.catalog.models import Category, Product
+from ecomstore.cart import cart
+from ecomstore.cart.models import CartItem
+import httplib
-Replace these with more appropriate tests for your application.
-"""
-
-from django.test import TestCase
-
-class SimpleTest(TestCase):
- def test_basic_addition(self):
- """
- Tests that 1 + 1 always equals 2.
- """
- self.failUnlessEqual(1 + 1, 2)
-
-__test__ = {"doctest": """
-Another way to test that 1 + 1 is equal to 2.
-
->>> 1 + 1 == 2
-True
-"""}
+class CheckoutTestCase(TestCase):
+ def setUp(self):
+ self.client = Client()
+ home_url = urlresolvers.reverse('catalog_home')
+ self.checkout_url = urlresolvers.reverse('checkout')
+ self.client.get(home_url)
+ # need to create customer with a shopping cart first
+ self.item = CartItem()
+ product = Product.active.all()[0]
+ self.item.product = product
+ self.item.cart_id = self.client.session[cart.CART_ID_SESSION_KEY]
+ self.item.quantity = 1
+ self.item.save()
+ def test_checkout_page_empty_cart(self):
+ """ empty cart should be redirected to cart page """
+ client = Client()
+ cart_url = urlresolvers.reverse('show_cart')
+ response = client.get(self.checkout_url)
+ self.assertRedirects(response, cart_url)
+
+ def test_submit_empty_form(self):
+ """ empty form should raise error on required fields """
+ form = CheckoutForm()
+ response = self.client.post(self.checkout_url, form.initial)
+ for name, field in form.fields.iteritems():
+ value = form.fields[name]
+ if not value and form.fields[name].required:
+ error_msg = form.fields[name].error_messages['required']
+ self.assertFormError(response, "form", name, [error_msg])
View
0 marketing/__init__.py
No changes.
View
3 marketing/models.py
@@ -0,0 +1,3 @@
+from django.db import models
+
+# Create your models here.
View
2 marketing/robots.txt
@@ -0,0 +1,2 @@
+User-agent: *
+Disallow:
View
19 marketing/sitemap.py
@@ -0,0 +1,19 @@
+from ecomstore.catalog.models import Product, Category
+from django.contrib.flatpages.models import FlatPage
+from django.contrib.sitemaps import Sitemap
+
+class ProductSitemap(Sitemap):
+ def items(self):
+ return Product.active.all()
+
+class CategorySitemap(Sitemap):
+ def items(self):
+ return Category.active.all()
+
+class FlatPageSitemap(Sitemap):
+ def items(self):
+ return FlatPage.objects.all()
+
+SITEMAPS = {'categories': CategorySitemap,
+ 'products': ProductSitemap,
+ 'flatpages': FlatPageSitemap }
View
23 marketing/tests.py
@@ -0,0 +1,23 @@
+"""
+This file demonstrates two different styles of tests (one doctest and one
+unittest). These will both pass when you run "manage.py test".
+
+Replace these with more appropriate tests for your application.
+"""
+
+from django.test import TestCase
+
+class SimpleTest(TestCase):
+ def test_basic_addition(self):
+ """
+ Tests that 1 + 1 always equals 2.
+ """
+ self.failUnlessEqual(1 + 1, 2)
+
+__test__ = {"doctest": """
+Another way to test that 1 + 1 is equal to 2.
+
+>>> 1 + 1 == 2
+True
+"""}
+
View
19 marketing/urlcanon.py
@@ -0,0 +1,19 @@
+from django.http import get_host, HttpResponsePermanentRedirect
+from ecomstore import settings
+
+class URLCanonicalizationMiddleware(object):
+
+ def process_view(self, request, view_func, view_args, view_kwargs):
+ if not settings.DEBUG:
+ """ only perform the redirect if not debug mode """
+ protocol = 'https://' if request.is_secure() else 'http://'
+ host = get_host(request)
+ new_url = ''
+ try:
+ if host in settings.CANON_URLS_TO_REWRITE:
+ new_url = protocol + settings.CANON_URL_HOST + request.get_full_path()
+ except AttributeError:
+ if host != settings.CANON_URL_HOST:
+ new_url = protocol + settings.CANON_URL_HOST + request.get_full_path()
+ if new_url:
+ return HttpResponsePermanentRedirect(new_url)
View
12 marketing/urls.py
@@ -0,0 +1,12 @@
+from django.conf.urls.defaults import *
+from ecomstore.marketing.sitemap import SITEMAPS
+
+urlpatterns = patterns('ecomstore.marketing.views',
+ (r'^robots\.txt$', 'robots'),
+ (r'^google_base\.xml$', 'google_base'),
+)
+
+urlpatterns += patterns('',
+ (r'^sitemap\.xml$', 'django.contrib.sitemaps.views.sitemap',
+ {'sitemaps': SITEMAPS }),
+)
View
17 marketing/views.py
@@ -0,0 +1,17 @@
+from django.http import HttpResponse
+from ecomstore.settings import CURRENT_PATH
+import os
+from django.template.loader import get_template
+from django.template import Context
+from ecomstore.catalog.models import Product
+
+ROBOTS_PATH = os.path.join(CURRENT_PATH, 'marketing/robots.txt')
+
+def robots(request):
+ return HttpResponse(open(ROBOTS_PATH).read(), 'text/plain')
+
+def google_base(request):
+ products = Product.active.all()
+ template = get_template("marketing/google_base.xml")
+ xml = template.render(Context(locals()))
+ return HttpResponse(xml, mimetype="text/xml")
View
42 search/tests.py
@@ -1,23 +1,21 @@
-"""
-This file demonstrates two different styles of tests (one doctest and one
-unittest). These will both pass when you run "manage.py test".
-
-Replace these with more appropriate tests for your application.
-"""
-
-from django.test import TestCase
-
-class SimpleTest(TestCase):
- def test_basic_addition(self):
- """
- Tests that 1 + 1 always equals 2.
- """
- self.failUnlessEqual(1 + 1, 2)
-
-__test__ = {"doctest": """
-Another way to test that 1 + 1 is equal to 2.
-
->>> 1 + 1 == 2
-True
-"""}
+from django.test import TestCase, Client
+from django.core import urlresolvers
+from django.utils import html
+import httplib
+class SearchTestCase(TestCase):
+
+ def setUp(self):
+ self.client = Client()
+ home_url = urlresolvers.reverse('catalog_home')
+ response = self.client.get(home_url)
+ self.failUnless(response.status_code, httplib.OK)
+
+ def test_html_escaped(self):
+ search_term = '<script>alert(xss)</script>'
+ search_url = urlresolvers.reverse('search_results')
+ search_request = search_url + '?q=' + search_term
+ response = self.client.get(search_request)
+ self.failUnlessEqual(response.status_code, httplib.OK)
+ escaped_term = html.escape(search_term)
+ self.assertContains(response, escaped_term)
View
17 settings.py
@@ -65,8 +65,11 @@
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
+ 'django.contrib.csrf.middleware.CsrfMiddleware',
'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware',
+ 'django.contrib.redirects.middleware.RedirectFallbackMiddleware',
'ecomstore.SSLMiddleware.SSLRedirect',
+ 'ecomstore.marketing.urlcanon.URLCanonicalizationMiddleware',
'djangodblog.middleware.DBLogMiddleware',
)
@@ -91,7 +94,10 @@
'ecomstore.accounts',
'ecomstore.search',
'ecomstore.stats',
+ #'ecomstore.billing',
'tagging',
+ 'django.contrib.sitemaps',
+ 'django.contrib.redirects',
'djangodblog',
)
@@ -127,4 +133,13 @@
PRODUCTS_PER_PAGE = 12
-PRODUCTS_PER_ROW = 4
+PRODUCTS_PER_ROW = 4
+
+CANON_URL_HOST = 'www.django-ecommerce.com'
+CANON_URLS_TO_REWRITE = ['django-ecommerce.com', 'modernmusician.com']
+
+SESSION_AGE_DAYS = 90
+SESSION_COOKIE_AGE = 60 * 60 * 24 * SESSION_AGE_DAYS
+
+# seconds to keep items in the cache
+CACHE_TIMEOUT = 60 * 60
View
2 stats/stats.py
@@ -54,6 +54,8 @@ def log_product_view(request, product):
v = ProductView()
v.product = product
v.ip_address = request.META.get('REMOTE_ADDR')
+ if not request.META.get('REMOTE_ADDR'):
+ v.ip_address = '127.0.0.1'
v.tracking_id = t_id
v.user = None
if request.user.is_authenticated():
View
7 templates/500.html
@@ -0,0 +1,7 @@
+{% extends “base.html” %}
+{% block title %}Internal Server Error – 500{% endblock %}
+{% block site_wrapper %}We’re sorry, but the site you are trying to access is currently
+experiencing problems.
+<br /><br />
+We apologize for any inconvenience. Please try back again later.
+{% endblock %}
View
2 templates/base.html
@@ -12,4 +12,6 @@
</head>
<body>
{% block site_wrapper %}{% endblock %}
+ {% include "marketing/google_analytics.html" %}
+ {% block receipt_analytics %}{% endblock %}
</body></html>
View
20 templates/billing/add_card.html
@@ -0,0 +1,20 @@
+{% extends "catalog.html" %}
+{% block content %}
+ <h1>Add Card</h1>
+ <form method="post" action="{{ request.path }}">
+ <table>
+ {{ form.as_table }}
+ </table>
+ <input type="submit" value="Submit" />
+ </form>
+ <br /><br />
+ Original Post Data: {{ post_data }}
+ <br /><br />
+ Data as JSON: {{ json_data }}
+ <br /><br />
+ Encrypted JSON: {{ encrypted_json }}
+ <br /><br />
+ Decrypted JSON: {{ decrypted_json }}
+ <br /><br />
+ Decrypted Python Dictionary: {{ decrypted_data }}
+{% endblock %}
View
33 templates/checkout/receipt.html
@@ -32,3 +32,36 @@
</tbody>
</table>
{% endblock %}
+{% block receipt_analytics %}
+{% if order %}
+<script type="text/javascript">
+ // IMPORTANT: put your own tracking ID in below
+ var pageTracker = _gat._getTracker('UA-xxxxxxx-1');
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ pageTracker._addTrans(
+ '{{ order.id }}', // order ID (required)
+ '', // store name
+ '{{ order.total }}', // order total (required)
+ '', // order tax
+ '', // order shipping
+ '{{ order.shipping_city }}', // city
+ '{{ order.shipping_state }}', // state or province
+ '{{ order.shipping_country }}'// country
+ );
+// Loop through items in the order
+{% for item in order_items %}
+ pageTracker._addItem(
+ '{{ order.id }}', // order ID (required)
+ '{{ item.sku }}', // product SKU
+ '{{ item.name }}', // product name
+ '', // category
+ '{{ item.price }}', // product price (required)
+ '{{ item.quantity }}' // quantity (required)
+ );
+{% endfor %}
+ pageTracker._trackTrans();
+</script>
+{% endif %}
+{% endblock %}
+
View
10 templates/marketing/google_analytics.html
@@ -0,0 +1,10 @@
+<script type="text/javascript">
+var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
+document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js'
+type='text/javascript'%3E%3C/script%3E"));
+</script>
+<script type="text/javascript">
+try {
+var pageTracker = _gat._getTracker("UA-xxxxxxx-x");
+pageTracker._trackPageview();
+} catch(err) {}</script>
View
34 templates/marketing/google_base.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<rss version ="2.0" xmlns:g="http://base.google.com/ns/1.0">
+<channel>
+ <title>Modern Musician Product Feed</title>
+ <description>Modern Musician Product Feed</description>
+ <link>http://www.django-ecommerce.com/</link>
+{% for p in products %}
+<item>
+<title>{{ p.name }}</title>
+<g:brand>{{ p.brand }}</g:brand>
+<g:condition>new</g:condition>
+<description>{{ p.description }}</description>
+<guid>{{ p.sku }}</guid>
+<g:image_link>{{ p.image.url }}</g:image_link>
+<link>{{ p.get_absolute_url }}</link>
+<g:mpn>ABC123</g:mpn>
+<g:price>{{ p.price }}</g:price>
+<g:product_type>{{ p.categories.all|join:", " }}</g:product_type>
+<g:quantity>{{ p.quantity }}</g:quantity>
+<g:shipping>
+ <g:country>US</g:country>
+ <g:service>Ground</g:service>
+ <g:price>9.99</g:price>
+</g:shipping>
+<g:tax>
+ <g:country>US</g:country>
+ <g:region>CA</g:region>
+ <g:rate>8.75</g:rate>
+ <g:tax_ship>y</g:tax_ship>
+</g:tax>
+</item>
+{% endfor %}
+</channel>
+</rss>
View
4 urls.py
@@ -18,12 +18,14 @@
(r'^accounts/', include('accounts.urls')),
(r'^accounts/', include('django.contrib.auth.urls')),
(r'^search/', include('search.urls')),
+ (r'^', include('marketing.urls')),
+ (r'^billing/', include('billing.urls')),
)
if settings.DEBUG:
urlpatterns += patterns('',
(r'^static/(?P<path>.*)$', 'django.views.static.serve',
- { 'document_root' : static }),
+ { 'document_root' : static }),
)
handler404 = 'ecomstore.views.file_not_found_404'

0 comments on commit 0c051f6

Please sign in to comment.
Something went wrong with that request. Please try again.