Django & Python Adventure Part 6

Today I am going to focus on incorporating JQuery into Django. If you’re following along this is material covered in chapter 6 of Ayman Hourieh’s “Django 1.0 Web Site Development”. The book was published in March 2009, so this will be an interesting test of what’s changed in JQuery in 21 months. It was common practice back then to download a copy of JQuery, but, today I believe utilizing CDNs (Content Delivery Network) is the preferred method.

The big players run these CDNs:
• Microsoft: http://www.asp.net/ajaxlibrary/cdn.ashx
• Google: http://code.google.com/apis/libraries/
• JQuery: http://code.jquery.com/

As an interesting aside, some developers worry about their applications being unable to connect to the CDN 100% of the time. If you want to read more on this, read this blog about getting around it:

http://code-inside.de/blog-in/2011/02/06/howto-jquery-hosted-cdn-version-local-fallback/

One final note, it’s best to use the .min version of whatever JQuery as it has been “minified” to work faster for you application.

We only want to reference this once, so we’ll drop it in the Master Page base.html:

The first thing I want to implement is AJAX-enabled search functionality on the bookmarks. The book suggests the best practice of writing the search form without AJAX (so it should work if the AJAX fails) and then add on the AJAX functionality. This is called “Progressive Enhancement” and it simply means we try not to leave anyone out of the fun.

First: bookmarks/forms.py:

Second: bookmarks/views.py
Notice the search is already implemented in Django. We’re calling it with Bookmark.objects.filter(). When we passit arguments, they must be in the format: field__operator. For a .Net programmer I still find the double underscore a little odd, but, whatever. There are other operators we could use aside from “icontains”. “contains”, “startswith”, and “exact” are some others. You can see this gives you similar power to a SQL SELECT blah FROM blah WHERE… Again, Django is handling the ORM code for us so this is what we’ll use to query the Model.

Third: implement templates/search.html

Fourth: update urls.py
(r’^search/$’, search_page),

Now test it out:

Very cool. We’ve now created our base search functionality with a few lines of code. Now we can add in the AJAX for browsers that can handle it (have JavaScript enabled).

First: update base.html to have a link to the search page:

Second: update the views.py

Third: update the search.html

Fourth: create the search.js file. This…

Again, we can test it. Notice this time the page does not reload. That is the JQuery AJAX call handling the manipulation of the innerHTML of the page for you:

AJAX accomplished! It’s a brand new day. Next time I’ll be doing something a little more advanced, but this was a good start.

Thanks,
Mike

jQuery to Web Service AJAX

jQuery to Web Service AJAX

This is a bit wacky, but in the end it all makes perfect sense.

jQuery has two functions you could use: get and put, but the function you’ll end up using is.ajax.

Example:

Let’s say I want to use JQuery to fill a Drop Down list on my ASP.Net page.

Here’s the basics of how that flows:

On whatever event (in this example it is a button click) you will wire up a JQuery function to fire off an AJAX call.

On the web, most examples call a PHP page, and that’s not what we want to do.

HTML:

<body>
    <form id="form1" runat="server">
    <div>
        <asp:DropDownList ID="MyDropDownList" runat="server">
        </asp:DropDownList>
        <asp:Button ID="FillDropDownListButton" runat="server" Text="Fill DropDownList" />
    </div>
    </form>
</body>

 

JQuery function to tap into the click event for the button:

    <script type="text/javascript">
        $(function () {

            $('#<%= FillDropDownListButton.ClientID %>').click(function () {
                doAjaxCall('/Test.asmx/FillDropDownList');
                return false;
            });

 

JQuery function to do the AJAX call:

            function doAjaxCall(url, data) {
                $.ajax({
                    type: 'POST',
                    url: 'Test.asmx/FillDropDownList',
                    data: "{}",
                    contentType: 'application/json; charset=utf-8',
                    dataType: 'json',
                    success: successHandler,
                    error: ajaxFailed
                });
            }
 

You can see that this is using the HTTP POST protocol, and thus, the function being called must either be an actual web page .aspx or a user control .asmx/.svc or it could be the rarely seen .ashx (not covered here).  It cannot be a library .cs because that doesn’t communicate via HTTP protocol.

Also note the data object being passed is an undefined empty object. 

The url has the page/function.  That function must be a web method.
 

The success function:

            function successHandler(response) {
                var myDropDownList = $('#<%= MyDropDownList.ClientID %>');
                myDropDownList.find('options').remove();
                var data = response.d;
                var doc = $('<div></div>');
                for (var i = 0; i < data.length; i++) {
                    doc.append($('<option></option>').
                            attr('value', data[i].CountryID).text(data[i].CountryName)
                            );
                }
                myDropDownList.append(doc.html());
                doc.remove();
            }

 The failure function:

            function ajaxFailed(xmlRequest) { alert(xmlRequest.status + ' nr ' + xmlRequest.statusText + 'nr' + xmlRequest.responseText); }

        }); 
    </script>

 

Now, as for the Test.asmx:

    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    [ScriptService]
    public class Test:System.Web.Services.WebService
    {
        [WebMethod]
        public Collection<Location> FillDropDownList()
        {
            var locations = new Collection<Location> 
                { 
                    new Location {CountryID = 0, CountryName = "Please Select"}, 
                    new Location {CountryID = 1, CountryName = "Country1"}, 
                    new Location {CountryID = 2, CountryName = "Country2"}, 
                    new Location {CountryID = 3, CountryName = "Country3"}, 
                    new Location {CountryID = 4, CountryName = "Country4"}, 
                    new Location {CountryID = 5, CountryName = "Country5"} 
                };
            return locations;
        }
        public class Location
        {
            public int CountryID { get; set; }
            public string CountryName { get; set; }
        }
    }
}

 

So, while I’m returning a collection from the code, it could also make a call to SQL or the WebCache, etc.

© Copyright Duke Hall - Designed by Pexeto