Saturday, June 28, 2014

So Long, and Thanks For All the Fish

Substitute your favorite parting phrase for the title, but it all comes down to the same thing. Our class has ended and the project will no longer be receiving updates.

Feel free to leave a comment on this post if you have questions about anything that we accomplished, and we'll get in contact with you and can hopefully help out.

Thursday, May 15, 2014

Javascript - the power of ajax

So, one issue we ran into was the fact that changes to the lights had to be submitted with a web form. The action of the form submitted the light values to another view which would handle the input and then redirect us back to the house list page. It worked great for demonstration purposes but then we started noticing (as we got a long list of lights that we had to scroll through) that, after the redirect, you are put back at the top of the page. So, if you've got a few lights at the bottom that you need to modify, you click on a light and are put at the top of the page and you have to scroll down to find your light again. This was also just a bunch of un-necessary page reloading. In the end, we decided to use javascript's ajax to submit the form without going through all this redirection.

The issue to attack was the fact that it doesn't matter what fancy javascript we put in place because once we hit submit, the form's default code will kick in and it will try to redirect us. so first, we have to suppress the default action of the form. I did that with the following javascript. (all this code runs when the document is ready.)

$("form").on("submit", function (e) {
     e.preventDefault();
}

This was okay because we only have one form on this page. I could have also changed "form" to be the exact id or class of my house list form but I figured it was un-necessary.
Now that this is done and the form will now lie here inactive, we need to send the input to the view ourselves but we also want to do this sort-of in the background. We don't really need feedback from this action as all feedback is already handled. To do this, I used ajax.

So, in order to set up this ajax call, we need to collect the information that would have been sent as the form was submitted. It also needs to be in the same format. I searched for a way to do this and quickly found jquery's "serialize" function. It gets all that data and prepares it to be sent. The only other thing I need is the url to send the data to which we have from the action of the original form.

The code looked like this:

$.ajax({
     type: "POST",
     url: "{% url 'management:submitChange' %}",
     data: $("#houseForm").serialize(),
})


And finally, we need to put both of these code sections together so they run immediately when the page loads. Then the ajax call needs to run on the form's attempt to submit. The finished code looked like this:

$(document).ready(function() { $("form").on("submit", function (e) {
   e.preventDefault();
   if (true){
      console.log($("#houseForm").serialize())
      $.ajax({
         type: "POST",
         url: "{% url 'management:submitChange' %}",
         data: $("#houseForm").serialize()
   })
}})})

I threw in that console.log() for debugging purposes and it is not necessary.
And with that, you have a form that does not refresh the page every time you change a light!
Ahh, the power of Ajax!

Tuesday, May 13, 2014

Schemamigration

As progress is made through any project, there comes a time when the creators realize that the models that they had in mind for the final product aren't sufficient to complete the task. At this point, the models must be revised in order to accomplish the goals of the project.

Unfortunately, if the project that is being built involves a database, this adapting of the model can be a difficult process. In our case, we decided to add in a schedule to every light, room, and house. The Django framework is under strict instructions to create tables, but not to update them. Then, when you choose to add something, the Django website will throw an error because it doesn't understand why there is an extra thing added into its design. If the story ends there, that means that every time we adapt our model we will have to re-create all of the test data that we have generated, adding in the schedule information as we build it new.

Fortunately, the story doesn't end there. The good folks at Aeracode have developed South, a data migration tool for Django projects. South takes care of the difficult task of adapting the database for you. All that one needs to do is set up an initial state of the database with the South tool and then when a change has been made, create and apply a data migration. For our purposes, it worked very smoothly and the tutorial was easy to follow. 

After installing South, there were just four simple commands to run:
./manage.py syncdb
./manage.py convert_to_south myapp
./manage.py schemamigration myapp --auto
./manage.py migrate myapp
The only minor hiccup in the migration was that the database did not know what value to fill in for the schedule for each of the lights. Since the lights are allowed to not be on a schedule, a quick null=true fixed this problem and our app was fully functional again.