-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathBeginning django e-commerce=Jim McGaw;Note=Erxin.txt
525 lines (453 loc) · 21.1 KB
/
Beginning django e-commerce=Jim McGaw;Note=Erxin.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
Beginning django e-commerce=Jim McGaw;Note=Erxin
# Introduction
- this book will introduce how to use django build a e-commercial website
- author e-mail
- source code
http://www.apress.com/book/sourcecodee
- why django
lightweight, straightforward
- django relative software in this book
django, 1.1
python, 2.5
mysql, 5.1
eclipse, 3.4.1, with pydev
apache, 2.2
nginx,
mod_wsgi,
ubuntu,
firefox
- version control
git, mercurial
http://subversion.tigris.org/
http://www.git-scm.com/
http://mercurial.selenic.com/wiki/
- firefox add-on, firebug,
http://getfirebug.com
http://addons.mozilla.org/en-US/firefox/addon/966
http://addons.mozilla.org/en-US/exitfirefox/addon/5809
- install base software environment
+ install python
+ install django, djangoproject.com
* check the admin.py
unix, $ /usr/lib/python2.5/site-packages/django/bin/django-admin.py command_here
windows, c:/pythonEnvironment/site-packages/django/bin/django-admin.py command_here
+ mysql
+ eclipse with pydev
- security and accessibility, example amazon.com/access, amazon.com/mobile
- PCI Compliance, stands for payment card industry, a set of recommended practices and guidelines to use
- Shopify is an online provider of e-commerce web applications
- Things to do before start a website
+ security
+ accessibility, consider make the website for
impaired vision, not able to use a mouse, colorblind
using css layout instead of html tables, makeing sure your site degrades gracefully when people have css turned off
+ example
http://www.amazon.com/access
+ PCI stands for Payment Card Industry, and a set of recommanded practices and guidelines to use dealing with customer credit card information
* if you can avoid, you should not storing your customer's credit card information
* make sure you never store or retain the card verification value(CVV)
+ Search engine optimization, (SEO), read google's guidelines http://www.google.com/support/webmasters/
+ Deployment
+ business requirements
* accounting and auditing
revenue recognition principle and matching principle
such as over year record for fiscal year, which called front-loading, you need to established internal policies about when you record sales
* supply chain management
+ marketing decisions
* what is the tone of the criticism being voiced? how are the expressing themselves
* is this a repeat customer or a one-time user
* Feature X for the customer
# Creating a django site
- create the project
$ django-admin.py startproject ecomstore
- boot up your new site by
$ python manage.py runserver
- check the site by
http://127.0.0.1 or http://localhost:8000/
- what django creates
+ open project with eclipse
file|new select pydev project, type project name set the directory as the path to the directory your project is in, click finish
+ files in the folder
__init__.py, tell the python to treated the project as a python module
+ manage.py, help to admin the site
+ urls.py, mapping incoming request to their respective responses, url to physical file
+ settings.py, configuration file
- creating the mysql database
+ create a new database
+ create a new mysql user with a password
+ grant the new mysql user permissions to manipulate the database
mysql> CREATE DATABASE ecomstore CHARACTER SET utf8;
Query OK, 1 row affected (0.00 sec)
mysql> CREATE USER 'username'@'localhost' IDENTIFIED BY 'password';
Query OK, 0 rows affected (0.00 sec)
mysql> GRANT ALL ON ecomstore.* TO 'username'@'localhost';
Query OK, 0 rows affected (0.00 sec)
+ NOTE
mysql offer two different types of engines, MyISAM and InnoDB, by default used MyISAM, ability to handle transactions in an all-or-nothing fashion
InnoDB storage engine was designed for transaction processing
+ don't forget to change mysql's default user which is the root account
+ add setting to create database as UTF-8 to make sure all table are created as UTF-8
- the Django internationalization framework
- Open settings.py file and input
DATABASE_ENGINE = 'mysql'# 'postgresql_psycopg2',...
DATABASE_NAME = 'ecomstore'# Or path to database file...
DATABASE_USER = 'username'# Not used with sqlite3.
DATABASE_PASSWORD = 'password'# Not used with sqlite3.
DATABASE_HOST = ''# Set to empty string for localhost....
DATABASE_PORT = ''# Set to empty string for default...
mysql's default port is 3306
- the manage.py file includes a dbshell utility that will enter a mysql command shell
$ python manage.py dbshell
- dealing with django exceptions
+ use log django exceptions to database package at http://code.google.com/p/django-db-log/
$ python setup.py install
change the settings.py add the django db log middleware module to MIDDLEWARE_CLASS:
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'djangodblog.DBLogMiddleware',
)
to keep things simple we disable sever functions add the Django DB log
INSTALLED_APPS = (
#'django.contrib.auth',
#'django.contrib.contenttypes',
#'django.contrib.sessions',
#'django.contrib.sites',
'djangodblog',
)
back to the shell run this code to create error message database, called djangodblog_error
$ python manage.py syncdb
- template & view basics
+ how django handles request
the request comes to the server
url resolver examines the request and compares it with a set of regular expressions specified in the urls.py files
the request and any additional parameters supplied by the url are passed to the corresponding view function
run relative logic and view function returns a response
+ urls.py file just acts as a dispatcher
+ example
create a python function
def catalog(request):
site_name = "Modern Musician"
response_html = u"<html><body>Welcome to %s.</body></html>" % site_name
return HttpResponse(response_html)
make it usable by add a corresponding entry in our urls.py
urlpatterns = patterns('',
(r'^catalog/$', 'site.views.catalog')
)
+ use django template to replace this sequence, django use special object called Context to manage the template variables, name-value pairs
replace the same function with template
<html><body>Welcome to {{ site_name }}.</body></html>
def catalog(request):
my_context = Context({ 'site_name': 'Modern Musician' })
response_html = return_to_string('sample.html', my_context)
return HttpResponse(response_html)
you create a context object and pass it a dictionary with name of your site, the {{}} is used to define template variables
- Advanced Templates with Inheritance
django templates should be three levels deep
+ first level, contains all of the elements that are common to all html pages on your site
+ django template block in a parent template are spaces reserved for content in the child templates
{%block site_warpper%}{%endblock%}
{%%} symbol pair allows you to place code logic into template
+ example
all templates are saved at the project's templates folder
create a base.html file contains
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>
{% block title %}
{% if page_title %}
{{ page_title }} - {% endif%} {{ site_name }}
{% endblock %}
</title>
<meta name="keywords"content="{{ meta_keywords }}"/>
<meta name="description"content="{{ meta_description }}"/>
</head>
<body>
{% block site_wrapper %}{% endblock%}
</body>
create a new file called catalog.html
{% extends "base.html" %}
{% block site_wrapper %}
<div id="main">
<a href="#content" class="skip_link">Skip to main content</a>
<div id="banner">
<div class="bannerIEPadder">
<div class="cart_box">
[link to cart here]
</div>
Modern Musician
</div>
</div>
<div id="navigation">
<div class="navIEPadder">
[navigation here]
</div>
</div>
<div id="middle">
<div id="sidebar">
<div class="sidebarIEPadder">
[search box here]
<br />
[category listing here]
</div>
</div>
<div id="content">
<a name=”content”></a>
<div class="contentIEPadder">
{% block content %}{% endblock%}
</div>
</div>
</div>
<div id="footer">
<div class="footerIEPadder">
[footer here]
</div>
</div>
</div>
{% endblock %}
the {% extends "base.html"%} tells django this catalog is inherit from the base.html
- create ease with render_to_response()
+ views.py in the app folder
from django.shortcuts import render_to_response
def home(request):
return render_to_response("index.html")
add url mapping
urlpatterns += patterns('',
(r'^catalog/$', 'preview.views.home')
)
start the server
$python manage.py runserver
make it a point to check your site during the various stages of development to ensure that the layout looks okay
- adding the css
create a directory at your project called static, and create a file called css.css
- The creators of Django believe that for scalability reasons, the server that is serving your site's page shouldn't be the server that is hosting and serving up your static media
- use regex compare in the urls.py is due to user may input wrong or abandon url when this happens, the application will direct to the right page
- use css import in another file
@import '*.clss'
- location, python have a simple function to return the path to the current directory as a string
os.path.abspath(os.path.dirname(__file__).decode('utf-8'))
- a site navigation
+ the base template's place holder reading [navigation here] will be replaced by a set of anchor elements
create a new file inside of your /templates/tags called navigation.html. put the following HTML into that file
<ul>
<li><a href="/catalog/">Home</a></li>
<li><a href="/catalog/">About</a></li>
<li><a href="/catalog/">Privacy</a></li>
<li><a href="/catalog/">Products</a></li>
<li><a href="/catalog/">Contact</a></li>
</ul>
<div class="cb"></div>
open your project's css file and add in the following styles for our navigation lists of hyperlinks
#navigation{
width:900px;
height:auto;
background-color:#98AC5E;
text-align:middle;
}
#navigation ul{
list-style:none;
}
#navigation ul li{
float:left;
margin-right:15px;
}
#navigation ul li a{
color:White;
font-weight:bold;
text-decoration:underline;
}
#navigation ul li a:hover{
color:#616161;
background-color:White;
text-decoration:none;
}
use template include, open up your catalog.html and find the place hoder for the navigation, replace with the
{% include 'tags/navigation.html' %}
django project looking for template file not contain the subdirectories
update the settings.py file change the DEBUG to False after deployment
server fault file are shown in the this case when server encounter exception, named 404.html and 500.html
- a word about urls
+ apache's mod_rewrite function to make your urls look better, django has a similar functionality
it's useful when you are dealing with a shared hosting environment and you are not allowed to tweak the apache conf files directly
# Models for sale
- database 101, in django based on a few simple assumptions
+ one business tier class mapped to one table in the database
+ one business tier object instance is mapped to one record in the database table
+ there are a limited number of things you can do to manipulate your data, based on the CRUD commands we covered earlier
- django ORM hands off the request to the relation database
- creating the catalog app
the checkout app would contain models for order information and views for your site's checkout process
- creating the django models
- draw a sketch for your page
+ draw a page layout and display items
+ add anything you don't see on you sketch
- Model field data types
+ charfield, store text that is less than or equal to some determinate length
+ textfield, store large amounts of text that you don't want to restricted by length, such as product description
+ slugField, specialized text field that is designed to be used in the URLs, they'll access a URL reading /products/product-name-here/ in order to request your product, this value should be unique to each product
the reason to use slugField is due to prevent content theft
+ decimalFields, is used to store monetary values
- creating the category model
+ create and open models.py file add the following code to the file
from django.db import models
class Category(models.Model):
name = models.CharField(max_length=50)
slug = models.SlugField(max_length=50, unique=True,
help_text='Unique value for product page URL, created from name.')
description = models.TextField()
is_active = models.BooleanField(default=True)
meta_keywords = models.CharField("Meta Keywords”,max_length=255,
help_text='Comma-delimited set of SEO keywords for meta tag')
meta_description = models.CharField("Meta Description",
max_length=255,
help_text='Content for description meta tag')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
db_table = 'categories'
ordering = ['-created_at']
verbose_name_plural = 'Categories'
def __unicode__(self):
'''
django will fall back on this method whenever your refer to a particular category object in a context is needed
'''
return self.name
;# this tells django this method is used to generate links
@models.permalink
def get_absolute_url(self):
return ('catalog_category', (), { 'category_slug': self.slug })
the meta class is created for any additional information for metadata
Defining the link to models in one place, and one place only, is following the DRY principle.
- create the product module
class Product(models.Model):
name = models.CharField(max_length=255, unique=True)
slug = models.SlugField(max_length=255, unique=True,
help_text='Unique value for product page URL, created from name.')
brand = models.CharField(max_length=50)
sku = models.CharField(max_length=50)
price = models.DecimalField(max_digits=9,decimal_places=2)
old_price = models.DecimalField(max_digits=9,
decimal_places=2,
blank=True,
default=0.00)
image = models.CharField(max_length=50)
is_active = models.BooleanField(default=True)
is_bestseller = models.BooleanField(default=False)
is_featured = models.BooleanField(default=False)
quantity = models.IntegerField()
description = models.TextField()
meta_keywords = models.CharField(max_length=255,
help_text='Comma-delimited set of SEO keywords for meta tag')
meta_description = models.CharField(max_length=255,
help_text='Content for description meta tag')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
categories = models.ManyToManyField(Category)
class Meta:
db_table = 'products'
ordering = ['-created_at']
def __unicode__(self):
return self.name
@models.permalink
def get_absolute_url(self):
return ('catalog_product', (), { 'product_slug': self.slug })
def sale_price(self):
if self.old_price > self.price:
return self.price
else:
return None
This is the field that defines the relationship between your Productand Categorymodels.
categories = models.ManyToManyField(Category)
- Django admin interface
add required application to use admin interface, change the settings.py
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'ecomstore.catalog',
'django.contrib.admin',
'djangodblog',
)
edit urls.py
;# Uncomment the next two lines to enable the admin:
from django.contrib import admin
admin.autodiscover()
;# Uncomment the next line to enable the admin:
(r'^admin/', include(admin.site.urls)),
- product and category admins
from django.contrib import admin
from ecomstore.catalog.models import Product, Category
from ecomstore.catalog.forms import ProductAdminForm
class ProductAdmin(admin.ModelAdmin):
form = ProductAdminForm
;# sets values for how the admin site lists your products
list_display = ('name', 'price', 'old_price', 'created_at', 'updated_at',)
list_display_links = ('name',)
list_per_page = 50
ordering = ['-created_at']
search_fields = ['name', 'description', 'meta_keywords', 'meta_description']
exclude = ('created_at', 'updated_at',)
;# sets up slug to be generated from product name
prepopulated_fields = {'slug' : ('name',)}
# registers your product model with the admin site
admin.site.register(Product, ProductAdmin)
class CategoryAdmin(admin.ModelAdmin):
;#sets up values for how admin site lists categories
list_display = ('name', 'created_at', 'updated_at',)
list_display_links = ('name',)
list_per_page = 20
ordering = ['name']
search_fields = ['name', 'description', 'meta_keywords', 'meta_description']
exclude = ('created_at', 'updated_at',)
;# sets up slug to be generated from category name
prepopulated_fields = {'slug' : ('name',)}
admin.site.register(Category, CategoryAdmin)
- model validation
django allows to hook up custom validation to its admin interface forms
create a custom form
from django import forms
from ecomstore.catalog.models import Product
class ProductAdminForm(forms.ModelForm):
class Meta:
model = Product
def clean_price(self):
if self.cleaned_data['price'] <= 0:
raise forms.ValidationError('Price must be greater than zero.')
return self.cleaned_data['price']
declare one method that actually performs the validation. These methods take the form of clean_[field name]. Because our field is called price, we create a method named clean_price.
- syncing up the models
project validation by
$ python manage.py validate
The next one allows you to get a look at the Data Definition Language (DDL) output that Django will run on your database in order to create the tables. This is how Django talks to your database
$ python manage.py sqlall catalog
use this to create database
$ python manage.py syncdb
manually create superuser
$ python manage.py createsuperuser
check the admin page
http://server/admin/
- playing with module structure and data
- templates, urls and views
create urls mapping file
from django.conf.urls.defaults import *
urlpatterns = patterns('ecomstore.catalog.views',
(r'^$','index',{'template_name':'catalog/index.html'}, 'catalog_home'),
(r'^category/(?P<category_slug>[-\w]+)/$',
'show_category', {'template_name':'catalog/category.html'},'catalog_category'),
(r'^product/(?P<product_slug>[-\w]+)/$',
'show_product', {'template_name':'catalog/product.html'},'catalog_product'), )
- configuring page titles and meta tags
for search engine optimization, you should make sure each pages has at least a distinct page title(SEO)
create new app and add new app into settings.py under the INSTALLED_APPS
copy the TEMPLATE_CONTEXT_PROCESSORS section out of your global_settings.py file and paste it somewhere inside your project's settings.py file
TEMPLATE_CONTEXT_PROCESSORS = (
'django.core.context_processors.auth',
'django.core.context_processors.debug',
'django.core.context_processors.i18n',
'django.core.context_processors.media',
'ecomstore.utils.context_processors.ecomstore',
)
- coding up the catalog views