Django Image Field Overwrite with ImageKit

I’m using django-imagekit on a new site. I was having a problem that when a user uploaded a new image for the object, the system would not overwrite the existing image file, but instead would create a new file with a sequence number on the end. This was not the behavior I was looking for. Lockjaw’s answer on StackExchange handled the not-overwriting the existing file problem. ImageKit was still caching the previous image for any specfields. The solution is to call ‘.clear()’ after saving the new image to purge the ImageKit cache for that specfield/image.

So, the total solution is:


#Lockjaw's code on StackExchange
class OverwriteStorage(FileSystemStorage):   
    def get_available_name(self, name):
        if self.exists(name):
            os.remove(os.path.join(settings.MEDIA_ROOT, name))
        return name

def issue_plane_image_path(plane, filename):
    "return the canonical file name for an image on this plane instance"
    extension = os.path.splitext(filename)[1]
    return os.path.join('photos/planes', plane.slug+extension) 

class Plane(models.Model):
    image = models.ImageField(upload_to=issue_plane_image_path, storage=OverwriteFileStorage(), null=True, blank=True)
    gallery = ImageSpecField(...)
    thumbnail = ImageSpecField(...) 

    def clearImageCache(self):
       "invalidate all ImageKit spec caches"
       self.gallery.clear()
       self.thumbnail.clear()

and in the edit view:


.
.
if form.is_valid():
   form.save()
   plane.clearImageCache()

And now each instance has very few images (usually only one, but if a person uploads different filetypes such as a PNG then a JPG, they will both exist. I am OK with that.)

Posted in Django, Python | Leave a comment

TiddlyWiki with Firefox 15

TiddlyWiki saves (and exports) stopped working with the Firefox upgrade to 15. After trying a few changes to prefs.js, I found the post Will Firefox 16 support TiddlyWiki on the Mozilla site. It had a link to a Firefox extension called Tiddly Wiki 5, which fixed the problems I had with saving and the export plugin.

https://github.com/Jermolene/TiddlyWiki5

Posted in Uncategorized | Tagged , | Leave a comment

Custom Sort in Google Apps Spreadsheet

I use a Google Docs spreadsheet to track my personal projects. Only, I’m not aware of a way to save sort options in a Google Docs spreadsheet. The solution is to create a script. The following script will add a menu option that remembers sort parameters and makes use of a header row on the data. Detailed instructions on adding the script are here: http://productforums.google.com/forum/#!topic/docs/Kl9WEj6Kha0 and I just added skipping of the header row.

/**
* sort spreadsheet assuming first row is a header row
*/
function customSort() {
var sheet = SpreadsheetApp.getActiveSheet();
var allData = sheet.getDataRange();
var range = sheet.getRange(2,1, allData.getNumRows()-1, allData.getNumColumns());
range.sort( [1,2,4]); // see https://developers.google.com/apps-script/class_range#sort
};

/**
* Adds a custom menu to the active spreadsheet, containing a single menu item
* for invoking the readRows() function specified above.
* The onOpen() function, when defined, is automatically invoked whenever the
* spreadsheet is opened.
* For more information on using the Spreadsheet API, see
* https://developers.google.com/apps-script/service_spreadsheet
*/
function onOpen() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var entries = [{
name : "Custom Sort",
functionName : "customSort"
}];
sheet.addMenu(“Custom Scripts”, entries);
};

Posted in Uncategorized | Leave a comment

SimpleJson Error with django under google app engine

Since moving over to 64 bit windows 7, I’ve had this error when starting up:

"... py_zipimport.py:108] zipimporter('C:\\python25\\lib\\site-
packages\\simplejson-2.0.9-py2.5-win.egg', 'simplejson\\') ...
dev_appserver_main.py ... SetGlobals() ...
...
File "C:\Program 
Files\Google\google_appengine\google\appengine\dist\py_zipimport.py", line 
268, in _getitem__
info = _zipfile_cache[self._archive].getinfo(filename)
File "C:\Python25\lib\zipfile.py", line 462, in getinfo
return self.NameToInfo[name]
KeyError: 'simplejson\\_speedups.pyd'

The solution is from peplafi on the google app engine defect list:

It looks that it gives the error when you have installed simplejson in your python
dist and dev_appserver is mixing its own simplejson (which is located in
django\utils) and the python’s sipmlejson. The solution is to go to

The solution is to go to 

"c:\Program Files\Google\google_appengine\google\appengine\ext\key_range\__init__.py" 
, line 26

and change:

   import simplejson

 to:

   from django.utils import simplejson

Posted in Python | Leave a comment

Rynsc on Windows 7 Under Cygwin

I *finally* have rysnc working under Windows 7 without issuing permission-denied messages. Here’s the story:

The goal is to run a bash script that backs up a set of directories to a an external hard-drive. This script will run as me from a bash shell.

The destination hard drive is mounted as E: in this example. The bash script contains a series of rysnc commands similar to:

rsync -rltgovR --delete-after /cygdrive/h/music /cygdrive/e

This will mirror h:\music on E:\h\music with recursion.

The catch was getting permissions correct on the external drive. This took two commands run from a cmd.exe shell (bash shell should work if you escape the parameters correctly, but don’t bother for two commands).

E: is rsync destination for mirrors, ‘Kevin’ is the windows user name the script will be running under.


E:
cd \
takeown /f * /r /d y
icacls * /grant Kevin:(F) /T

This did it for me. Hope this helps.

Some other posts mention adding
none /cygdrive cygdrive binary,posix=0,user,noacl 0 0
to /etc/fstab. I tried this both ways and it did not seem to matter. For now it is commented out.

Posted in programming | Leave a comment

Review of Ergometer Testing for Rowers

This is a review of a new ebook I purchased from Row Perfect called Ergometer Testing for Rowers by Walter Martindale.

The ebook is 10 pages of content plus a font and back sheet.

    Sections:
  1. Introduction
  2. Basic Physiology for Coaches and Athletes
  3. Warming Up
  4. Plan of Attack
  5. Develop a Race Plan
  6. What’s Your Goal
  7. Doing the Test
  8. After the Test
  9. Technique During an Ergometer Test
  10. About the Author
  11. Ergometer Split Chart

Mr. Martindale explains the importance of and reasons for an erg test in the Introduction. The Basic Physiology for Coaches and Athletes section does a nice job of outlining the energy systems in the context of a 2K erg piece. He shines in the Warming Up section by providing the what is probably the best description of what happens when you warm up, and why it is imperative to do so, that I have seen to date. I feel I received my money’s worth for purchase price with this section. The final part of Warming Up outlines a detailed pre-race warm-up plan. The next three sections cover preparing your strategy. They are a bit light. Doing the Test provides coaching on execution of your race plan and practical tips. This contains the most amusing line in the book, regarding people falling to the floor and writhing in pain after a 2K:


    -sure they’re tired and everything hurts, but a lot more people fall of the ergometers than fall out of boats at the end of a really hard 2000m race.

After the Test covers what to do to recover from the piece. Technique During and Ergometer Test talks about people modifying their technique off the water vs. on the water. It also includes a very interesting chart of ergometer test profiles from some univesirty testing in New Zealand. The book then concludes with a short biography of the author and an ergometer split chart. The latter was not as useful, as I prefer the Power Twenty Online Calculator myself(!)

Summary
This is a short ebook that shines in its explanation of the physiological aspects of preparing, rowing, and recovering from a 2K ergometer test. I found it a good value for the £5.00 (~$8.00 USD) price and would recommend it for anyone, regardless of experience, that is serious about their body and performance on the 2K.

Posted in indoor-rowing, rowing | 1 Comment

Sequence from every Nth Item of another Sequence

The phrase ‘every Nth item‘ may be off here, but it is close enough what I want to do (reduce a data set for charting purposes).

# data = sequence of data items
# nth = you want every nth element in the array
[data[index] for index in xrange(0, len(data), nth)]

for example:

data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print [data[index] for index in xrange(0, len(data), 2)]   # [1, 3, 5, 7, 9]
print [data[index] for index in xrange(0, len(data), 3)]   # [1, 4, 7, 10]
print [data[index] for index in xrange(0, len(data), 4)]   # [1, 5, 9]
print [data[index] for index in xrange(0, len(data), 5)]   # [1, 6] 

Posted in programming, Python | 12 Comments

In-Application Customer Feedback

Matt Wilson asked about ‘awesome web-apps to let customers suggest/vote/comment’ on upcoming features.‘ This gave me the idea to post about ErgMate’s in-application feedback mechanism.

In addtion to sending an email to the support mailbox, there are two other ways customers can provide feedback on ErgMate.

The first is through the UserVoice ErgMate Page. UserVoice is a service that allows people to suggest, comment, and vote on features.

The second is through the menu item in the program itself. Selecting ‘Send Feedback’ on the help menu in ErgMate will bring up dialog box:

The Ergmate feedback dialog showing 3 options and a text field.

ErgMate Feedback Dialog

This dialog box collects the data and submits it to a php script on the website:


    def OnSubmit(self, event):
        feedbacktype = self.getFeedbackType()
        feedback = self.feedbackText.GetValue()
        version = buildInfo.getVersion()
        build = buildInfo.getBuild()
        params = urllib.urlencode({'t':feedbacktype, 'b':build, 'v':version, 'f':feedback })        
        try:
            f = urllib.urlopen(ErgMateGlobals.feedbackUrl, params) 
            done = True
         except:
            # do something rational here

The php script on the website collects the input, urlendcodes it, and adds it to a google docs spreadsheet by emulating a form subission from a form on that spreadsheet. Matt Casperson outlines the method in his blog article ‘Submit Data to a Google Form with PHP.

The heart of the php form-submission script looks like this:


$data =         "key=p......Q&embedded=true";
$data = $data . "&entry.0.single=" . urlencode($fbtype);
$data = $data . "&entry.1.single=" . urlencode($emversion);
$data = $data . "&entry.2.single=" . urlencode($embuild);
$data = $data . "&entry.3.single=" . urlencode($fbtext);
sendToHost( "spreadsheets.google.com", "POST", "/formResponse", $data ); 

This will add a row to the spreadsheet:
Google docs spreadsheet showing ErgMate feedback.

This mechanism is convenient for the user and simple to implement.

Posted in Micro-isv, programming, Python | Leave a comment

Rowing Q/A Site on Stack Exchange

Saw this proposal for a rowing question / answer site on stack exchange posted on the Concept 2 Forum. What a great idea. The difference between this and a normal forum is that answers are voted up or down by others. Over time the best answer migrates to the top.

Posted in rowing | Leave a comment

A Journalist’s First Ergatta

Cleveland Plain Dealer columnist Zachary Lewis rowed his first 2K erg race and wrote about it. I’m just impressed with his time, that being only the 2nd time he’s ever rowed a 2K erg piece:

Indoor rowing machines’ virtual experience a whole-body workout: a Stretching Out column

Posted in indoor-rowing, rowing | Leave a comment