about 1 year ago

Found a really good example that explains the differences among bind, call and apply.

Both call and apply attaches this into function and executes the function immediately:

var person = {  
  name: "James Smith",
  hello: function(thing) {
    console.log(this.name + " says hello " + thing);

person.hello.call(person, "world"); // output: "James Smith says hello world"

The difference is that apply can take in an array as the parameters but call has to list them individually:

call(obj, 'arg1', 'arg2', 'arg3');

var args = ['arg1', 'arg2', 'arg3'];
apply(obj, args);

bind only attaches this with a function but id does not execute the function:

var person = {  
  name: "James Smith",
  hello: function(thing) {
    console.log(this.name + " says hello " + thing);

var helloFunc = person.hello.bind(person);
helloFunc("world");  // output: "James Smith says hello world"

You can also pass parameters to bind:

bind(obj, arg1, arg2 ,arg3);

bind is often used to express the intention of "this function is invoked with a particular this".

about 1 year ago
function test() {
  console.log(this);    // window

  function inner(){
    console.log(this);  // window


The this keyword inside the inner() function also refers to the Window object. This is because:

When a function is invoked as a function rather than as a method, the this keyword refers to the global object. Confusingly, this is true even when a nested function is invoked (as a function) within a containing method that was invoked as a method: the this keyword has one value in the containing function but (counterintuitively) refers to the global object within the body of the nested function.

about 1 year ago

I defined two properties (one enumerable and one not enumerable) on a prototype object and two properties on an instance object. I want to see what is the difference among for...in, Object.keys() and Object.getOwnPropertyNames():

function Person(){}

Object.defineProperty(Person.prototype, 'grade', {
  configurable: true,
  enumerable: true,
  writable: true,
  value: '5'

Object.defineProperty(Person.prototype, 'school', {
  configurable: true,
  enumerable: false,
  writable: true,
  value: 'a_school'

var p1 = new Person();

Object.defineProperty(p1, 'name', {
  configurable: true,
  enumerable: true,
  writable: true,
  value: 'test'

Object.defineProperty(p1, 'age', {
  configurable: true,
  enumerable: false,
  writable: true,
  value: 20

for(var prop in p1){
} // name, grade

console.log(Object.keys(p1));                   // name

console.log(Object.getOwnPropertyNames(p1));    // name, age

console.log(p1.hasOwnProperty('name'));    // true

console.log(p1.hasOwnProperty('age'));     // true

console.log(p1.hasOwnProperty('grade'));   // false

console.log(p1.hasOwnProperty('school'));  // false

Here is a summary of which method displays which properties:

Methods Prototype Object Instance Object
Enumerable Not Enumerable Enumerable Not Enumerable
about 1 year ago

To understand what configurable does, I did a little experiement:

var obj = {};
obj.name = 'cheng';
console.log(obj.name); // cheng

Object.defineProperty(obj, 'name', {configurable: false});
var des = Object.getOwnPropertyDescriptor(obj, 'name');
console.log('Writable: ' + des.writable);          // true

console.log('Configurable: ' + des.configurable);  // false

console.log('Enumerable: ' + des.enumerable);      // true

delete obj.name;       // the delete operation returns false

console.log(obj.name); // prints cheng

Object.defineProperty(obj, 'name', {writable: false});
des = Object.getOwnPropertyDescriptor(obj, 'name');
console.log('Writable: ' + des.writable); // false, so it is ok to change writable to false

Object.defineProperty(obj, 'name', {enumerable: false}); // "TypeError: Cannot redefine property: name, which means enumerable cannot be changed if configurable is set to false

I wonder if I can change those properties to true if they started as false:

var obj = {};

Object.defineProperty(obj, 'name', {configurable: false, writable:false, enumerable: false, value:'cheng'});
var des = Object.getOwnPropertyDescriptor(obj, 'name');
console.log('Writable: ' + des.writable);          // false

console.log('Configurable: ' + des.configurable);  // false

console.log('Enumerable: ' + des.enumerable);      // false

Object.defineProperty(obj, 'name', {configurable: true});   // "TypeError: Cannot redefine property: name

Object.defineProperty(obj, 'name', {writable: true});   // "TypeError: Cannot redefine property: name

Object.defineProperty(obj, 'name', {enumerable: true}); // "TypeError: Cannot redefine property: name


When configurable is set fo false:

  • you cannot delete the property by using the keyword delete
  • you cannot change the property enumerable
  • you CAN change the property writable from true to false but not the other way around
  • you cannot change configurable to true if its current state is false
about 1 year ago

I did a little experiment just want to see what's the difference between defining object properties "normally" vs defining them using defineProperty:

var obj = {};
Object.defineProperty(obj, 'name', {value: 'cheng'} );

var des = Object.getOwnPropertyDescriptor(obj, 'name');
console.log('Writable: ' + des.writable);
console.log('Configurable: ' + des.configurable);
console.log('Enumerable: ' + des.enumerable);
console.log('getter: ' + des.getter);
console.log('setter: ' + des.setter);
obj.name = 'test';

var obj2 = { name: 'cheng'};
var des2 = Object.getOwnPropertyDescriptor(obj2, 'name');
console.log('Writable: ' + des2.writable);
console.log('Configurable: ' + des2.configurable);
console.log('Enumerable: ' + des2.enumerable);
console.log('getter: ' + des2.getter);
console.log('setter: ' + des2.setter);
obj2.name = 'test';

Here is the output:

"Writable: false"
"Configurable: false"
"Enumerable: false"
"getter: undefined"
"setter: undefined"
"Writable: true"
"Configurable: true"
"Enumerable: true"
"getter: undefined"
"setter: undefined"


When using defineProperty, you have to define all of the properties by yourself, otherwise they are default to false. But if the properties are define normally, then configurable, enumerable and writable are all default to true.

about 1 year ago

I had a local postfix mail server setup and trying to send an email with the following setting:

EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'localhost'
DEFAULT_FROM_EMAIL = 'TEST <test@blah.com>'

Here is the code responsible for sending the email:

email = EmailMessage(
        cc=applicants + cc_email,
    email.content_subtype = 'html'


Because the mail server is setup locally, there is no need to supply any user name or password. So I didn't bother to specify them in the settings.py. When I had the server running, here is the error that I encountered:

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/home/cheng/.virtualenvs/diandi/lib/python2.7/site-packages/django/core/mail/__init__.py", line 61, in send_mail
    return mail.send()
  File "/home/cheng/.virtualenvs/diandi/lib/python2.7/site-packages/django/core/mail/message.py", line 292, in send
    return self.get_connection(fail_silently).send_messages([self])
  File "/home/cheng/.virtualenvs/diandi/lib/python2.7/site-packages/django/core/mail/backends/smtp.py", line 100, in send_messages
    new_conn_created = self.open()
  File "/home/cheng/.virtualenvs/diandi/lib/python2.7/site-packages/django/core/mail/backends/smtp.py", line 67, in open
    self.connection.login(self.username, self.password)
  File "/usr/local/lib/python2.7.10/lib/python2.7/smtplib.py", line 585, in login
    raise SMTPException("SMTP AUTH extension not supported by server.")
SMTPException: SMTP AUTH extension not supported by server.

The error message is very misleading, but this particular caught my eyes:

self.connection.login(self.username, self.password)

I didn't specify any username and password because I don't think I need them. Maybe I should put them back in? So I added the following lines:


Wholah, it worked! But why? So I looked under the hood:

self.username = settings.EMAIL_HOST_USER if username is None else username
self.password = settings.EMAIL_HOST_PASSWORD if password is None else password

When using the EmailBackend class, a username and password can be passed in as parameters. I didn't pass either of them in my view function. Thus, Django defaults them to settings.EMAIL_HOST_USER and settings.EMAIL_HOST_PASSWORD. However, EMAIL_HOST_USER and EMAIL_HOST_PASSWORD are not defined in the settings file. So by the time self.connection.login(self.username, self.password) is called, both username and password are None.

The error message SMTP AUTH extension not supported by server is generated by python's own smtp library. I guess Django can throw a more meaningful error before this to make this error more apparent.

about 1 year ago

When django template renders parameters passed from views, it auto escapes characters that are considered as HTML entities.In English, that means characters like the double quote is convereted to &quot;. This default behavior may not be what you want so it is important to know how to turn it off.

Here is a situation that I encountered while working on a project. I need to pull all of the staffusers out of the database and then put their email addresses in the following format:

[{'email': 'user1@blah.com'}, {'email': 'user2@blah.com'}, ...]

In the view function, I pull the email addresses out of the database and converted them into JSON format:

def a_view_handler(request):
  contacts = User.objects.get(is_staff=True)
  email_list = []
  for c in contacts:
      if c.email:
          email_list.append({'email': c.email})
  return render(request, 'contacts.html', {'email_list': json.dumps(email_list)}

Then, in the template:

emails = {{ email_list }}

When I tested the page, this is what I see:

emails = [{&quot;email&quot;: &quot;test@test.com&quot;}, ...]

This happened because when python converts the email_list to json, it added double quotes around the key and value pairs. When Django template renders it, it auto escaped the double quote character (meaning convert it to #quot;). To stop Django from doing that:

{% autoescape off %}
    emails = {{ email_list }}
{% endautoescape %}

The autoescape block controls whether the content inside of it should be auto escaped or not. So use it when you dont want to see those HTML entities.

about 1 year ago

The common command line arguments that I use with the netstat command:

-t: display tcp connections
-u: display udp connections
-l: display ports that are in LISTEN state
-p: display process id
-n: display ip addresses instead of host names

To see if a port has been occupied:

> netstat -tulpn | grep :port_number
about 1 year ago

I was trying to start a Postfix mail server on a Ubuntu 12.4:

> service postfix start
* Starting Postfix Mail Transport Agent postfix                                     [ OK ]

> telnet localhost 25
telnet: Unable to connect to remote host: Connection refused

What? I just started the service and it should be running on port 25 but telnet won't connect, so I had to dig more:

> netstat -tulpn | grep :25 | LISTEN

Nothing?! After some Google search, I located the log file at /var/log/mail.err:

> less /var/log/mail.err

fatal: open lock file /var/lib/postfix/master.lock: cannot open file: Permission denied

No Permission? Ok, let's give it the permission:

> chown postfix.postfix -R /var/lib/postfix
> service postfix start
 * Starting Postfix Mail Transport Agent postfix

> netstat -tulpn | grep :25 | grep LISTEN
tcp        0      0    *               LISTEN      22166/master

Great, it worked!

P.S. chown postfix.postfix = chown postfix:postfix = chown owner_name:group_name

about 1 year ago

I have a site which sends out emails through my corporate email account (Outlook), here are the steps need to send emails using Django:

Let's say my username is cheng@blah.com and the password is 123 for my email account.

  1. Make sure the following settings are in your settings.py
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'email.blah.com' # double check the settings in your outlook mailbox to make sure the host name is correct

EMAIL_PORT = 587  # double check the settings in your outlook mailbox and make sure the port number is correct

EMAIL_HOST_USER = 'cheng'  # don't include the @blah.com part! I have made this stupid mistakes before

  1. In your code:
from django.core.mail import EmailMessage
import traceback

def send_email():
    email = EmailMessage(
        to=['someone1@blah.com', 'someone2@blah.com'],
        reply_to=['cheng@blah.com'],  # when the reply or reply all button is clicked, this is the reply to address, normally you don't have to set this if you want the receivers to reply to the from_email address

    email.content_subtype = 'html' # if the email body contains html tags, set this. Otherwise, omit it

        return HttpResponseRedirect(reverse('apply:success'))
    except Exception:
        print traceback.format_exc() # you probably want to add a log here instead of console printout

That should be it :)