Tuesday, April 28, 2015

Site Performance: CDN vs Local Hosting

In a few posts here, we will explore how to improve the site performance and scale.

To begin with one of the easiest performance boost to page loads is to source your standard libraries from CDN whenever possible instead of sourcing them from your server.

WHAT
A CDN, Content Delivery Network, is a set of servers spread across the globe that host content and have an optimized algorithm to serve the content efficiently. So most of your standard libraries like jQuery should be loaded from CDN.

WHY
The advantages of using CDN for your standard scripts are:
  1. Better Caching: No matter how optimized your site is, the user will have to download the library once at least. But, if you use a popular CDN, and if your user has already visited another site that referenced the same library, the library has already been downloaded into the browser's cache. So it will not be downloaded again. This creates a cool cross-site caching effect. 
  2. Lower Load and More Parallelizing: Browsers typically limit number of simultaneous connections from one server. Loading libraries from a CDN server means one less connection to your server for that library. This translated to lower loads to your server, but more importantly, it also frees up the connections that this library load would have used to loading your actual content.
  3. Decreased Latency: CDNs are typically optimized to serve content efficiently based on location. Meaning that the content will be served from the CDN server that can serve it the fastest. You will have to invest fairly well in infra to achieve that kind of optimization.
WHICH
The main CDN providers are cdnjs and Google CDN, along with Microsoft for ASP. Google CDN is the most widely deployed. However, cdnjs has some libraries that Google does not provide. 

HOW
Using CDN is simple. Just direct your script statement to load from Google instead of loading from your server copy.

<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/jquery-ui.min.js></script>

Notice that we use https. Many CDNS also accept just // and then translate that to http or https depending on what your site uses. However, by using https, you can ensure that no one can get in between you and Google and tamper the libraries. So even if your site is un-encrypted http, use https while loading the CDN libraries.

And finally, you may yet want the browser to go to your local server copy in case your CDN is unavailable. While chances of CDNs being unavailable are low, you may hit unfortunate events like library moving behind a paywall, changing its URL location, and such. So it is prudent to have a fallback. To do that just add a check to see if the library was loaded, and if not, load yours.

<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/jquery-ui.min.js"></script> <script> 
if (!window.jQuery) 
    document.write('<script src="/path/to/local/jqueryui/1.8.18/jquery-ui.min.js"><\/script>');
</script>

Make sure you don't write </script> anywhere within the <script> element as it will close the HTML and cause the script to fail. So notice that we escaped it using a backslash <\/script> in the closing script element of the documentWrite



Read More

Thursday, March 26, 2015

Some Useful Web Development Tools

In course of working and learning, we all discover some useful tools that just make life easier. But the net is a big place. And usual venues of information sharing - meeting at conferences and swapping tidbits doesn't happen all the time. So am trying to write down a list of webdev tools, and other general tools that I found useful.

There is a lot of choice out there for most tools. So I have included the one we use, and a few others that we evaluated. To begin with,

General Resources
Web Frameworks
  • Django: This is probably redundant here, given that we have been talking of Django all the time. Basically, Python based web framework.
  • Ruby on Rails
  • ASP.NET
CSS Frameworks
JavaScript Libraries
  • jQuery: Nifty JavaScript library that makes html document traversing, event handling and ajax simpler
  • YUI
JavaScript Frameworks
  • Backbone with Marionette: Backbone is awesome when you have a fairly interactive application. Helps you manage the client data display and event handling in a MVC fashion. Marionette is another library that makes backbone easier. Now, just to note, there are many more JavaScript Frameworks coming along. Back when we were evaluating, it was Backbone, Angular and Ember. But by the time I publish this post, this list will probably be outdated. :-)
  • AngularJS
  • Ember
  • Meteor
  • NodeJS
  • ReactJS
Code Editors
Okaym. We are a Vi shop. But for what its worth, there are these awesome 
Module Loaders
Won't make a recommendation here since we are not yet convinced that out choice is working for us yet :) But you have Module Loader Comparison + Pros / Cons to help out
Build Tools
Know of an awesome tool? Leave a comment!

Read More

Wednesday, November 7, 2012

Writing Custom Template Tags in Django

Django templates are the view part of the Django MVC. So, the templates should just handle the display part and any login in templates should be kept to a minimum. However, there are times when we just have to include logic in the templates, and using template tags is the most elegant way to handle this. Creating your own custom template tags is fairly simple.

One template tag needed often is to get the value from a dictionary.

We like passing dictionaries to templates because dictionaries keep everything readable, especially when I have a long list of parameters to pass to the template. Django templates have no in-built mechanism to retrieve a specific key from the dictionary. So we will write our custom template tag to do that.

Create a directory tempatetags/ under your apps directory. In this directory create a file custom_filters.py.

from django import template

register = template.Library()

@register.filter('key')
def key(d, key_name):
    try:
       value = d[key_name]
    except KeyError:
       # handle the error
       raise Http404  
    return value


Now, from views.py, we pass a dictionary to the template. Say
valdict = {'parent':'Mr John Doer', 'child1':'Emily Doer', 'child2':'Mark Doer'}

To access the dictionary keys in the template we do,

template.html.

{% load custom_filters %}

{% block main_content%}
Parent: {{ valdict|key:parent }}
Child1: {{ valdict|key:child1 }}
Child2: {{ valdict|key:child2 }}
{% endblock %}


Read More

Thursday, June 7, 2012

Testing PayPal on Website


PayPal provides a testing tool called PayPal Sandbox to test website's PayPal's deployment. We can create pseudo buyer and seller accounts, provide the accounts with pseudo money and cards, and test the transaction and user experience. All this without putting up real money or fees. They have a User's Guide here. However, the basic steps are simple:
  • Create a Sandbox account first with some email other than the regular PayPal email. 
  • Login to the account. 
  • Inside this account, click on 'Create Preconfigured Account" and create a couple of buyer accounts and one seller account. Once these accounts are created, they are assigned a randomly generated email address. This is the login email address for that account.
  • Now, click on the radio button near buyer's account and then click on "Enter Sandbox Test Site" button below the form. This will direct you to login with buyer's generated email account and password. Without this step, Paypal will not recognize the buyer's sandbox account when we try to psedo-pay the seller later. 
  • In the website's code where the PalPal form was created, set the business email address to the sandbox's seller account's generated email address.
    <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
      <input name="business" type="hidden" value="seller_45681279_biz@mywebsite.com" />
      <input name="cmd" type="hidden" ...
    </form type="submit" value="PayPal">
  • Once the Sandbox seller account is set as business, all the payments go to that account, and no fees are charged
  • Now, go through the buyer's transaction. When Paypal asks for login to pay, use the Sandbox buyer generated email and pwd and login to pay with the Sandbox buyer. 
Thus the complete website flow can be tested. To check the emails PayPal will send to your account on completion of transaction, click on 'Test Email' link in Sandbox nav-bar.

Normally Sandbox transactions do not go through IPN. However, Sandbox provides separate hooks to test this. Go to the 'Test Tools' bar in the Sandbox nav-bar. Here they have IPN Simulator with which the all the different configurations of IPN can be tested.
Read More

Wednesday, June 6, 2012

Paypal Shopping Cart

PayPal's documentation has really very subtle hints about what needs to be done to get Paypal working for a website, and you need to plough through a lot of links to figure out anything useful.

On sign up, they take the user to a page with customizable buttons for Buy Now, Subscribe, Shopping Cart. Now, if the site has only one item to sell, it should use the 'Buy Now', if it is selling subscriptions, use the Subscription Button. For a site that sells multiple items and needs a shopping cart, Paypal has tied up with some Shopping Cart providers.

There is however an option of creating your own light weight shopping carts. Its called Third Party Shopping Cart. This is especially useful when a website is just starting out and it doesn't need the whole armada of a formal Shopping Cart, but it needs something beyond a Buy Now or Subscription Button.

To create your own shopping cart, we need to have a list of items, quantities and price. Then we pass it to Paypal as follows:

<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
    <input type="hidden" name="cmd" value="_cart">
   <input type="hidden" name="upload" value="1">
   <input type="hidden" name="business" value="seller@mywebsite.com">
   <input type="hidden" name="item_name_1" value="Item Name 1">
   <input type="hidden" name="amount_1" value="1.00">
   <input type="hidden" name="quantity_1" value="2">
   <input type="hidden" name="shipping_1" value="1.75">
   <input type="hidden" name="item_name_2" value="Item Name 2">
   <input type="hidden" name="amount_2" value="2.00">
   <input type="hidden" name="quantity_2" value="3">
   <input type="hidden" name="shipping_2" value="2.50">
   <input type="submit" value="PayPal">
</form>


The suscript-ing numbers item_name_1, amount_1 all refer to the first item on list. There are other options like tax_x, handling_x, discount_amount_x, weight_x. The value of x must increase by 1 for each new item in the cart.

There are some options that can be applied to the entire cart like: currency can be specified with hidden currency, units of weight can be given as weight_unit, tax can be calculated for the entire cart instead of per-item by using tax_cart, discount_amount_cart to charge a single discount amount for the entire cart, discount_rate_cart to give a discount percentage for the entire cart.

This will display a PalPal button on the site. Clicking on that button takes the user to PayPal's site where it shows the list of all the items purchased and the total quantity, and invites the user to pay using the PayPal account or a credit card.

To make Paypal really integrate with a website though, the website needs IPN or PDT.  Stackoverflow has a good discussion on which one to use. We use IPN and are happy with it so far.
Read More

Thursday, May 24, 2012

Adding placeholders, autofocus and other attributes to Django forms

Placeholder is a short hint (a word or short phrase) intended to aid the user with data entry in forms. With HTML5, adding placeholders to forms is as simple as including a keyword:

<label>Name: <input name="name" placeholder="John Doe" type="text" /></label>

This would appear in the form as:

  

To add placeholders to Django forms, simply specify placeholder as an attribute to the form widget.

  name = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'John Doe'})

This is actually a pretty general and useful way of passing attributes to Django forms. We can pass other attributes like 'autofocus':'autofocus'. Autofocus is when we want the form field to be in focus automatically when the page loads.

This is for forms created in our app's own forms.py. If we want to pass attributes to forms created by a Django package, we have to pass those attributes at the form's init.

Say, to add attributes to a form called RegistrationForm from some Django package with fields username and password, first create a form in project's forms.py that inherits RegistrationForm. In the __init__ function of the inherited form, pass all the attributes to the form widgets.

class MyRegistrationForm(RegistrationForm):
    def __init__(self, *args, **kwargs):          
        super(MyRegistrationForm, self).__init__(*args, **kwargs)
        self.fields['username'].widget.attrs['placeholder'] = u'Username'
        self.fields['password'].widget.attrs['placeholder'] = u'Password'


Now while using the form, use it as
form = MyRegistrationForm()

This will display base form with the attributes passed to to it at init.
Read More

Wednesday, May 23, 2012

Changing Django Password

Go to the directory where your settings.py resides:

$ python manage.py shell
>>from django.contrib.auth.models import User
>> users = User.objects.all()
>> users
(output) [<User: foo>, <User: adminlogin>, <User: bar>]
>> user = User.objects.filter(name='adminlogin')
>> user.set_password('newpassword')
>> user.save()

This can be used to do most user object management.
Read More