Oct 29 2008

Webfaction Limited Review

Tag: YadaDustin @ 5:48 am

I’ve seen a lot of recommendations for Webfaction for new Django developers who want an easy to use hosting solution. As you can see from previous posts that I have a VPS that I’ve set up Django on. I was having problems getting one of my applications to work, and I wondered if it was because of my setup. So I decided to try out Webfaction. After all, they offered a 60 day money back guarantee. So I signed up and set up my account. I must admit it was much easier to set up than my VPS, plus I could choose to use Python 2.5 (which was never really able to get working on my server setup) and you can use mod_python or WSGI. I was quite impressed with their setup options and the ease of setup. It turns out there there was a problem in my code because I ended up getting the same error on their servers as I did mine. I was just confused because it was working on my windows develpement machine, by not my linux servers. 

So having lost the need for Webfaction, I decided to exercise their money back guarantee. I think this was the best part of the process. I sent them an email. The responded quickly telling me how to cancle the account from the control panel. I think within a half hour I had the money back in my PayPal account and an email confirmation letting me know and saying thanks for trying their service.

Surely, If I ever need another Django host or if it comes to the point where I need to use the latest version of Python, I will look to Webfaction. If I have a client looking for hosting, I will recommend Webfaction.


Oct 03 2008

Django Tip: get_FIELD_display()

Tag: YadaDustin @ 3:45 pm

I’m posting this because it seems rather simple, but it took me a while to find - even with some tips from some helpful people in the #django IRC channel.

Let’s say you have a ChoiceField set up like the documents describe:

 

class Foo(models.Model):
    GENDER_CHOICES = (
        ('M', 'Male'),
        ('F', 'Female'),
    )
    gender = models.CharField(max_length=1, choices=GENDER_CHOICES)

Now, you want to display the gender field in a template. If you use the {{ person.gender }} variable, you would get “M” or “F” to display on your page. But what if you want “Male” or “Female”? Then you would use {{ person.get_gender_display }}.

Nifty.


Oct 03 2008

Dynamic Filtered Drop-Down Choice Fields With Django

Tag: YadaDustin @ 10:05 am

I’m enjoying the Django framework. Sometimes, what was seems rather easy (relatively speaking) gets sort of complicated when working within the boundaries of a framework. Such was the case with my latest endeavor to filter on drop-down based on the selection of another drop-down.

Here is the situation: I have a database with car makes and models. When a user selects a make, I want to update the models drop-down with only the models associated with that make. Sounds pretty common, right? The database has a lot of entries, so I don’t want to do it with pure javascript because that could make for big script, and maybe I don’t want to give away all my data so easily so some hacker can just parse a simple javascript file to get all the make/model data out of my database (not that I care, but some people might). Therefore I want to use Ajax to populate the data.

First, the proof of concept. I created this simple html file to test how it might work:

 

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd”>
<html>
    <head>
        <meta http-equiv=”Content-type” content=”text/html; charset=utf-8″ />
        <title>Update Drop-Down Without Refresh</title>
        <script type=”text/javascript” charset=”utf-8″>
            function FilterModels() {
                var makeslist = document.getElementById(’makes’);
                var modelslist = document.getElementById(’models’);
                var make_id = makeslist.options[makeslist.selectedIndex].value;
                var modelstxt = new Array();
                modelstxt[1] = “1\tEscort\n2\tTaurus”;
                modelstxt[2] = “1\tAltima\n2\tMaxima”;
                var models = modelstxt[make_id].split(”\n”);
                for (var count = modelslist.options.length-1; count >-1; count–){
                    modelslist.options[count] = null;
                }
                for (i=0; i<models.length; i++){
                    var modelvals = models[i].split(”\t”);
                    var option = new Option(modelvals[1], modelvals[2], false, false);
                    modelslist.options[modelslist.length] = option;
                }
            }
        </script>
    </head>
    <body>
        <p>This is a proof of concept to update a select (drop-down) list of values, based on the selection of another select (drop-down) element using ajax.</p>
        <form action=”" method=”get” accept-charset=”utf-8″>
            <select name=”makes” onchange=”FilterModels()” id=”makes”>
                <option>–</option>
                <option value=”1″>Ford</option>
                <option value=”2″>Nissan</option>
            </select>
            <select name=”models” id=”models”>
                <option>Choose Make</option>
            </select>
        </form>
    </body>
</html>

 

 

That basically helped me organize the code I needed to change the drop-down, now I just need to plug in the Ajax and server side code to make it happen.

Notice, in the proof of concept, I used a tab delimited format for my models. I really didn’t want to mess with parsing xml or json or whatever. So I wrote a model feed based on my automobile make id.

URL:

(r'^feeds/models-by-make-id/(\d+)/$', 'autos.views.feed_models'),

View:

def feed_models(request, make_id):
    make = AutoMake.objects.get(pk=make_id)
    models = AutoModel.objects.filter(make=make)
    return render_to_response('feeds/models.txt', {'models':models}, mimetype="text/plain")

Template:

{% for model in models %}{{ model.id }}    {{ model.model }}
{% endfor %}

That gave me the data feed that I needed to request via Ajax. Now for my form. Because the model field loads dynamically, I had to override the clean function in the ChoiceField class and use it instead so I didn’t get invalid choice errors:

 

class DynamicChoiceField(forms.ChoiceField): 
    def clean(self, value): 
        return value

 

 

class MyForm(forms.Form): 
    make = ModelChoiceField(AutoMake.objects, widget=forms.Select(attrs={'onchange':'FilterModels();'})) 
    model = DynamicChoiceField(widget=forms.Select(attrs={'disabled':'true'}), choices=(('-1','Select Make'),))

Notice that I am making a call to FilterModels() on my ModelChoiceField’s onchange event. So, here is that code as well:

function FilterModels(sel_val) {
	var modelList = $('id_model');
	for (var count = modelList.options.length-1; count >-1; count--){
		modelList.options[count] = null;
	}
	modelList.options[0] = new Option('Loading...', '-1', false, false);
	modelList.disabled = true;

	var makeList = $('id_make');
	var make_id = makeList.options[makeList.selectedIndex].value;
	if (make_id > 0) {
		new Ajax.Request('/feeds/models-by-make-id/' + make_id + '/', {
			method: 'get',
			onSuccess: function(transport){
				var response = transport.responseText || 'no response text';
				var kvpairs = response.split("\n");
				for (i=0; i<kvpairs.length - 1; i++) {
					m = kvpairs[i].split("\t");
					var option = new Option(m[1], m[0], false, false);
					modelList.options[i] = option;
				}
				modelList.disabled = false;
				if (sel_val > 0) {
					modelList.value = sel_val;
				}
			},
			onFailure: function(){
				alert('An error occured trying to filter the model list.');
				modelList.options[0] = new Option('Other', '0', false, false);
				modelList.disabled = false;
			}
		});
	}
	else {
		modelList.options[0] = new Option('Select Make', '-1', false, false);
		modelList.disabled = true;
	}
}

I also make a call to this function in my template after the form loads. This is incase the form is refreshed, or it fails validation and a make is still selected. It will populate the model list and select the value that was selected previously:

<script type="text/javascript" charset="utf-8">
	FilterModels({{ model_id }});
</script>

Note that in order to get the model_id, I had to set it in my view:

def add_classified(request):
	if request.method == 'POST':
		form = AdForm(request.POST)
	if request.POST.has_key('model'):
		model_id = request.POST['model']
	else:
		model_id = 0
	return render_to_response('add_classified.html', {'form':form,'model_id':model_id}, context_instance=RequestContext(request))

I think that’s about it… Did I miss anything?




ss_blog_claim=4973c51f5e7bec57951f995fed1b85f3 ss_blog_claim=4973c51f5e7bec57951f995fed1b85f3