This one you won’t believe…

There are quite a bunch of blog posts and the like about how using “network-path reference” aka “protocol-relative” aka “scheme-relative” urls for specifying resources in a web page can spare us a few lines of code.

This technique consist on removing the protocol part (i.e. “http:” or “https:”) of our resource’s url and let the browser fill it in with the same protocol the containing web page has.

this way, we don’t need to worry about “mixed content” security warnings and such things that ie likes to rub in our face every time we try to do something.

instead of:


<link rel="stylesheet" href="http://somedomain.com/style.css"/>
<script type="text/javascript" src="http://somedomain.com/somejs.js">

you write:…


<link rel="stylesheet" href="//somedomain.com/style.css"/>
<script type="text/javascript" src="//somedomain.com/somejs.js"></script>

and, depending on which protocol the page was loaded with, the css or js (or img, if it’s the case) will load with the same protocol.

It’s documented that this should work in all major browser, with a few quirks for ie, of course:

  • ie6 can show a security mixed content warning, depending on certain obscure internet options being stablished or not
  • ie7 and ie8, when asked to load a css with a url like these, will load it twice, but won’t complain about security

But there’s another case in which IE8 will complain about security, and that’s when we try to dynamically load a stylesheet with a protocol-relative url.

This won’t work out clean “out of the box”:..


<script type="text/javascript" src="somedomain.com/jquery.com"></script>
<script>
jQuery('<link/>',{type:'text/css', rel:'stylesheet',href:'//somedomain.com/style.css'});
</script>

When used in a secure page, IE8 will complain about non secure content being loaded, but….


<script type="text/javascript">
var link = jQuery(' <link/>,{type:'text/css', rel:'stylesheet'});
link.appendTo('head');
link.attr('href','//somedomain.com/style.css');
</script>

will work ok!!!

the essential point I think is to actually append the link element in the dom of the page before specifying its href attribute. probably related to some kinky super weird way of checking urls that ie8 does.

hope it helps


When you modify your settings.py file of your Django project on production servers you can get errors like this when updating the code:

$ git fetch
$ git merge origin/master
...
error: Your local changes to 'settings.py' would be overwritten by merge.  Aborting.
Please, commit your changes or stash them before you can merge.
...

The best solution I’ve found was using the stash, a temporary location where you can save your changes to recover them later, resetting your branch to put it in a clean state.

$ git stash save "My local settings.py prod changes"
Saved working directory and index state On master: My local settings.py prod changes
HEAD is now at a318301 That commit message
$ git merge origin/master
Merge made by recursive.
...
5 files changed, 219 insertions(+), 28 deletions(-)
...
$ git stash list
stash@{0}: On master: My local settings.py prod changes
$ git stash apply
Auto-merging settings.py
...
$ git stash drop
Dropped refs/stash@{0} (c00440c6a495cffd2f69de172faf6371c28058cf)

And your changes are back again!


// Symfony 2
public function updateAction($id)
{
  $em = $this->getDoctrine()->getEntityManager();
  $product = $em->getRepository('AcmeStoreBundle:Product')->find($id);
  
  if (!$product) {
    throw $this->createNotFoundException('No product found for id '.$id);
  }
  
  $product->setName('New product name!');
  $em->flush();
  
  return $this->redirect($this->generateUrl('homepage'));
}
# Django
def updateAction(request, id):
    product = Product.objects.get(pk=id)
    # Product.DoesNotExist exception raised if not found
    product.name = u"New product name!"
    product.save()
    return HttpResponseRedirect(reverse('homepage'))

more on this.

Now that we know how to trigger django permission creation mechanism with a fake migration, there is still one more issue. Those permissions are not associated to the right content_type (the one that corresponds to the proxy models), so they are useless in the django admin.

This is related to an old bug in django, by which , when creating a proxy model, the content type object associated to it was the same that the proxy model’s parent, but the admin permission system works using the app_name, so there is a contradiction in there.

On django 1.3 (I can’t tell for earlier versions), there is a new content type object created per each proxy model, but the automatic permissiion creation mechanism doesn’t work right with that. Django keeps creating permissions for the proxy model’s parent class, and the admin framework keeps needing more specific permissions to allow someone in.  This is related to the ContentTypeManager.get_for_model(class) method.

Well, there’s a hack I got from modifying this ticket attachment.:

Say you put all of your proxy models under an app called “customer”, so the “customers” can access a “special admon” in which you can customize several options without having to mutilate your own admon.

What we do is disconnect the default “create_permissions” function from the post_syncdb signal, connect it to our very own custom function, and, in case the “sender” of the signal is other than our particular app (which we know contains only proxy models), then use the old “create_permissions”funcion.

I put this in my customer/models.py

from django.db.models import get_models
from django.db.models.signals import post_syncdb
from django.utils.encoding import smart_unicode

from django.contrib.auth.management import create_permissions, _get_all_permissions

# Hack the postsyncdb signal, so we can fix the misbehavior of the 
# content_type
# assignment to the proxy models. 
# see http://code.djangoproject.com/ticket/11154

def create_permissions_respecting_proxy(
    app, created_models, verbosity, **kwargs
    ):

    if not kwargs['sender'].__name__ == 'customer.models':
        # if not in 'customer' app, then use the original function
        create_permissions(app, created_models, verbosity, **kwargs)
        return

    from django.contrib.contenttypes.models import ContentType
    from django.contrib.auth import models as auth_app
    app_models = get_models(app)
    searched_perms = list()
    ctypes = set()
    for klass in app_models:
        # this is where the difference is: the original create_permissions
        # use ctype = ContentType.objects.get_for_model(klass)
        opts = klass._meta
        ctype, created = ContentType.objects.get_or_create(
            app_label=opts.app_label, 
            model=opts.object_name.lower(),
            defaults = {'name': smart_unicode(opts.verbose_name_raw)}
            )
        # end of the modification
        ctypes.add(ctype)
        for perm in _get_all_permissions(klass._meta):
            searched_perms.append((ctype, perm))

    all_perms = set(auth_app.Permission.objects.filter(
            content_type__in=ctypes
            ).values_list("content_type", "codename"))

    for ctype, (codename, name) in searched_perms:
        if(ctype.pk, codename) in all_perms:
            continue
        p = auth_app.Permission.objects.create(
            codename=codename, name=name, content_type=ctype
            )
        if verbosity >=2:
            print "Adding permission '%s'" % p


post_syncdb.disconnect(
    create_permissions, 
    dispatch_uid='django.contrib.auth.management.create_permissions',
    )

post_syncdb.connect(
    create_permissions_respecting_proxy, 
    dispatch_uid='django.contrib.auth.management.create_permissions',
    )

enjoy.


So much for a post title.

The thing is as follows:

  1. you use migrations for a certain app
  2. in some point at your development, you add proxy models to that app
  3. you need to have specific permissions for that recently created proxy model.
  4. since that app you’re adding the proxy model is not controlled by the syncdb command of django (since it’s on migrations), you can not rely on django’s syncdb command to fix the permissions associated to that model for you.
  5. if you try to run the ‘migrate’ command, nothing happens, no permissions are added, neither any record in django_content_type table.
  6. what’s worst. if you reset the database and start over, then , since migration 0001_initial, the permissions are already there: however , you can not rely on this since you’ve already have a production site going on.
  7. You can not put the data in a data migration either, because, in case the migration is run from 0001 point when the fake models are already defined, it will throw an error when reaching a data migration that tries to reinsert the same data.

Well , what I find as an acceptable solution is the use of send_create_signal in a “fake” migration.

say you have an app which already have 10 migrations run on it. Now you add a proxy model. you create a “fake” schema migration whose only purspose is to send the send_create_signal so the django framework reacts and create the needed content_type and permission records .

In your models.py:

from django.db import models

class TestModel(models.Model):
  ..

class ProxyTestModel(TestModel):
  class Meta:
  proxy=True

and now create an empty schemamigration. this is where you’ll fire the “send_create_signal” event:

class Migration(SchemaMigration):

   def forwards(self, orm):
   # faking proxy model creation
   db.send_create_signal('myapp', ['ProxyTestModel'])

   def backwards(self, orm):
     pass

when you run that migration, it will throw the send_create_signal associated to the model “ProxyTestModel” , in the app “myapp” . the django framework will recognize that and create if they are not created already, the necessary content_type and permissions records on the db.


For those of you that use Textmate here are my favourite bundles and plugins. First of all you should read documentation on how to get more bundles.

GetBundles

This bundle lets you easily find and install other bundles. It’s not so pretty but it works. You can download it with this Terminal.app command:

svn export http://svn.textmate.org/trunk/Review/Bundles/GetBundles.tmbundle

Open the working directory in Finder (open .) and double click the .tmbundle to install it.

You can access GetBundles from the Bundles menu. You will get a window where you will find lots of bundles for different purposes. Sometimes you will find different bundles for the same purpose. It’s up to you to download and install the one that best fit to your workflow.

LESS TextMate Bundle (by Carter Allen)

You can install it from GetBundles. It will save a .css file in the same directory of your .less file, making development easier. It requires the LESS library:

sudo gem install less

And that’s it.

Django Bundles

I use the official Python Django bundle and the Python Django Templates bundle by Paul Bissex. You can install them from GetBundles. They will make your life easier if you develop in Django. They support most of the commonly used syntax for models, templates…

AckMate

This is the Textmate’s Find in Project command with steroids. It shows you what file contains what you were searching for and a small piece of the code around the result with line numbers. You can download it from protocool’s GitHub. I’ve downloaded the 1.1.1 version because of some UTF-8 issues in 1.1.2.

If you have binary files not recognized by ack you will get lots of errors (PDF files, for example). You can edit a .ackrc file in your home directory and put your binary file extensions like this:

--type-set=bin=.pdf .pyc
--nobin

The first line defines the bin type for .pdf and .pyc extensions and the second line deactivates those types in for ack.


For all of you that don’t know what Less CSS is, check this first, but I will try to summarize it in a phrase:

It is a way of writing cleaner CSS code using variables and mixins but with the need of being compiled to an actual CSS file.

Lets see an example of .less file:

@corporate-red: #c00;

a {
  color: @corporate-red;
}

... (1000 lines of code later) ...

blockquote em {
  color: @corporate-red;
}

After compiling it would become:

a {
color: #cc0000;
}

... (1000 lines of code later) ...

blockquote em {
  color: #cc0000;
}

With the advantage that, if we change the value of @corporate-red to #900 we can re-compile and go on, changing only one value.

Ok, ¿how we do benefit of this wonder in symfony?

There are multiple plugins and libraries for symfony but I’m a idle for some things. My quick & dirty solution is not the best because I must update all libs manually, but it was only an experiment that someone less idle than me can use to develop a great updateable symfony plugin.

I used:

First I got the lessphp’s lessc class file (lessc.inc.php) and renamed it to lessc.class.php and moved it into my sf project’s lib directory.

Later I supposed that I could have my .less and my .css files in the same folder and use .less files in development environment and compiled .css files in production so I’ve created a task to recompile manually all .less files in my /css folder.

// lib/task/compileLessTask.class.php

class compileLessTask extends sfBaseTask
{
  protected function configure()
  {
    $this->namespace = "less";
    $this->name = "compile";
    $this->briefDescription = "Compile all .less files into .css files";
  }
  
  protected function execute($arguments = array(), $options = array())
  {
    $dir = sfConfig::get('sf_web_dir')."/css";
    
    // Exclude all *.inc.less from compile
    $lessfiles = sfFinder::type('file')
      ->not_name('*.inc.less')->name('*.less')
      ->in($dir);
    
    $compiler = new lessc();
    $compiler->importDir = $dir."/includes/";
    
    foreach($lessfiles as $lessfile)
    {
      echo "Compiling ".basename($lessfile).PHP_EOL;
      try
      {
        file_put_contents(dirname($lessfile)."/".basename($lessfile, '.less').".css", $compiler->parse(file_get_contents($lessfile)));
      }
      catch (Exception $e)
      {
        echo "Less fatal error: ".$e->getMessage().PHP_EOL;
      }
    }
  }
}

So I can run $ php symfony less:compile in my terminal after a development session.

And finally, we must load different stylesheets if we are in dev environment than in other cases, so I created a LessHelper.php file in my apps/myapp/lib/helper directory:

function use_less_stylesheet($css, $position = '', $options = array())
{
  if ("dev" == sfConfig::get('sf_environment'))
  {
    use_javascript('less-1.0.35.min.js', 'last');
    use_stylesheet(basename($css, '.css').".less", $position, array_merge($options, array('rel' => 'stylesheet/less')));
  }
  else
  {
    use_stylesheet(basename($css, '.less').".css", $position, $options);
  }
}

As you can see I’ve added the LessJS file to my /js folder and loaded the in dev environment.

The problem here is that I cannot get this working through the app-level view.yml file so I’ve done it through a helper taking advantage of the fact that the configuration of assets in view.yml is deprecated in favor of use_javascript and use_stylesheet helpers.

Suppose you’ve done all of this and I forgot nothing, and suppose you have a layout.less file in /css folder and lessjs in /js folder. You would have something like this:

/apps/myapp/lib/helper/LessHelper.php
/apps/myapp/templates/layout.php
/lib/lessc.class.php
/lib/task/compileLessTask.class.php
/web/css/layout.less
/web/js/less-1.0.35.min.js

And in your layout.php you’ve added:

<?php
use_helper('Less');
use_less_stylesheet('layout');
?>

Then if you access your production environment, symfony will add the following line to your document’s head section:

<link rel="stylesheet" type="text/css" media="screen" href="/css/layout.css">

And if you access your dev environment:

...
<link rel="stylesheet/less" type="text/css" media="screen" href="/css/layout.less">
...
<script type="text/javascript" src="/js/less-1.0.35.min.js"></script>

And the JS will generate just after its inclusion:

<style type="text/css" media="screen" id="less:css-layout">
/* THE COMPILED CODE */
</style>

In dev mode code is always compiled. In production you will get your styles if you previously compiled the css with the task we created. Why don’t automatically compile the CSS? Well, it would add complexity and I don’t want it. I’m idle, but I’m not so lazy as to not run the task to update .css files before uploading changes to my version control system.

That’s all! Comments are appreciated.


We have been working for a while with the django framework and we were also early adopters of the symfony framework using it almost from the begining in 2005. So I think I can write some of my thoughts about these two frameworks and try to make some comparisons between them. I’m not gonna try to make an exhaustive and data comparison, but only share my experience and impressions using both of them.

So, the first thing I should say is that both are gorgeous in many aspects. If you are a web developer and still don’t use any framework… man, what are you waiting for?

Documentation is also really good in both of them, and the learning curve, I think is more or less the same.

But all this said, my feeling is that actually django is better, and I’ll try to explain why in the next few lines.

  • First, I think is usually easy to find where the things are. Maybe because you have less files in django that in symfony. In symfony many times you have too many folders and files, and it makes harder to find something.
  • The way django manage forms and submissions is really good. The philosophy in symfony about forms is similar, but they are harder to manage, and usually you have to write so much code to make the things you want with forms.
  • The templates in django is another pretty good feature. Especially the way you can “extend” the templates, the built-in tags and filters and so on. In symfony many times you have the feeling of writing more code when you are writing templates. Some people can see this as an advantage, but that’s not my case.
  • The multiple ways you can do tests in python, especially using doctests is in my opinion another good point for django.
  • And last, the python itself is like more “readable” and quick to write than php.

So, these are my impressions, as I said before these are only impressions, this is not an study about the frameworks. Anyway we continue working with symfony, especially in our open source project siwapp, first because is a really great framework, and secondly because it has many other advantages as well. And we hope the next release of symfony, symfony 2.0, will address many of these lacks and improve the framework in many ways.


Suppose we have HTML code with the following structure:

<body>
  <a id="panel-previous" href="#">previous</a>
  <ul id="panel">
    <li>ad</li>
    <li>adipisicing</li>
    <li>aliqua</li>
    <li>aliquip</li>
    <li>amet</li>
    <li style="display:none;">anim</li>
    <li style="display:none;">aute</li>
    <li style="display:none;">cillum</li>
    <li style="display:none;">commodo</li>
    <li style="display:none;">consectetur</li>
    <li style="display:none;">consequat</li>
    <li style="display:none;">culpa</li>
  </ul>
  <a id="panel-next" href="#">next</a>
</body>

We want to show only five items at once, and we want to show next and previous items in a scrolling-like manner. This approach is based on showing only those items that should remain visible and hiding the others. The other one would be the classical container vs. content divs.

You need jquery, jquery.timers plugin (included in the attachment zip file) and the code we are going to comment now, as a panel.cer.js file in the attachment.

(function($){

  $.fn.cerPanel = function () {
    var speed = arguments.length > 0 ? parseInt(arguments[0]) : 100;
    return this.each(function(){
      var panel = $(this);

      $('#'+panel.attr('id')+'-next').mousedown(function(e){
        $(this).everyTime(speed, 'next', function(i){
          if (panel.children(':visible ~ :hidden').length > 0) {
            panel.children(':visible + :hidden').show();
            panel.children(':visible:first').hide();
          }
        });
      }).mouseup(function(e){
        $(this).stopTime('next');
      }).click(function(e){ e.preventDefault(); });

      $('#'+panel.attr('id')+'-previous').mousedown(function(e){
        $(this).everyTime(speed, 'prev', function(i){
          if (panel.children(':hidden ~ :visible').length > 0) {
            panel.children(':hidden:not(:visible ~ :hidden):last').show();
            panel.children(':visible:last').hide();
          }
        });
      }).mouseup(function(e){
        $(this).stopTime('prev');
      }).click(function(e){ e.preventDefault(); });

    });
  };

})(jQuery);

After the document is loaded you can call:

$('#panel').cerPanel();
$('#panel').cerPanel(mySpeed);

You will notice that in our HTML we defined ‘panel-previous’ and ‘panel-next’ links. You can use any clickable tag.

Those links works similar; we will focus on the ‘next’ link first:

On mouse down a timer starts repeating the same action: if there are more hidden items after a visible one then show the first hidden after a visible item and hide the first visible item. On mouse up stop doing it.

The ‘previous’ link works looking for visible items after a hidden one. If one item matches the condition it shows “the last hidden item that is not located after a visible one” and hides the last visible item.

This is useful when we want to scroll “complete” block items inside a parent block; this is not recommended to scroll text in the usual way.

Download


If you are a web developer, maybe this post title doesn’t say nothing new to you. But I’m really really tired of IE annoyances. Today  I worked extra hours on an ajax problem with IE.

The page I was working on has an ajax call like this one:

<div id="LoginForm"> </div>
<script type="text/javascript">
  new Ajax.Updater('LoginForm',
    '/www.php/login/ajaxForm'),
    {asynchronous:true, evalScripts:false, method:'get'})
</script>

Well, is the typical prototype ajax call. The call updates the “LoginForm” layer with the information of the user: if he is logged or not basically.

Everything works right on every browser. I remark: on every browser, except of course IE. Explorer has the bright idea of use always his cache to fill the layer, so when the user logout, and go to another page, the “ajax call” shows the cached content, and voilá: the user is logged in again!

Here the solution:

<div id="LoginForm"> </div>
<script type="text/javascript">
  new Ajax.Updater('LoginForm',
    '/www_dev.php/login/ajaxForm?rdm='+Math.floor(Math.random()*10000),
    {asynchronous:true, evalScripts:false, method:'get'}) 
</script>

It’s pretty obvious knowing the problem, but anyway is ANOTHER annoyance!

Thank you Microsoft, for these great moments.