Beginning Django E Commerce
398 pág.

Beginning Django E Commerce


DisciplinaProgramação I24.794 materiais282.206 seguidores
Pré-visualização50 páginas
the reverse order in which they opened. Read from 
beginning to end, elements should open and close like a LIFO stack. Open 
Element 1, Open Element 2, Close Element 2, Close Element 1. 
If you\u2019d like to know more about XML and how to create well-formed XML, I\u2019d recommend 
consulting http://www.w3.org/XML/ for more detailed information about the specification. 
Building XML in Python is fairly straightforward. Take the following bit of Python code: 
from xml.dom.minidom import Document 
 
def build_me_some_xml(): 
 doc = Document() 
 # generate the root node. 
 root = doc.createElement('checkout-shopping-cart') 
 # add an attribute to the root node 
 root.setAttribute('xmlns', 'http://checkout.google.com/schema/2') 
 # add this root node to document 
 doc.appendChild(root) 
 # create another node, append to root node 
 shopping_cart = doc.createElement('shopping-cart') 
 root.appendChild(shopping_cart) 
 # return the xml doc to whatever function called it 
 return doc.toxml() 
And you can continue in this fashion, creating new element nodes and appending them as child 
nodes to existing ones, as many levels deep as you desire. This code produces and returns the following 
XML as output: 
<?xml version=&quot;1.0&quot;?> 
<checkout-shopping-cart xmlns=&quot;http://checkout.google.com/schema/2&quot;> 
 <shopping-cart /> 
</checkout-shopping-cart> 
In this case, the shopping-cart element is a self-closing tag because it doesn\u2019t contain any child 
nodes or text. However, this document is nothing more than semantic markup without any content, 
making it about as useful as mammary glands on a bull. However, as a working example, it\u2019s quite useful. 
With this code, all of the methods we need to create our full XML document are there. We can create a 
document, add nodes, and add attributes. 
www.it-ebooks.info
CHAPTER 5 \u25a0 SITE CHECKOUT & ORDERS 
 
114 
 
There are other libraries out there for building XML. I\u2019ve had good experiences with the 
ElementTree3 library, but the standard XML libraries in Python will do for our purposes. If you\u2019ve got 
another library that you want to use to build the document, feel free to use that instead. 
Making HTTP Requests in Python 
The next piece of the puzzle lies in generating an HTTP request, and posting it to a given URL, in Python 
code. Python comes equipped with a library for making these HTTP requests called urllib2, which we\u2019re 
going to use here in order to post our order data to Google\u2019s Checkout API. 
Take this bit of Python code, which illustrates the basics of constructing a POST request (don\u2019t type 
this in, as the code itself will not work): 
import urllib2 
from urllib2 import Request, urlopen 
 
def make_dummy_request(): 
 my_url = 'http://checkout.google.com/whatever/url/to/checkout/' 
 # calls another local function for XML Cart 
 cart_xml = get_cart_xml() 
 # build request with 
 req = Request(url=my_url, data=cart_xml) 
 # set one header, containing content-type 
 req.add_header('Content-Type', 'application/xml; charset=UTF-8') 
 # read the response into a local variable for processing 
 response_data = urlopen(req).read() 
The real heavyweight here is the urlopen() function, which is actually posting the request and its 
corresponding data to the URL we specified, and then reading the response. Coming from the Google 
Checkout API, the response data will be an XML document that contains the URL to which we should 
redirect the user. 
Python comes equipped with a means of detecting exceptions where they might occur, through the 
use of the try keyword. If you expect that some code might raise a particular exception, you can use the 
following syntax in order to anticipate errors: 
try: 
 # code that might raise a HTTPError 
 # exception goes here. 
except HTTPError, err: 
 raise err 
else: 
 # if there was no exception encountered, 
 # run some more code here. 
When we try to open up our request to Google Checkout, we are expecting a couple of possible 
exceptions: HTTPError and URLError. We need to check our code block that is responsible for connecting 
to Google Checkout for these two types of exceptions, in that order, and raise them if they occur. 
Lastly, in our actual request to Google, one of the headers we\u2019re going to attach to our request will 
need to be a base64-encoded string. While this shouldn\u2019t be particularly intimidating, here is the code 
that will encode a string: 
 
3 http://docs.python.org/library/xml.etree.elementtree.html 
www.it-ebooks.info
CHAPTER 5 \u25a0 SITE CHECKOUT & ORDERS 
 
115 
 
import base64 
 
encoded_string = base64.encodestring(my_string) 
Let\u2019s jump back to our user-friendly Google Checkout Merchant home page and start putting these 
pieces together. 
Your Google Merchant ID and Key 
Before we can start coding things up, we need to put a couple of things into our project. When we signed 
up for our sandbox account with Google Checkout, we were issued two things: a Merchant ID and a 
Merchant Key. You can find both of these if you click on the \u201cSettings\u201d tab at the top of the page and 
then click on the \u201cIntegration\u201d link at the left side of the page, as shown in Figure 5-2. 
 
Figure 5-2. Your Google Merchant ID and Key. Keep the Key a secret! 
With this page open, bring up your settings.py module and add the following lines to it: 
GOOGLE_CHECKOUT_MERCHANT_ID = 'your id here' 
GOOGLE_CHECKOUT_MERCHANT_KEY = 'your key here' 
GOOGLE_CHECKOUT_URL = 'https://sandbox.google.com/checkout/ \ufffd 
 api/v2/merchantCheckout/Merchant/' + GOOGLE_CHECKOUT_MERCHANT_ID 
With these entries in your settings.py file, you can now write the code that is necessary for 
integrating with Google Checkout. If you do have values that may change, like the Merchant Key or ID, 
or that are not directly related to the logical code flow or processing that your code is doing, you don\u2019t 
want to stick these values directly in your Python functions. It\u2019s much better to have these values stored 
as constants in a configuration file. That way, later on, if any of these values changes, you won\u2019t need to 
update any of the Python code in your checkout package. You simply need to update the constants in 
your settings.py file. 
The Python Property Decorator 
There\u2019s one last thing I\u2019m going to point out before we implement our checkout. Have a look at the 
following code, which accesses properties on an instance of our CartItem model: 
item = CartItem() 
quantity = item.quantity 
product = item.product 
price = item.price() 
www.it-ebooks.info
CHAPTER 5 \u25a0 SITE CHECKOUT & ORDERS 
 
116 
 
The last item looks a little out of place. We have to do it this way because a call to price is actually a 
call to a method named price(), which we defined in the model: 
def price(self): 
 return self.product.price 
This is simply a means of getting the price of the CartItem\u2019s related product. This is a little strange, 
because while price() is a method, intuitively it makes much more sense as a property, like the rest of 
the fields in the model. 
We can explicitly use the @property decorator on our price() method definition so that we can call it 
like a property instead of a method. So altering the method to this: 
@property 
def price(self): 
 return self.product.price 
actually makes the following call on a model instance valid: 
price = item.price 
While this isn\u2019t necessary, it\u2019s a nice little trick to keep your code a little more consistent and logical. 
Bear in mind that property is read only, and acts only as a \u201cgetter\u201d property. Also, this will break any 
existing calls that use the method syntax of item.price(). This won\u2019t affect us if we change it now, since 
the