Thursday, February 26, 2009

minor touches

Some minor changes could be made to the Ajax live bookmark search example on page 109 of the book Learning Website Development with Django[I get paid if you buy it].

First, at the end of bookmark_list.html we could add the same condition check as in search.html in order to avoid displaying 'No bookmarks found' message when searching for an empty string:

...
{% else %}
{% if show_results %}

No bookmarks found.


{% endif %}
{% endif %}


Second, as from Django 1.0 the HttpRequest.is_ajax() function is available . It returns True if the request was made via an XMLHttpRequest, by checking the HTTP_X_REQUESTED_WITH header for the string 'XMLHttpRequest'.

We can use it in our example to avoid the not so beautiful 'ajax' varaible hard-coding:

In search.js instead of:

...
$("#search-results").load("/search/?ajax&query=" + encodeURIComponent(query));
...


I am writing:

...
$("#search-results").load("/search/?query=" + encodeURIComponent(query));
...


And in views.py instead of:

def def search_page(request):
...
if request.GET.has_key('ajax'):
return render_to_response('bookmark_list.html', variables)
else:
return render_to_response('search.html', variables)
...


I write:

def def search_page(request):
...
if request.is_ajax():
return render_to_response('bookmark_list.html', variables)
else:
return render_to_response('search.html', variables)
...


Now it looks cleaner to me :-)

Wednesday, February 25, 2009

Learning Website Development with Django errata

The book Learning Website Development with Django[I get paid if you buy it] has been written for Django 0.96. In my spare time I am following its code while using Django 1.0 and making corrections where(hopefully) it seems appropriate.

On page 104 instead of

...
if request.GET.has_key('query'):
show_results = True
query = request.GET['query'].strip()
if query:
form = SearchForm({'query' : query})
bookmarks = Bookmark.objects.filter (title__icontains=query)[:10]
...


you might want to write:

...
if request.GET.has_key('query'):
if request.GET['query'].strip() != '':
show_results = True
query = request.GET['query'].strip()
if query:
form = SearchForm({'query': query})
bookmarks = Bookmark.objects.filter(title__icontains=query)[:10]
...

Wednesday, February 4, 2009

о книге Learning Website Development with Django

Книга неплохая но есть и некоторые нестыковки. Необычно выглядит использование __str__ в моделях вместо настоятельно рекомендуемого __unicode__.(см. Choosing between __str__() and __unicode__()) Книга показалась интересной поэтому продолжил чтение сверяя код из книги с документацией. Вскоре наткнулся на следущую незавершенность.

Вот модель которую предлагает автор(после замены __str__ на __unicode__):


class Link(models.Model):
url = models.URLField(unique=True)
def __unicode__(self):
return self.url

class Bookmark(models.Model):
title = models.CharField(max_length=200)
user = models.ForeignKey(User)
link = models.ForeignKey(Link)
def __unicode__(self):
return '%s, %s' % (self.user.username, self.link.url)

class Tag(models.Model):
name = models.CharField(max_length=64, unique=True)
bookmarks = models.ManyToManyField(Bookmark)
def __unicode__(self):
return self.name


Неопытный читатель вроде меня ничего бы не заметил если бы не одна особенность Джанго которая показалась не совсем удобной и из-за которой захотелось копнуть глубже. Вот она:


>>> dir(Bookmark)
['DoesNotExist', 'MultipleObjectsReturned', '__class__', '__delattr__', '__dict_
_', '__doc__', '__eq__', '__format__', '__getattribute__', '__hash__', '__init__
', '__metaclass__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_e
x__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_
_unicode__', '__weakref__', '_collect_sub_objects', '_default_manager', '_get_FI
ELD_display', '_get_next_or_previous_by_FIELD', '_get_next_or_previous_in_order'
, '_get_pk_val', '_meta', '_set_pk_val', 'delete', 'link', 'objects', 'pk', 'sav
e', 'save_base', 'tag_set', 'user']
>>> dir(Tag)
['DoesNotExist', 'MultipleObjectsReturned', '__class__', '__delattr__', '__dict_
_', '__doc__', '__eq__', '__format__', '__getattribute__', '__hash__', '__init__
', '__metaclass__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_e
x__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_
_unicode__', '__weakref__', '_collect_sub_objects', '_default_manager', '_get_FI
ELD_display', '_get_next_or_previous_by_FIELD', '_get_next_or_previous_in_order'
, '_get_pk_val', '_meta', '_set_pk_val', 'bookmarks', 'delete', 'objects', 'pk',
'save', 'save_base']
>>>

Есть что-то нелогичное в разнице между Tag.bookmarks и Bookmark.tag_set. Почему бы не реализовать повсюду одинаково - Tag.bookmark_set ? (Смутно припоминаю что в RoR тоже не очень приятная история со множественным числoм существительных. )

У нас есть Bookmark и есть Tag. Согласно докам : "It doesn't matter which model gets the ManyToManyField, but you only need it in one of the models -- not in both."

Однако затем читаем:
"Generally, ManyToManyField instances should go in the object that's going to be edited in the admin interface, if you're using Django's admin. In the above example, toppings is in Pizza (rather than Topping having a pizzas ManyToManyField ) because it's more natural to think about a pizza having toppings than a topping being on multiple pizzas."

У нас хоть и ManyToMany, но таки натуральней думать что Букмарк имеет Тэги а не наоборот.

Wednesday, January 28, 2009

Зачистка

До выхода NetBeans 7.0 Milestone2 с поддержкой Django и чисткой проекта осталось больше двух недель. Несмотря на то что чистить Питон проект особой нужды нет, привычка, похоже, действительно вторая натура. Поэтому :



#!/usr/bin/env python

#----------------------------------------------------
#use ';' to separate the extentions if more than one,
#for example: pattern = "*.pyc;*.doc;*.txt"
#all of the files with that extention will be deleted.
#----------------------------------------------------

import os
path = "."
pattern = "*.pyc"

#print files that match to file extention:
def printFiles(dirList, spaceCount, typeList):
for file in dirList:
for ext in typeList:
if file.endswith(ext):
print "/".rjust(spaceCount+1) + file
break

#print each sub-directory:
def printDirectory(dirEntry, typeList):
print dirEntry[0] + os.sep
printFiles(dirEntry[2], len(dirEntry[0]), typeList)

def deleteFiles(dirList, typeList):
for file in dirList[2]:
for ext in typeList:
if file.endswith(ext):
print 'deleting ' + os.path.join(dirList[0], file)
os.remove(os.path.join(dirList[0], file))
break

extList = []
for ext in pattern.split(";"):
extList.append(ext.lstrip("*"))
for directory in os.walk(path):
printDirectory(directory, extList)
s = raw_input("This is your last chance, the above files will be deleted, press any key to continue, CTRL+C otherwise")
for directory in os.walk(path):
deleteFiles(directory, extList)

Friday, December 26, 2008

List environment variables from Python

To print the list of environment variables use the following code:


import os

for param in os.environ.keys():
print "%20s %s" % (param,os.environ[param])

Thursday, November 27, 2008

Cross-page posts and OnClientClick

The Button.OnClientClick property is a convenient way of executing additional client side script when the Click event is raised.

For example, after clicking the following button :

<asp:Button ID="Button1" runat="server"
OnClientClick="return confirm('Are You Sure?');"
Text="Button" Width="125px" />

a confirmation dialog will pop up:

If the confirmation box returns false, the button click is canceled.

Problem:
if you try to post the form of the current page to another page by using the PostBackUrl Property and still want to use the OnClientClick property, care should be taken when writing your JavaScript code. If you write your button in a way similar to this:

<asp:Button ID="Button1" runat="server"
OnClientClick="return confirm('Are You Sure?');"
Text="Button" Width="125px"
PostBackUrl="~/PageToPostbackTo.aspx" />

the cross-page post will fail.

The problem here is this line of code:

OnClientClick="return confirm('Are You Sure?');"

Let's have a look at what has been generated by our button code:


<input type="submit" name="Button1" value="Button"
onclick="return confirm('Are You Sure?');
WebForm_DoPostBackWithOptions(new
WebForm_PostBackOptions("Button1", "",
false, "", "PageToPostbackTo.aspx", false,
false))" id="Button1" />

The return statement cuts off the DoPostBackWithOptions function, it never gets called.

For comparison's sake, have a look at our first button generated code:

<input type="submit" name="Button1" value="Button" onclick="return confirm('Are You Sure?');" id="Button1" />

you see, there was no problem at all with the initial JavaScript code.


Solution:
If you want to use both OnClientClick and PostBackUrl in the same button, instead of

onclick="return confirm('Are You Sure?');"

use:

onclick="if(!confirm('Are You Sure?'))return false;"

Wednesday, November 12, 2008

Custom Templates for Dynamic Data Web Application

While following the MSDN documentation on DynamicData found myself stuck on How to: Customize the Layout of an Individual Table By Using a Custom Page Template.
After copying List.aspx to the CustomPages folder the project just would not compile:

The naming collision is obvious and I couldn't believe my eyes - the MSDN article seemed to be incorrect.

Solution: the MSDN article is written for a Dynamic Data Web Site, while I was workind with a Dynamic Data Web Application. The Web Application is compiled in one DLL, while the Web Site is using folder names to generate namespaces at runtime.

Now, when it was clear were the name collision came from, renamed the namespace in the List.aspx.cs file, modified the 'Inherits' attribute of the @Page directive for List.aspx and it worked like a charm.


A thing to note here is that there are two web.config files on the picture above, one in the root directory and the other in the DynamicData folder. If you look at the content of the second web.config file, its purpose becomes clear:


<?xml version="1.0"?>
<!--
The purpose of this file is to block access to the template files, that are not meant
to be directly requested.
-->
<configuration>
<system.web>
<httpHandlers>
<add path="*.aspx" verb="*" type="System.Web.HttpNotFoundHandler" validate="true"/>
</httpHandlers>
</system.web>
</configuration>


Should you try to access directly your List.aspx file you will get a Not Found error.

Friday, November 7, 2008

NVI pattern (again)

There was an example of the Non Virtual Interface pattern in a previous post . Time has come to show its use in the FCL. Technically speaking, the Collection<T> class is not a demonstration of using of the NVI per se, but still an incentive to apply the pattern in your own code.

After deriving from System.Collections.ObjectModel.Collection<T> you have exactly the same functionality as in a List<T>. Now, however, you can override its InsertItem(it is called Insert in List<T>), SetItem(Add in List<T>), RemoveItem (Remove in List<T>) or ClearItems(Clear in List<T>) and plug-in any additional functionality you might need.

I don't write any example code, since it has exactly the same logic as in my previous post: client code will call the "List<T> version" of the function, i.e. Remove instead of RemoveItem and so on.

Note that the old, non-generic version of Collection<T> is CollectionBase.

Monday, November 3, 2008

ANSI C and C# bit-fields comparison

We can achieve storage space saving in ANSI C by one of the following means:

1. define a set of bit-field masks:

#define MONDAY 01
#define TUESDAY 02
#define WEDNESDAY 04


2. declare an enum with bit-fields:

enum { MONDAY = 01, TUESDAY = 02, WEDNESDAY = 03};

/*turn on Monday and Wednesday:*/
days |= MONDAY | WEDNESDAY;

/*turn off Monday and Wednesday:*/
days &= ~(MONDAY | WEDNESDAY);

/*is true if Monday and Wednesday are off:*/
if((days & (MONDAY | WEDNESDAY)) == 0)
....


3. Access the fields within the word directly rather than by bitwise logical operations(the number following the colon represents the field width in bits):

struct {
unsigned int is_Monday : 1;
unsigned int is_Tuesday : 1;
unsigned int is_Wednesday : 1;
} days;

/*turn on Monday and Wednesday:*/
days.is_Monday = days.is_Wednesday = 1;

/*turn off Monday and Wednesday:*/
days.is_Monday = days.is_Wednesday = 0;


/*is true if Monday and Wednesday are off:*/
if(days.is_Monday == 0 && days.is_Wednesday ==0)
....



In C# we can apply the [Flags] attribute to an enum. To avoid overlapping, the same rule of defining the enumeration constants in power of two is respected here:

[Flags]
public enum Days {
Monday = 0x01,
Tuesday = 0x02,
Wednesday = 0x04,
}

sealed class FlagTest {

static void Main(string[] args) {
/*turn on Monday and Wednesday:*/
Days days = Days.Monday | Days.Wednesday;
Console.WriteLine(days);

/*turn off Monday and Wednesday:*/
days &= ~(Days.Monday | Days.Wednesday);
Console.WriteLine(days);
}
}


(post inspired by K&R 2nd, MSDN)

Wednesday, October 29, 2008

Restore a SQL Server 2005 Express database from a *.bak file

How to restore a SQL Express 2005 database from an existing *.bak to an *.mdf file:

1. download and install SQL Server Management Studio from the official site or use the direct link

2. right click on 'Databases' folder in the Object Explorer, choose restore database.

3. under 'Specify the source and location of backup sets to restore' choose 'From device',
click on browse button, add your bak file.

4. select the backup set to restore

5. Under 'Destination for restore' write the name for your database in the 'To database' dropdown or
choose it from the existing list.

6. On the right upper side select 'Options' page

7. Under 'Restore the database files as' write the path to the *.mdf and *.ldf files respectively

8. click on OK


I've spent quite a while trying to figure out how to do this, the search on both google and msdn did not help. The problem was I didn't realize that after having a full install of Visual Studio 2008 I still could install and use another tool - the SQL Server Management Studio. Hope this post will be a time saver to someone else or even myself after a period of time.

Monday, October 27, 2008

Wait and Pulse fun

If you want two threads to increment a variable in an alternating manner, a nice way of doing it could be the following:


class EntryPoint {
static private int counter = 0;
static private object theLock = new Object();

static private void ThreadFunc1() {
lock (theLock) {
for (int i = 0; i < 50; ++i) {
Monitor.Wait(theLock, Timeout.Infinite);
Console.WriteLine("{0} from Thread {1}", ++counter, Thread.CurrentThread.GetHashCode());
Monitor.Pulse(theLock);
}
}
}

static private void ThreadFunc2() {
lock (theLock) {
for (int i = 0; i < 50; ++i) {
Monitor.Pulse(theLock);
Monitor.Wait(theLock, Timeout.Infinite);
Console.WriteLine("{0} from Thread {1}", ++counter, Thread.CurrentThread.GetHashCode());
}
}
}

static void Main(string[] args) {
Thread thread1 = new Thread(new ThreadStart(EntryPoint.ThreadFunc1));
Thread thread2 = new Thread(new ThreadStart(EntryPoint.ThreadFunc2));
thread1.Start();
thread2.Start();
Console.ReadLine();
}
}



The output is just as beautiful as the code is:

(post inspired by 'Accelerated C#2008', Trey Nash)

Tuesday, October 21, 2008

MVC's UpdateModel function and the AcceptVerbs attribute(unrelated)

After you create your new model object within the controller action, you want to populate its properties with the corresponding values from the FormCollection, right?

If for example you have a model Message class:


public class Message {

public Message() { }

public Message(int id, string author, string subject, string body) {
this.Id = id;
this.Author = author;
this.Subject = subject;
this.Body = body;
}

public int Id { get; set; }
public string Author { get; set; }
public string Subject { get; set; }
public string Body { get; set; }
}


Then your controller code might look like this:

public class MyController : Controller {

//repository pattern stuff here
...

public ActionResult Create(FormCollection form) {
// Create new message
var messageToCreate = new Message();
messageToCreate.Author = form["author"];
messageToCreate.Subject = form["subject"];
messageToCreate.Body = form["body"];

// Add to database, show the view and return
...
}
}



Instead, use Controller.UpdateModel function to type less lines of code:

public class MyController : Controller {

//repository pattern stuff here
...

public ActionResult Create(FormCollection form) {
// Create new message
var messageToCreate = new Message();
this.UpdateModel(messageToCreate, new[] {"author", "subject", "body"});

// Add to database, show the view and return
...
}
}


Also we could have two versions of Create() action - one for GET and the other for POST:

public class MyController : Controller {

//repository pattern stuff here
...

[AcceptVerbs("GET")]
public ActionResult Create() {
return View();
}

[AcceptVerbs("POST")]
public ActionResult Create(FormCollection form) {
// Create new message
var messageToCreate = new Message();
this.UpdateModel(messageToCreate, new[] {"author", "subject", "body"});

// Add to database, show the view and return
...
}
}


Now it looks better :-)

(inspired by these two amazing tutorials: http://www.asp.net/learn/mvc-videos/video-422.aspx and http://weblogs.asp.net/stephenwalther/archive/2008/09/05/asp-net-mvc-application-building-forums-3-post-messages.aspx)

Saturday, October 18, 2008

Upgrading from MVC preview 5 to MVC Beta

Here is what I did to my toy project to make it work under MVC Beta:

1. Removed reference to Microsoft.Web.Mvc.dll.

2. Set 'Copy Local' option to true for the System.Web.Mvc.dll.

3. Added

<add namespace="System.Web.Mvc.Html"/>

to the namespaces section of Web.config.

Wednesday, October 15, 2008

Non-Virtual Interface Pattern

An interesting design pattern found in chapter 13 of "Accelerated C# 2008" by Trey Nash.

Suppose after writing and delivering your base class to thousands of users you want some pre and/or post work done.

Instead of introducing two more methods, PreDoWork() and PostDoWork() and asking your users to reimplement their overrides to call these new methods on the correct time, use the Non-Virtual Interface Pattern:



public class Base {

public void DoWork() {
//Console.WriteLine("some additional stuff added long after you delivered your library");
this.CoreDoWork();
}

protected virtual void CoreDoWork() {
Console.WriteLine("Base.DoWork()");
}
}

//happy users of your library don't have to change their code:
public class Derived : Base {
protected override void CoreDoWork() {
Console.WriteLine("Derived.DoWork()");
}
}

sealed class EntryPoint {
static void Main(string[] args) {
Base b = new Derived();
b.DoWork();
}
}



A detail worth mentioning is the protected modifier in the following code:

public class Derived : Base {
protected override void CoreDoWork() {
Console.WriteLine("Derived.DoWork()");
}
}

In .NET 1.0 you could use the private modifier here. As from .NET 1.1 you cannot override private virtual methods.