Beginning Django E Commerce
398 pág.

Beginning Django E Commerce


DisciplinaProgramação I24.476 materiais278.734 seguidores
Pré-visualização50 páginas
def get_absolute_url(self): 
 return ('catalog_category', (), { 'category_slug': self.slug }) 
 
get_absolute_url = models.permalink(get_absolute_url) 
However, in this book, I\u2019m assuming that you\u2019re using Python 2.5 or higher, and that the code is going to 
remain on development and production machines of your choosing, so we\u2019ll be using the @ decorator 
syntax instead. 
Why is this so useful? Headaches in maintaining web applications usually don\u2019t hit you all at once. 
Instead, they creep up on you slowly over long periods of time. Imagine creating a web site with category 
pages, and you start linking to them from your homepage to allow users to click through and start 
shopping. You define the link to the category page like this: 
<a href=&quot;/category/{{ category_name}}/&quot;>Category Name</a> 
www.it-ebooks.info
CHAPTER 3 \u25a0 MODELS FOR SALE 
 
54 
 
Of course, this link might work fine. It works so well that a week later, when you need to link to the 
category page from another page, such as in your product templates, you use it there, too. Little needs 
for links to category pages within your application start cropping up and you use this solution, and 
pretty soon the /category/{{ category_name}}/ form is everywhere on your site. 
Then one day, you need to change the way these links are all formed. Suddenly, it needs to be 
something like /shop/category/{{ category_name }}/ instead, and you find yourself having to iterate 
through every last page on your site, looking for these old links and updating them to the new form. 
Django\u2019s philosophy is that the models should have as much information about themselves as 
possible. In this case, we\u2019re encapsulating the structure of the internal links to our category pages within 
the Category models themselves. When we need to link to a category, we define the method and use it 
in our application, instead of hard-coding it in a bunch of different templates. 
Defining the link to models in one place, and one place only, is following the DRY principle. This 
stands for \u201cDon\u2019t Repeat Yourself,\u201d which is a programming virtue you should make every effort to 
adhere to. If you find yourself repeating the same work twice, do yourself a favor and stop right there. 
Anything you do in two separate locations might end up being done in three, or four, and so on. Stop, 
and rethink your approach. 
Take a moment and let that information sink in. As a matter of fact, you may feel your brain starting 
to melt after all that code. Get out of your seat, stretch, and grab some coffee. Hang in there and you\u2019ll 
see shortly what\u2019s so great about what we\u2019re doing. 
 Creating the Product Model 
The Product model is a little more complex than the category one, but fortunately, there are a lot of 
parallels between the two, and these should help you get your head around the code. In your models.py 
file, below the declaration of the Category class, enter the following lines of code: 
class Product(models.Model): 
 name = models.CharField(max_length=255, unique=True) 
 slug = models.SlugField(max_length=255, unique=True, \ufffd 
 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, \ufffd 
 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, \ufffd 
 help_text='Comma-delimited set of SEO keywords for meta tag') 
 meta_description = models.CharField(max_length=255, \ufffd 
 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'] 
 
www.it-ebooks.info
CHAPTER 3 \u25a0 MODELS FOR SALE 
 
55 
 
 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 code should make a little bit more sense to you, now that we\u2019ve already walked through the 
Category model. There are a few things you should notice that are new, such as the use of a 
DecimalField to store the product prices. Both of these take two arguments in their declaration: 
max_digits and decimal_places. With a max_digits value of 9, and decimal_places value of 2, we 
store values with 2 decimal places, and up to 7 digits to the left of the decimal point. That means our 
products can be up to $9,999,999.99, which should suit most e-commerce sites, save for the ones that are 
selling commercial airliners. Of course, if you\u2019re selling Boeing 747s, you\u2019re probably not selling a lot of 
them to your customers via a shopping cart web interface. 
You\u2019ll also notice that there\u2019s an additional argument being passed to our old_price field reading 
blank=True. By default, blank is set to False, meaning that all of your model fields require a value of 
some sort, unless you specify otherwise. old_price is the first field where allowing a blank field makes 
sense, because we don\u2019t necessarily want every product to appear as though it\u2019s on sale. We also set a 
default value for this field so that if the user doesn\u2019t enter anything, a value of 0.00 is automatically 
entered into the field. 
Along the same lines, we\u2019ve also created a new method in our Product model: 
 def sale_price(self): 
 if self.old_price > self.price: 
 return self.price 
 else: 
 return None 
This will be used to create a different display in our catalog templates for products that are on sale, 
and those that aren\u2019t. Since we can define a portion of this logic in the model as opposed to in our 
template code (Django templates have their own {% if %} statement tags, as you saw in the last 
chapter), it makes sense to do so to keep the templates as simple as possible. 
Next, we specify a mere string field to store the product image. We\u2019ll come back to this in a later 
chapter, when we cover how to deal with product images. Django actually provides a couple of special 
fields you can add to your models, designed specifically for handling the uploading of files. These are 
ImageField and FileField, which handle images and files. For now, we\u2019ll just use that to store the 
name of the file and use our templates to point to the correct directory where the image resides on our 
file system. 
Boolean fields are extremely handy, and I\u2019ve created two others, on top of the is_active we 
created for our Category model: is_featured and is_bestseller. The only difference with these 
latter two is that they are set to False by default, which makes sense because we expect the bestseller 
and featured labels to apply to only a small handful of products, while we expect almost every product 
in our system to be active. 
www.it-ebooks.info
CHAPTER 3 \u25a0 MODELS FOR SALE 
 
56 
 
True/False fields are an excellent way to manage your products. When you get around to creating 
the home page, you\u2019ll have a box containing some \u201cfeatured products.\u201d By editing a few of your products 
and checking the featured field, you