Slide on overlay demo

by jaymz on 14/02/2012

This is a test embed of this simple swipe on hover:

Embed code:


<iframe src="http://jaymz.eu/demos/swipe/" width="300" height="330" scrolling="no" frameborder="0">iframes needed</iframe>

No Comments

Automatic superusers via Active Collab for django

by jaymz on 21/02/2011

Two things I use a lot at work – Django and Active Collab. One is the python framework we build everything on and the other is a project management tool that we use – think a local install of Basecamp roughly.

It can get annoying when we create development versions of things we’re working on and have to go and create test users for people; so I thought since writing an auth backend for django is so easy why not just use that to allow any user with a valid Active Collab account to login to the dev admin.

The code is on github and will automatically create a superuser in django’s auth table. Users can then login with their active collab emails & passwords without having to pass around test accounts. It also means users wont suddenly lose access when you nuke the database for imports saving you some earache. Just add your base active collab url to the AC_URL variable in settings.py and add ‘acollabauth.backends.ActiveCollabBackend‘ to your AUTHENTICATION_BACKENDS tuple.

I have also blogged about this over at udox.

No Comments

Active Collab library in Python

by jaymz on 16/02/2011

We use active collab at work to manage our various projects and track issues on sites we’re building. It comes complete with a REST API which returns results in XML. So I’ve written some code that abstracts out the process of making a request and displaying the returned data. It’s, predictably, on github.

Here’s an example based on the 0.2.0 code which is simply outputting data for now allowing me to check on open tickets easily from code. Remember, to enable write methods to work (setting a ticket to complete for example) you need to have Write Access enabled via the config.php file.

In [1]: from activecollab.library import ACRequest
 
In [2]: req = ACRequest('projects')
 
In [3]: req.execute()
34: AC 101: http://my.ac-site.com/projects/34
# More results trimmed
 
In [4]: req = ACRequest('projects', item_id=34, subcommand='tickets')
 
In [5]: req.execute()
2208: ie6 error when zooming on map: http://my.ac-site.com/projects/34/tickets/1: 1
2216: new user accounts for testing: http://my.ac-site.com/projects/34/tickets/3: 3

I’ve also blogged about this over at our udox company site.

No Comments

Redirecting users in django based on client IP

by jaymz on 15/02/2011

geoip-redirect is available on my github page.

No Comments

Geocoding and radial search of data for django apps

by jaymz on 5/12/2010

Something that I’ve had need of more than once the past while is placing lots of address data on google maps. For a few places it’s easy to manually handle that but I’ve been having to work with databases with thousands and thousands of samples – many in an unclean form with fields missing.

I’ve ended up with a small django based library over at github. For the data I had to work with much of the complications where the mis-matching of city/town level names – for example as well as London many items had the actual area listed instead, e.g. Camden or Westminster. When doing queries we wanted to be able to return items within certain areas but without having to manually clean everything up, so the model code provides a within_radius method which will return matching enteries that fall within the radial bounds given.

Within the scripts folder there’s an example of how I decided to work with an existing django based site that I then installed the geosearch code to.

#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
 
# To run this you'll need to set two environment variables. Could probably do this
# as a management command but seems a bit messy since it's a very specific thing...
#
# export PYTHONPATH=/home/jaymz/development/www/vansemea
# export DJANGO_SETTINGS_MODULE=settings
#
# Obviously you'll need to change that path if you want to run it yourself
 
from locator.models import Dealer, City
from geosearch.models import GeoEntry
from base.models import Country
from django.db.models import Count
 
MAX_TOP_CITIES = 30 # how many of our "has the most dealers" to bin the others into
BOUNDRY_RADIUS = 25 # number of *miles* from our source point to include
CTYPES = {
    'dealer': 32,
    'city': 29,
}
 
for country in Country.objects.all():
    try:
        cities = Dealer.objects.values('city__pk', 'city__name') \
            .filter(country=country).annotate(Count('city')) \
            .order_by('-city__count')[:MAX_TOP_CITIES]
    except IndexError:
        print "No data for %s" % country.name
 
    print "Working out cities for %s\n" % country
 
    for city in cities[::-1]:
        # Look up the GeoEntry for this city. If we have one then we'll get
        # back a list of other enteries which are within BOUNDRY_RADIUS miles
        print "\nGetting db places within %dmiles of %s...\n" % (BOUNDRY_RADIUS, city['city__name'])
 
        try:
            primary_city = City.objects.get(pk=city['city__pk'], country=country)
            primary_city.primary_city = primary_city
            primary_city.save()
        except:
            "Could not find city matching %d and country id %d" % (city['city__pk'], country.pk)
            continue
 
        try:
            city_geoentry = GeoEntry.objects.get(content_type__pk=CTYPES['city'],
                object_id= city['city__pk'])
        except GeoEntry.DoesNotExist:
            print "No geoentry for %s" % city['city__name']
            continue
 
        radial_results = GeoEntry.within_radius(
            [city_geoentry.latitude, city_geoentry.longitude],
            BOUNDRY_RADIUS
        )
 
        # Trim off our source point, reverse and update our source cities
        # (we need to reverse it to have it assign by most populated last)
        for point in radial_results[1:][::-1]:
            if point['content_type'] == CTYPES['city']:
                source_city = City.objects.get(pk=point['object_id'])
                source_city.primary_city = primary_city
                source_city.save()
                print "Set %s as primary city for %s" % (primary_city, source_city)
No Comments

WordPress plugin to post to Facebook wall and Twitter feed

by jaymz on 21/10/2010

We’ve recently had to do some automatic posting of content to facebook from a wordpress blog. I did find this wordbook plugin but it apparently has broke recently and people have been complaining it no longer works (27 out of 27!). So I’ve rolled my own. It’s in a very early stage but the code seems to work ok.

Instructions (you’ll need to create a new application and then authorize that for your user) and code are all over at github. I can’t really tell if I’m “doing it right” but it’s working and is a start. Fork and be happy…

Updated I’ve now added in support to push the title to twitter. I’m currently working on hooking in Bit.ly support to add the short URL to the tweet. Code is pushed to GH.

More updates The twitter posting now uses the post tile + a bit.ly link to your blog permalink. I’ve decided it’s now worthy of v0.2!

No Comments

Integrating ooyala in django (or just python)

by jaymz on 14/07/2010

Ooyala is a feature rich video hosting platform. Something I needed recently was some way to link the data over at ooyala into a django site I’m building. So I wrote myself a library. It’s available over at github and it’s called (predictably) django-ooyala. Currently there is a management command syncooyala to pull in all the data using the Backlot Query API. These imported items are then linked to a specific URL. Finally in your templates there is a ooyala_video tag which when given the current path (via request.path) returns the <script> tags needed for it to render.

Expect some updates as I flesh it out into the front end over the next few days.

Updated (11th August): I have added in analytics support. You can now make requests for video stat’s for a given account or video. The facebook SDK has also been added with a new template tag to output the headers in your template for a given video. Remember to request whitelisting from facebook for SWF embeds to work.

from django.http import HttpResponse
from ooyala.library import OoyalaAnalytics
from ooyala.constants import OoyalaConstants as O
from ooyala.models import OoyalaItem
 
def backlot_query(request):
    req = OoyalaAnalytics(video=OoyalaItem.objects.all()[0].embed_code, \
        method=O.ANALYTIC_METHODS.VIDEO)
    ooyala_response = req.process()
    return HttpResponse(ooyala_response.toprettyxml(), mimetype="text/xml")
1 Comment

Tube Delay Refund for android released

by jaymz on 14/07/2010

Update (v1.4.0) National Rail & TFL Travelcard support has been added. (August 2nd)

Update (v1.3.2) Some layout rejigging has been done, defaults added and a few more menu options for resetting/prefilling. The preferences layout has also been tidied. (July 17)

Updated (v1.2.0) I have updated this app to disable submission until all the station/date info is added. I’ve also added some more labels to show what’s been entered so far. You must make sure you’ve filled in all the preferences or else it’ll fail (Click menu>preferences). (July 16)

A few days ago I was in bed trying to sleep and I suddenly thought it would be good if there was an app to submit refunds for the tube as you come out. I had in my head the idea of a timer that would count down from 15 minutes and then alert you that you were in valid refund territory.

After I coded said timer, I pushed it live without refund submissions working. I also did a quick google to see what else there was only to discover that there was a company that released the exact same app on the iPhone about 3 months ago. Let this be a lesson that if you are about to code something as an exercise don’t go googling first or you’ll inevitably be put off because “whats the point”.

Several hours later today and it is now submitting refund applications to TFL and I get an email confirmation with the reference number. I’m very happy if incredibly tired. The app is free for now, all the others that do these on Blackberry/iOS are paid for. There doesn’t seem to be one for android yet, the guys that did the iPhone app said they where working on one way back in March or April, not quite sure what happened to it. They’re about to release the blackberry one so for now this is the only refund submission app on android :D Took me basically 2 days part time.

From a technical point of view this is making use of the apache http libraries to do a GET request for the TFL refund page. It parses that to grab the ASPX Viewstate variable and session cookies. Then it grabs the data from the main activity and combines that with the data stored in shared preferences for the form variables. The POST request is processed and the response parsed again to find the reference number. That’s then displayed via a Toast call. Fairly simple, having to deal with the viewstate crap was probably the most annoying part, that and debugging the actual POST.

4 Comments

SpineMagazine.com radio player & news reader for android

by jaymz on 2/07/2010

Quite a while back I was trying to get my head around the fairly complex ListView control for android and something I thought perfect for it was the set of radio shows over at spine magazine.

I have had this code sitting around for a while and I thought why not knock out the news code and release it and then just continue to work on it and update it. As the saying goes, release early, release often! I think it’ll be easy enough to add in reviews using the same sort of code to get the data and just re-using the show layout. This particular app was a lot more complicated than the django-reference thing, so here is some of what I’ve learned… You can get this in the marketplace now. Bug reports are expected & indeed welcome.

Warning! Technical crap follows.

It takes a bit of time to get your head around it, essentially you subclass the ArrayAdapter class with a container class to hold your list view elements. The ArrayAdapter is a templated class so you first need another class that is actually going to hold your data. This is were you’ll need to create a class for your data and then instantiate the ArrayList with this type. The code to hold my news post data is very simple:

package eu.jaymz.spinemag;
 
import android.util.Log;
 
public class NewsPost {
    private String title;
    private String description;
    private String date;
    private String author;
 
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }
    public String getAuthor() {
        return author;
    }
    public void setAuthor(String author) {
        this.author = author;
    }
    public String getDate() {
        return date;
    }
    public void setDate(String date) {
        this.date = date;
    }
 
}

Then in my main activity class I cast the templated ArrayList to a NewsPost class:

ArrayList<NewsPost> spr_news = new ArrayList<NewsPost>();

With the data structure sorted I need a method in my ListView activity to actually fill in the ArrayList with data. This is very typically something along the lines of the following, here I read the JSON data from a URL, decode it and assign it to the class members, finally appending it to the ArrayList from earlier.

private void getPosts() {
        try {
            URL url = new URL("url for data");
            BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
            String str = in.readLine();
            in.close();
            spr_news = new ArrayList<NewsPost>();
            JSONObject json = new JSONObject(str);
            JSONArray posts = json.getJSONArray("posts");
            for(int x=0; x < posts.length(); x++) {
                JSONObject post_data = new JSONObject(posts.get(x).toString());
                NewsPost post = new NewsPost();
                post.setTitle(post_data.get("title").toString());
                post.setDescription(post_data.get("description").toString());
                post.setDate(post_data.get("date").toString());
                post.setAuthor(post_data.get("author").toString());
                spr_news.add(post);
                //Log.d("NEW", "added a post - "+post.getTitle());
            }
        } catch (Exception e) {
 
        }
        runOnUiThread(setPosts);
    }

With all the above in place the code is at the point where there is now an array full of structured data for our ArrayAdapter to show. To do this the ArrayAdapter needs subclassed to work with our earlier NewsPost classes members:

private class NewsAdapter extends ArrayAdapter<NewsPost> {
 
        private ArrayList<NewsPost> items;
 
        public NewsAdapter(Context context, int textViewResourceId, ArrayList<NewsPost> items) {
                super(context, textViewResourceId, items);
                this.items = items;
        }
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
                View v = convertView;
                if (v == null) {
                    LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                    v = vi.inflate(R.layout.post, null);
                }
                NewsPost o = items.get(position);
                if (o != null) {
                    /* hmm, this looks proper ugly */
                    TextView title = (TextView)v.findViewById(R.id.post_title);
                    TextView description = (TextView)v.findViewById(R.id.post_description);
                    TextView date = (TextView)v.findViewById(R.id.post_date);
                    TextView author = (TextView)v.findViewById(R.id.post_author);
 
                    description.setText(o.getDescription());
                    title.setText(o.getTitle());
                    author.setText(o.getAuthor());
                    date.setText(o.getDate());
                }
                return v;
        }
    }

All this code is really doing is loading the layout resource XML for our row and binding the data from the array elements members to views within the XML. Finally we need to tell the list view to update. Typically the above code has all been kicked off and ran in a thread, populating the ListView when it’s actually finished without stalling the phone itself.

for(int i=0;i<spr_news.size();i++) {
    n_adapter.add(spr_news.get(i));
}
m_ProgressDialog.dismiss();
n_adapter.notifyDataSetChanged();

All the above is doing is updating the ArrayAdapter and adding our ArrayList elements to display. We then signal that the data has changed which will cause the ListView itself to update. Simple! :) Again, I must make the point of how verbose this all feels when I’m coding in python all day. I’m sure it needs a good refactor to now but I’m a lot more familiar with the way android works with layouts and indeed strong typing :)

1 Comment

Google Blogger to Django integration

by jaymz on 30/06/2010

I’ve been working a lot on Vans recently and they have a large number of blogs that are currently hosted on the blogger platform. This works really well for them, they have a straightforward & easy to use blog platform that does what they need it to do.  The sites themselves work great as they are but the integration into the main site isn’t quite as nice.

If you go to the blogs section on vans as it stands it will pull in an XML feed of all the current blogs and display them on one giagantic page. It can take a fair bit of time to load and its hard to see how each different blog gets displayed as its really one big list. For now it’s not so easy to pull in bits of content from the various blogs without someone having to mess with files or copy & paste, with the build in django I wanted to create a much cleaner & easier way to work with this content.

For this I introduce django-blogger, a django application which will integrate Google Blogger blogs via their RSS feeds. As it is it will import the blogs for a given profile id and then sync up with the latest data via their RSS feeds. These can be enabled easily for your given blogs. When you first install it comes with some admin actions which will all ow you to sync up the blogs manually all at once. There is also a management command, syncblogs, which is more suited to scheduling an update via cron (if you’re going to use cron you might be interested in django-crontab).

This works on the feeds and not an archive, so it doesn’t require authentication, just access to the feed URL. A basic template is included to show how to render out the blog posts & blogs as a menu, I override these myself for the format I need. The app itself now lets me pull content from any of the blogs and use it within the rest of the django based site cleanly & easily. Rather than directly reading and displaying via the feed URL I’m creating actual objects for each post and blog so it’s easily extendible also, say to return posts in various formats or pulling images from each blog post to create blog galleries automatically.

The code is available from GitHub.

3 Comments