Pages

Saturday, May 18, 2013

Busy

Sorry, I cannot answer all your questions. These past few days I've been busy in my work. I do not know if I can post more codes here or be active in this blog. Sometimes I forgot to visit here. 

It's time to learn on your own even if it is difficult.

Thanks to all your questions and for being active in this blog. I hope you learn a lot...

Thursday, May 16, 2013

Django 1.5 - Upgrade url tags

In Django 1.5 url tags require you to pass in the name of the url as a string.

So where you used to be able to do this {% url home_page %} you now have to do this {% url 'home_page' %}

Upgrading an old project can be a pain, so here is a snippet for a py file that will update all your url tags. Just put it in a py file in your root directory and execute it.

The error you get otherwise is: 'url' requires a non-empty first argument. The syntax changed in Django 1.5, see the docs.



import os, re

app_path = os.path.split(os.path.split(__file__)[0])[0]
PROJECT_ROOT = os.path.abspath(app_path)

def update_path(directory):
 "Update {% url to include ''"
 for path, dirs, files in os.walk(directory):
  for fname in files:
   if fname.endswith('.txt') or fname.endswith('.html'):
    fpath = os.path.join(path, fname)
    with open(fpath) as f:
     s = f.read()
    s = re.sub(r'{% url "(\w+)" ', r"{% url '\1' ", s)
    s = re.sub(r'{% url (\w+) ', r"{% url '\1' ", s)
    with open(fpath, "w") as f:
     f.write(s)
  for dir in dirs:
   update_path(dir)
update_path(PROJECT_ROOT)


by Craterdome

How to know if your using a smartphone?

It's very important to us to make our site compatible in a mobile device. There are some functions that are not effective if your using a mobile. So you have to do is determine first what mobile device is the user using and add the functions there.


<script>
    $(document).ready(function(){
        if( /iPhone/i.test(navigator.userAgent) ) {
            //add functions here
            alert('iPhone');
        }else if( /iPad/i.test(navigator.userAgent) ) {
            //add functions here
            alert('iPad');
        }else if( /Android/i.test(navigator.userAgent) ) {
            //add functions here
            alert('Android');
        }else{
            //leave null
        }
    });
</script>

Tuesday, May 14, 2013

Reducing Bottleneck - Capped efficient count paginator

This is the result of discovering how slow a COUNT(*) is in PostgreSQL on large tables, even with a WHERE clause (indexed) and a LIMIT.


from django.core.paginator import Paginator
from django.db import connections
from django.db.models.query import EmptyQuerySet, QuerySet
from django.db.models.sql import EmptyResultSet


class CappedPaginator(Paginator):
    """
    Django Paginator subclass that evaluates COUNT in a cheaper way for large
    tables (100K plus).

    This reduced count queries from ~800ms to 12ms on a table containing 500K rows.

    The idea is to change a query like:

        SELECT COUNT(*) FROM "my_table" WHERE "my_table"."col" = 10 LIMIT 1000;
    to:
        SELECT COUNT(*) FROM
            (SELECT * FROM "my_table" WHERE "my_table"."col" = 10 LIMIT 1000)
            AS object_list;

    which is a much faster query on large tables in PostgreSQL.

    """

    hard_limit = 1000

    def _get_queryset_count(self, queryset):
        """
        Efficiently counts queryset after limiting it.

        The count_sql is formed using format, this is on purpose. The idea is
        that the SQL being added to the count comes from queryset.

        The format is forming the SQL query part, no params should be there.
        """
        if isinstance(queryset, EmptyQuerySet):
            return 0
        sliced = queryset[:self.hard_limit]
        try:
            sql, params = sliced.query.get_compiler(queryset.db).as_sql()
        except EmptyResultSet:
            return 0
        count_sql = 'SELECT COUNT(*) FROM ({0}) AS object_list'.format(sql)
        cursor = connections[queryset.db].cursor()
        cursor.execute(count_sql, params)
        result = cursor.fetchone()
        cursor.close()
        return result[0]

    def _get_count(self):
        """
        Returns the total number of objects across all pages.

        If the number is > self.hard_limit, self.hard_limit is returned.
        """
        if self._count is None:
            if isinstance(self.object_list, QuerySet):
                self._count = self._get_queryset_count(self.object_list)
            else:
                self._count = len(self.object_list)
            self._count = min(self._count, self.hard_limit)
        return self._count

    count = property(_get_count)



by hassa

Django 1.5 - utf8-friendly dumpdata management command (no escape symbols)

# serializers/json_pretty.py
"""
Add the line to settings.py::

    SERIALIZATION_MODULES = {'json-pretty': 'serializers.json_pretty'}

And call dumpdata as follows::

    ./manage.py dumpdata --format=json-pretty <app_name>

"""

from django.core.serializers.json import Serializer as JSONSerializer


class Serializer(JSONSerializer):
    def start_serialization(self):
        super(Serializer, self).start_serialization()
        self.json_kwargs['ensure_ascii'] = False



by Inductor

Python 3 - New Features

- Composite string formatting
"{:10s} {:10d} {:10.2f}".format(name, shares, price)

- Dictionary comprehensions

a = {key.upper():value for key,value in d.items()}

- Function annotations

def square(x:int) -> int:
      return x*x

Saturday, May 11, 2013

Sending Unicode emails in Python

Sample:

# U+263A and U+263B are smiley faces (☺ and ☻)
sender = u'Sender \u263A <sender@example.com>'
recipient = u'Recipient \u263B <recipient@example.com>'
subject = u'Smile! \u263A'
body = u'Smile!\n\u263B'
send_email(sender, recipient, subject, body)


Solution:

from smtplib import SMTP
from email.MIMEText import MIMEText
from email.Header import Header
from email.Utils import parseaddr, formataddr

def send_email(sender, recipient, subject, body):
    """Send an email.

    All arguments should be Unicode strings (plain ASCII works as well).

    Only the real name part of sender and recipient addresses may contain
    non-ASCII characters.

    The email will be properly MIME encoded and delivered though SMTP to
    localhost port 25.  This is easy to change if you want something different.

    The charset of the email will be the first one out of US-ASCII, ISO-8859-1
    and UTF-8 that can represent all the characters occurring in the email.
    """

    # Header class is smart enough to try US-ASCII, then the charset we
    # provide, then fall back to UTF-8.
    header_charset = 'ISO-8859-1'

    # We must choose the body charset manually
    for body_charset in 'US-ASCII', 'ISO-8859-1', 'UTF-8':
        try:
            body.encode(body_charset)
        except UnicodeError:
            pass
        else:
            break

    # Split real name (which is optional) and email address parts
    sender_name, sender_addr = parseaddr(sender)
    recipient_name, recipient_addr = parseaddr(recipient)

    # We must always pass Unicode strings to Header, otherwise it will
    # use RFC 2047 encoding even on plain ASCII strings.
    sender_name = str(Header(unicode(sender_name), header_charset))
    recipient_name = str(Header(unicode(recipient_name), header_charset))

    # Make sure email addresses do not contain non-ASCII characters
    sender_addr = sender_addr.encode('ascii')
    recipient_addr = recipient_addr.encode('ascii')

    # Create the message ('plain' stands for Content-Type: text/plain)
    msg = MIMEText(body.encode(body_charset), 'plain', body_charset)
    msg['From'] = formataddr((sender_name, sender_addr))
    msg['To'] = formataddr((recipient_name, recipient_addr))
    msg['Subject'] = Header(unicode(subject), header_charset)

    # Send the message via SMTP to localhost:25
    smtp = SMTP("localhost")
    smtp.sendmail(sender, recipient, msg.as_string())
    smtp.quit()



by Marius Gedminas