Friday, October 31, 2008

Dear apple

(permalink)
Picture 1
Apple Receipt,
originally uploaded by odiosam.
Please stop sending me receipts for free downloads from the app store. They're clogging my inbox.

While you're at it, you might as well not require that I input my account password to download them as well. It's a hassle on the tiny keyboard, and pointless (somebody's going to steal my phone and rack up charges downloading free software?)

Wednesday, October 22, 2008

Using Gmail with Django

(permalink)
It's easy to set up django to send emails through Gmail. Just use the following settings:


DEFAULT_FROM_EMAIL = 'user@gmail.com'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_HOST_USER = 'user@gmail.com'
EMAIL_HOST_PASSWORD = 'password'
EMAIL_USE_TLS = True
EMAIL_PORT = 25


Gmail supports other ports, which you can use as well. This is important if you're running thee server on your local machine, and your ISP blocks port 25.

Labels:

Tuesday, October 21, 2008

testing out twitter feed.

(permalink)
I've been trying to integrate all my online "personalities" and I think I've finally got it.

Here's what I have:
- Startup twitter feed (divvyshot)
- Personal twitter feed (sodio)
- This blog
- The divvyshot blog (coming soon)
- Friendfeed
- Facebook
- Linked in

What I'm doing is using twitterfeed to repost my blog posts on their respective twitter feeds. Then I'm using FriendFeed to aggregate the two twitter feeds, along with LinkedIn. I think have installed the facebook FriendFeed plugin, which should aggregate all that data on my fb wall.

We'll see how it all goes...

Friday, September 26, 2008

taking quick notes

(permalink)
I usually email myself stuff I want to remember. That's nothing new - I'm sure most of heard of it before.

But what about quick notes that don't merit an email, or even a post-it?

For example, whenever I'm on the phone with some company I get a confirmation number... they're usually worthless but sometimes can come in handy. I don't want to clutter my inbox or my desk with these confirmation numbers.

Instead, I google them.

For example, I just talked to USPS about an address delivery problem. They gave me a confirmation number, which I promptly googled: "usps confirmation #CO329235921" There's a google bar in most browsers these days... so and I leave my browser running throughout the day so this is pretty convenient. Then if I ever need to talk to them again, I hit CMD-Y (for history), and search "usps conf..."

Of course google searches aren't 100% private - so be sure to only google stuff you can afford to publicize.

Another tip: I set my browser to keep a 120-day history (I find I'm always looking for stuff I visited several months ago, and storage is cheap, so why not). You may want to consider changing your default expiration if you think you're going to need your notes for longer than a month.

Labels:

Thursday, September 18, 2008

Tried change_stage in module django.contrib.admin.views.main. Error was: 'module' object has no attribute 'change_stage'

(permalink)
Another Django upgrade hint:
Tried change_stage in module django.contrib.admin.views.main. Error was: 'module' object has no attribute 'change_stage'



Your forgot to update urls.conf as follows:

# OLD:
from django.conf.urls.defaults import *

urlpatterns = patterns('',
(r'^admin/', include('django.contrib.admin.urls')),
)



# NEW:
from django.conf.urls.defaults import *
from django.contrib import admin

admin.autodiscover()

urlpatterns = patterns('',
(r'^admin/(.*)', admin.site.root),
)

Note to self

(permalink)
This is an excellent post about being a web entrepreneur:

Jason Fried - 10 Things We’ve Learned at 37Signals

Thursday, July 24, 2008

Django: Error while importing URLconf 'django.contrib.admin.urls': No module named urls

(permalink)
I didn't see a lot on google about this error so I thought I'd post something. If you're getting it, it's likely you updated to the latest Django SVN release, and haven't upgraded your admin site's configuration.

Read more here: http://code.djangoproject.com/wiki/NewformsAdminBranch

Thursday, July 03, 2008

One button sign up (continued)

(permalink)
There have been a number of comments about my previous post a one button sign up. I thought I'd re-post them here and clarify.

OpenID is easier: http://openid.net/

OpenID is easier and it's not mutually exclusive to what I'm suggesting here. OpenID or not, many websites will still need to collect additional information. The idea is not to force the user to give you that information in order to use basic site functionality.

If a user sees an auction ending in 1 minute but is then required to jump through some hoops before bidding - thats just as bad an experience.

You're right - so maybe eBay should require accounts just to browse listings? Obviously, that idea doesn't make sense. You shouldn't force the user to sign up early just so that in the off chance they want to bid on an item that's ending soon, they can.

Instead, I'm suggesting you give the user as much access to the site as possible, as soon as possible. Prompt the user for additional information with messages like "Update your address for quick bidding." If your users decide to wait, that's their decision - don't make it for them.

I want to feel involved. Plus, if I'm using a website to the extent that I'm going to want a username and password I pretty much expect that I may have to fill out more information upon registration so it is not as bothersome.

I disagree. Long and tedious registration forms are a horrible way of involving the user. The less information a user needs to enter for the same functionality, the better.

By giving people random user names, you force them to do more work long term.

Step 1: Click the one button and get my user name Step 2: Go write it down somewhere Step 3: Cookie expires/is cleaned - now user forgets the random user name or email. Step 4: Go look it up, enter info


The user should never actually see (or need to remember) their random username. What I was referring to is simply a unique backend identifier. Tracking a user without a username isn't that radical - even Amazon does it.

Amazon (and other stores) do one button sign ups

When I first visit Amazon, the site gives me as much functionality as possible. I can look at products and even add them to my cart - without logging in. Like I was suggesting - Amazon does upsell for more information, prompting you with messages like "Sign in to turn on 1-Click ordering."

After I've visited a product page, I'm in Amazon's database. In this example, simply viewing a product is the equivalent of "signing up" - even though the user doesn't realize that. That's great. Sign up buttons don't always have to be big and green. Ideally, the first step of the sign up process should occur transparently.

Every time I return to the site, Amazon recognizes who I am and suggests similar products to ones I've already viewed:



Now, if I choose (or am required) to create a login, Amazon seamlessly associates it with all my previous "anonymous" data. For example, I still have my previous browse history:


By making it as easy as possible to start using the site, creating a "transparent user" to track my history, and up-selling to gather more information in order to gain additional functionality, Amazon is doing almost exactly what I described in the previous post.

But why limit this process to online stores which by their nature must collect most user information during checkout? Every site should collect as little information as feasible and do it as late in the user experience as possible. That's the whole premise behind one button sign ups.

Wednesday, July 02, 2008

One button sign up

(permalink)
I've stumbled across a new sign-up process: one button. That's it. From now on, the user will only have to click a button on all of my new projects to sign up.

"But Sam," you might ask, "How will you collect user information?"

Easy. Ask for it when you need it. If you only ask for the user's address when the user wants to do something that requires their address, then you have a carrot to encourage the user to give you that information.

If you ask for the address up front, then not only does the user have little incentive to give it to you, but you discourage the user from signing up at all

Take, for example, ebay's registration form:



Does ebay really need my address if I just want to watch an item? Requiring me to fill out all this information just to preform basic actions (like watching an item or searching closed auctions) discourages me from using the site at all.

Why not not create a "one button" sign up with a default user account and random username? Allow me to use as much of the site as possible, while asking for (but not requiring) information to gain additional access.

"But Sam", you counter again, "what if the user forgets their random username?"

That's easy, authenticate with cookies and/or a unique URL (see craigslist). At the same time, prompt the user (maybe at the top of every page) for a unique username or email address for logins.

EDIT: I've continued this discussion in my next post, One button sign up (continued)

Monday, June 23, 2008

Free Mohammed Maree

(permalink)
By now, you've all probably heard of James Buck - a university student jailed in egypt. After twittering that he was arrested, friends, journalists, bloggers and many in the online community rallied for his release.

While it's nice to see the world unite behind such a good cause it's unfortunate that James' friend (Mohammed) hasn't received the same level of attention.

Needless to say he's still in some Egyptian jail, having endured several weeks of torture: http://jameskarlbuck.com/


Interested in helping? Check out James' blog

Labels:

Wednesday, June 18, 2008

Well I cancelled embarq... and I now have a new ISP

(permalink)
My new ISP
My new ISP,
originally uploaded by odiosam.
I've had embarq for about 2 years, and I think I'm fed up with them. I was paying ~$200/mo for business class DSL with a few static IPs. For that price, the connection should be FAST and rock solid.

It wasn't.

After about a weekend of downtime (which caused a permanent 35% decrease in BluWiki's traffic) - I was done. Here's my solution: I'm hosting my servers on slicehost for ~$130 / month, and for my personal internet, well, I'm using my friends' connections :)

In the attached photo, you see what I came up with to facilitate doing that.
Parts include:
- DLB 2300 Deliberant AP (no longer sold, had this laying around)
- Buffalo WHR-G125 (not sold in the US, you have to buy it off ebay)
- U.FL to RP-SMA adapter (for the buffalo's antenna)
- Hawking Hi-Gain Directional Corner Antenna 15db
- Yagi 2.4GHz 14.5dBi
- 4 port switch
- Power strip
- Cheap tripod

Basically, I followed the instructions over at i-hacked (www.i-hacked.com/content/view/261/42/), except I substituted the WHR-G125 for the router and the 90 degree corner antenna instead of the yagi. This setup will scan within a 90 degree radius for the strongest open network.

I then use the DLB 2300 in WISP mode to aim the Yagi antenna at the network and repeat it on the switch.

I've decided against repeating the network wirelessly to eliminate any WIFI interference.

It works pretty well :)

Wednesday, June 04, 2008

Error creating thumbnail: /path/to/wiki/bin/ulimit.sh: xrealloc: ../bash/subst.c:514: cannot reallocate 512 bytes

(permalink)
MediaWiki's software was giving me this error, and I couldn't find a solution on google. I thought I'd post one.

I was able to fix the problem by moving the bin folder to bin.bak, downloading a new copy of mediawiki, and copying the bin folder from the new installation.

I suspect that the error occurs when you set the permissions on ulimit.sh to global read-write (777). The ulimit.sh in the new bin directory was set with limited permissions:

total 20K
-rwxr-xr-x 1 root root 88 Jun 5 04:18 svnstat
-rwxr-xr-x 1 root root 52 Jun 5 04:18 ulimit-tvf.sh
-rw-r--r-- 1 root root 53 Jun 5 04:18 ulimit.sh
-rwxrwxrwx 1 root root 53 Jun 2 01:54 ulimit.sh.bak
-rwxr-xr-x 1 root root 48 Jun 5 04:18 ulimit4.sh


Correcting the error may be as easy as changing the permissions, but if that doesn't work, you can follow the steps I outlined above.

Labels: , ,

Tuesday, May 27, 2008

a quick tip: the disk "name-here" is in use and could not be ejected

(permalink)
Under Leopard I seem to get this error relatively often when I'm trying to eject my external disks. Even after quitting all my applications, the error doesn't go away. I never want to disconnect my drive without unmounting it (maybe it's an OCD thing). Here's my solution:

First, get the device name of the drive: Disk utility > Select volume > Click Info > Then note the disk identifier.

Open up terminal to check which applications are using this drive (substitute your drive name):
lsof /dev/disk2s10


Quit (or kill) all the processes that are using the resource. If nothing is returned (as is frequently the case with me), then force umount the drive (substitute your drive mount point):
sudo umount -f /Volumes/Backup


I'm adding this because the man page on umount doesn't document the force (-f) option.

Labels: , ,

Saturday, May 17, 2008

Extending the user model: profiles in Django

(permalink)
I think the documentation about using profiles & the get_profile() function isn't as clear and/or elegant as it could be. The problem with django's recommended implementation of profiles is that when a user is created, a user's profile isn't automatically created - it's not part of the same model. Managing the two can be tricky - if you mess up, you're bound to get ObjectDoesNotExist errors.

My solution was to never use get_profiles() directly - but instead add a helper method where any ObjectDoesNotExist errors are caught and resolved:


First, create a profile class in models.py:
from django.db import models
from django.contrib.auth.models import User

class UserProfile(models.Model):
    karma = models.IntegerField(default=1, core=True)
    url = models.URLField(default="", core=True)
    user = models.ForeignKey(User, unique=True)

Note, if you want to be able to create profiles using the Django admin interface, change the last line to the following:
user = models.ForeignKey(User, unique=True, edit_inline=models.TABULAR, num_in_admin=1,min_num_in_admin=1, max_num_in_admin=1,num_extra_on_change=0)


Add this line to settings.py:
AUTH_PROFILE_MODULE = 'core.UserProfile'

(change your line to 'appname.ModelName' - note, do NOT include your project name or anything else. Just your application name and model name (the model name is UserProfile, unless you change it).

Finally, add to views.py:
from django.contrib.auth.models import User
from project.core.models import UserProfile
from django.core.exceptions import ObjectDoesNotExist

def get_or_create_profile(user):
    try:
        profile = user.get_profile()
        except ObjectDoesNotExist:
        #create profile - CUSTOMIZE THIS LINE TO OYUR MODEL:
        profile = UserProfile(karma='1', url='http://example.org', user=user)
        profile.save()
    return profile


Now, in views.py, to access a user's profile, you only need two lines:
user = User.objects.get(pk = user_id)
user.userprofile = get_or_create_profile(user)


And, say if you wanted to change a value:
user.userprofile.karma += 1
user.userprofile.save()


Easy, eh?

Labels: , ,

Wednesday, May 14, 2008

SICP and promises

(permalink)
A few days ago I blogged about be working through SICP in ARC. I was going to track my progress on bluwiki.

My personal goal was to make some progress every day. That hasn't happened.

I'm thinking about abandoning ARC, and just working through SICP in scheme. Scheme & ARC are remarkably similar, it seems the only difference is semantics. It'd be a lot easier scheme, since I wouldn't have to translate all the problems. Also, the language is more mature - so I suspect the libraries are more robust.

We'll see - I'm going to take a crack on SICP 1.2 and 1.3 this weekend, and I'll make a decision after that.

Labels: ,