Django Admin Autocomplete JS Library Issues

Just adding a quick post on this here as much of the stuff on various forums (here, here) wasn’t exactly what I was looking for…

While attempting to implement Django Autocomplete Light within my Django admin, I encountered the following error:

select2.full.js:491 Select2: An instance of jQuery or a jQuery-compatible library was not found. Make sure that you are including jQuery before Select2 on your web page.

The *reason* for the issue was pretty apparent: Django’s jquery.init.js library transforms the jQuery namespace into django.jQuery, and thus autocomplete libraries are unable to initialize properly.

Most pages suggested running Django’s collectstatic command, and ensuring dal and dal_select2 were loaded above django.contrib.admin in the settings file:

INSTALLED_APPS = [
     'dal',
     'dal_select2',
     'django.contrib.admin',
 ]

As my settings were configured properly, collectstatic didn’t resolve the issue, and there did not seem to be a way to manually rearrange the library loading order, I opted for a simple (perhaps less-than-ideal-but-gets-the-job-done) resolution: include jQuery a second time on that page by defining it within the Meta js property of the admin.ModelAdmin object:

class PersonAdmin(admin.ModelAdmin):
    form = PersonForm
    class Media:
        js = (
            'admin/js/vendor/jquery/jquery.min.js',
        )

However that only gets us halfway there as I then encountered the following exception:

jquery.min.js:2 Uncaught TypeError: $(…).select2 is not a function

Basically the autocomplete libraries still need to be initialized with the new jQuery namespace. I re-included the autocomplete jQuery init library, and to tidy things up even more, I created an abstract AutocompleteAdmin object to inherit from:

class AutocompleteAdmin(admin.ModelAdmin):

    class Media:
        abstract = True
        js = (
            'admin/js/vendor/jquery/jquery.min.js',
            'autocomplete_light/jquery.init.js',
        )

class PersonAdmin(AutocompleteAdmin):
    form = PersonForm

class PlaceAdmin(AutocompleteAdmin):
    form PlaceForm

After that, autocomplete works like a charm! Hope that helps someone out there!

Kill Port Process on Synology Diskstation (Linux)

Every now and again, my Django server will time out, but when attempting to restart I’m faced with the following error:

Error: That port is already in use.

Most solutions out there – such as using the fuser command – were of no help as Synology’s OS is pretty vanilla. I was able to find a solution though on Stack Overflow:

First run the following to retrieve your Port Id (PID):

$ ps aux | grep -i manage

This will return something like the following:

$ user <PID>  ... /volume1/web/bryanhadro_django_project/venv/bin/python manage.py runserver 0.0.0.0:9000

Or for example:

$ user 12345  1.3  5.2 893874 84987 pts/12   Sl+  06:45   0:47 /volume1/web/bryanhadro_django_project/venv/bin/python manage.py runserver 0.0.0.0:9000

Where the first number after your username – 12345 – is the PID. Using that number, all we need to do is run /bin/kill <PID>:

$ /bin/kill 12345

You should now be good to restart your Django server!

Setting Up a Python 3 Django Development Site on Synology Diskstation

Today I’m going to focus on getting a Django site up and running (for development only) on your Synology Diskstation. I’ll be doing this with a Virtual Environment as well as requirements.txt file for package installation, as I do with all my Python projects.

Pre-Requisites

This tutorial is for users who have already setup SSH connectivity on their Diskstation, and have a basic familiarity with using their terminal.

If you haven’t already, install Web Station and Python 3 via Package Center on your Diskstation. Web Station should create a default web directory in a location similar to /v1/web. Be sure you have user rights to edit within this folder. Python3 should be installed in a location similar to: /v1/@appstore/py3k/usr/local/bin/python3

Make a note of that location, as we’ll need to make use of that executable the first time to begin our setup.

Within your /v1/web folder, create your site’s directory and navigate into it:

user@diskstation:/v1/web$ mkdir my_django_project && cd my_django_project 

Create a Virtual Environment

Using the full python3 path noted above, create the venv Virtual Environment:

user@diskstation:/v1/web/my_django_project$ /v1/@appstore/py3k/usr/local/bin/python3 -m venv venv

Now activate the Virtual Environment via the following command:

user@diskstation:/v1/web/my_django_project$ source venv/bin/activate

Note: now that you’ve installed and activated venv, the python3 command should point to the binary within that environments packages, and not the global Python 3 installation. You can confirm that by the following command:

(venv) user@diskstation:/v1/web/my_django_project/website$ which python3

Install Django

Create a requirements.txt file in which we’ll define our Django as well as our other Python packages:

(venv) user@diskstation:/v1/web/my_django_project$ touch requirements.txt

Open that file, and add the following:

django==2.2

Note that ordinarily you’d want a more recent version, or specify no version at all to get the latest. However I believe Synology’s Python 3.5.1 version is only compatible with 2.2.

Close and save requirements.txt. With venv activivated (which it should already be), use pip to install:

 (venv) user@diskstation:/v1/web/my_django_project$ pip3 install -r requirements.txt

Django should now be installed. Let’s use it to create our site:

(venv) user@diskstation:/v1/web/my_django_project$ django-admin startproject mysite

Run Server

Now, change directory into your new mysite project and startup Django’s development server:

(venv) user@diskstation:/v1/web/my_django_project$ cd mysite
(venv) user@diskstation:/v1/web/my_django_project/mysite$ python3 manage.py runserver 0.0.0.0:9000

Note that we need to use 0.0.0.0 as the domain here as opposed to 127.0.0.1 or localhost. The latter two won’t work.

Also note: I did initially encounter the following error at this point, though venv was activated and Django installed:

ImportError: Couldn't import Django. Are you sure it's installed and available on your PYTHONPATH environment variable? Did you forget to activate a virtual environment?

In all honesty, I’m not sure what resolved it, but when I came back to the project later everything worked as it should. Almost certainly user error.

Add Internal IP to Allowed Hosts

The last step before we can access the site in our browser is to add your Synology’s internal IP to the Django settings file, my_django_project/mysite/website/settings.py:

ALLOWED_HOSTS = [
     '<YOUR DISKSTATION IP HERE>'
 ]

If all went well, your Synology-hosted Django project should be available for viewing by your browser on port 9000:

http://<YOUR DISKSTATION IP HERE>:9000/

And that’s it, hope it was helpful!

Further reading:

Charles in Charge: Actual Mobile Testing with Charles Proxy

There are several decent mobile testing services out there. One that I’ve used significantly is Browserstack, which indeed is pretty good. Still, in my experience, nothing beats testing your site on an actual mobile device.

Further, though anyone with an internet connection can access a public site on their phone, if you have to access something on your computer or Sandbox/UAT server that’s available only by VPN connection, well… you’re up the proverbial creek. Or so you thought…

Accessing sites on your mobile device and through your computer’s internet connection is  made possible by the plethora of HTTP Proxy tools that are out there. But my favorite is Charles Proxy. They offer a persistent free trial version that runs for 15 minutes at a time (after which you’ll just need to restart it), so there’s no reason not to try. Download it for now, and if you like it and want to feed some hungry developers: buy it!

A few notes before we get started:

  • This tutorial is written for connecting to a Mac computer with an iPhone, but as a former Windows/Android man in my earlier life, the steps are for the most part the same.
  • Both your computer and mobile device must be connected to the same WiFi network. I would strongly advise that this network be a secured private one as we’ll temporarily opening up your machine for other devices to connect.
  • When finished testing, be sure to reset your phone’s proxy configuration back to “Off”. If you don’t, your phone won’t have any WiFi connection once Charles has been turned off, and you’ll be left wondering why the heck your phone won’t let you watch that cat video.
  • In the steps below, I am accessing a local site on my computer, which involves the additional step of configuring Apache to actually serve the page. That’s a separate tutorial for another time, but if you’re interested you can check out this tutorial which was how I learned to do that.

OK, let’s get started…

So let’s say you have this Sweet, Sweet Local Site (or something behind your Network Firewall). In either case, you can’t access it on your phone. In order to do so, you’ll need to enable Transparent HTTP proxying on your computer.

Start by opening Charles Proxy, select Proxy > Proxy Settings from the menu.
step-2

This will open up a window with a few panels.  In the first panel labeled “HTTP Proxy”, make a note of the Port number (which should be 8888), and check the box underneath which says “Enable transparent HTTP proxying”. This will basically allow devices connected to the network to connect to your machine via the aforementioned port. Again, warning that you should only be doing this on your home or privately secured network. Click “OK”.

step-3

Your Mac should now be open for your iPhone to connect.

Next, we’ll need your Mac’s network IP. For that we’ll use your terminal and grep. Open up your terminal and run the command: ifconfig | grep "inet". Basically what we’re doing here is searching through the network info dumped by the command ifconfig to find the IP address of your Mac. This value should be indicated by the keyword ‘inet’.

step-1

Grab your iPhone and open up Settings > Wi-Fi. To the far right of the currently selected network, touch the “i” icon to bring up information on the network.

step-4

Scroll down to the HTTP Proxy section, which should have a Configure Proxy option set to “Off”. Press that section and select Manual.

step-5step-6

This will bring up a section where you can enter the Server and Port that you want to proxy through. Enter the IP address and port number mentioned above for the values of Server and Port, respectively.

step-7

If you now try and access your site (or any website, for that matter) via your phone, Charles should now warn you via popup that a device is wishing to connect.

step-8

Click “Allow”. If everything went well, your iPhone should now be able to view the internet through your Mac’s network connection, and you can access Local and Fire-walled sites through your iPhone!

step-9

You can now test away! Just another reminder to reset your phone’s Proxy Configuration to “Off” when you’re done!

Happy testing!

 

Santa Claus According to George Hinke

George Hinke - Baking Cookies

Every December for as long as I can remember, we’d eagerly retrieve our Christmas decorations from their long-boxed-up slumber. Probably the most prized of which were our Santa Claus dinner placemats, which depicted various scenes of St. Nick, Mrs. Claus, elves and reindeer all prepping for their Yuletide escapades. A little internet sleuthing revealed that these scenes were actually illustrations commissioned for a children’s book by the name of “Jolly Old Santa Claus,” painted by German/American artist George Hinke.

George Hinke - Confectionery

From the Museum of Wisconsin Art Website:

George Hinke was born in Berlin, Germany, in 1883 and schooled in a classic style of painting. Mr. Hinke came to Milwaukee, Wisconsin, in 1923, where he worked at a printing shop until he opened his own studio. From 1944 until Mr. Hinke’s death in 1953, Ideals commissioned him to create many works of art. In addition to Santa Claus, Mr. Hinke’s subjects included American small-town life, American flags, and religious scenes – all in his classic, nostalgic style. The paintings in the 1961 Ideals Magazine Collector’s Edition of Jolly Old Santa Claus are rendered in oil on stretched canvas. The influence of Mr. Hinke’s German background is evident in the Santa Claus series: from Santa’s castle, which resembles the castles of Bavarian King Ludwig, to the Black Forest clock on the wall of Santa’s workshop to the elves themselves, who are reminiscent of those characters in stone that decorate many German gardens.

George Hinke - Christmas Tree

For me, these placemats provided the archetypal representation of what Santa Claus looked like — er, I mean — looks like, and all the little details were so fun and interesting to us as children. We still use them at mom and dad’s every year, and though the book can still be found easily enough through retailers like Amazon and Thriftbooks, actual full prints of the scenes are difficult to find. Thus I wanted to share them here for everyone to enjoy.

George Hinke - Reindeer and Sleigh

I’ve uploaded them here as HD photos taken with my iPhone 6 and cropped in GIMP. At some point perhaps I will use my limited photo-editing skills to restore some of the color and hide some of the placemat defects. But for now: Merry Christmas to all, and to all a good night!

Final onDatesChange with React-Dates

React-Dates is a pretty awesome date-picker library for React built by the developers over at Air BNB. It works well and it’s fairly customizable, so I recommend you check it out if you’re looking for a React datepicker.

Our Desired Functionality:
One issue we encountered – or rather desired functionality that wasn’t baked in and was a little tricky to get just right – was what we called “Final onChange.” Basically, we wanted to fire our onChange event handler only when the user was done interacting with the calendar. This could be when the user finished selecting a range of dates, or when default dates existed and the user selected a new valid startDate before clicking away. This functionality had been requested on their GitHub issues page, but in the end it was determined the logic was more appropriate for the parent component. So we set about figuring out how to build it there.

Our Original Implementation:

class DateRangeInput extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            startDate: null,
            endDate: null,
            focusedInput: null,
        };

        this.valuesDirty = false;
    }

    handleDatesChange = ({ startDate, endDate }) => {
        if (!startDate.isSame(this.state.startDate)) {
            this.valuesDirty = true;
        }
        this.setState({ startDate, endDate });
        if (this.props.onChange && endDate && !endDate.isSame(this.state.endDate)) {
            this.props.onChange({ startDate, endDate });
        }
    };

    handleFocusChange = focusedInput => {
        this.setState({ focusedInput: focusedInput });
        if (!focusedInput && this.valuesDirty && this.props.onChange) {
            this.valuesDirty = false;
            this.props.onChange({ startDate: this.state.startDate, endDate: this.state.endDate });
        }
    };

    render() { /* DateRangePicker here */ }
}

Using momentjs’s isSame method, we would fire the onChange handler if the endDate had changed, or if the startDate had changed and the user navigated away from the calendar. This allowed us to fire onChange when the user had selected a start date and navigated away from the calendar. However it introduced a problem: any other activity resulted in two onChange invocations – one when the start date was selected, the second when the end date was selected.

Attempting to rectify this issue was a little tricky for a couple reasons. First, because handleDatesChange is actually invoked after handleFocusChange. Second, because attempting to access values from state (in this case, startDate and endDate) isn’t a good idea because as we all know: setState is an asynchronous call. Accessing values from state randomly could be subject to a race condition.

Our Solution:

// handle onChange here to ensure state values are current, as setState is asynchronous
afterStateChange = () => {
    let { startDate, endDate, focusedInput } = this.state;

    // fire onChange if either date has changed and calendar has closed (whether automatic or click away)
    if (!focusedInput && this.valuesDirty) {
        this.valuesDirty = false;
        this.props.onChange && this.props.onChange({ startDate: startDate, endDate: endDate });
    }
}

handleDatesChange = ({ startDate, endDate }) => {
    // check if either date has actually changed
    if (startDate && !startDate.isSame(this.state.startDate)) {
        this.valuesDirty = true;
    }
    if (endDate && !endDate.isSame(this.state.endDate)) {
        this.valuesDirty = true;
    }

    this.setState({ startDate, endDate }, this.afterStateChange);
};

handleFocusChange = focusedInput => {
    this.setState({ focusedInput: focusedInput }, this.afterStateChange);
};

What worked for us in the end was first to move all of our logic to a common afterStateChange handler. This ensured the state values we were using would be current. Next we added a valuesDirty check for the endDate (as we had for the startDate) to indicate whether either of the values had changed. And finally, whenever the state was changed, we’d fire our onChange handler only when two conditions were met: (1) when focusedInput was null (i.e. the user had finished selecting a date range or clicked away) and (2) when either of the dates had changed. Easy peasy – just not immediately intuitive!

Hope that helps anyone out there who’s using React Dates and is looking for that extra event!

1472 Days

It’s been a while since I’ve posted anything. 1472 days, to be exact.

Gosh, I was just a newbie at U.S. News & World Report. So much has happened in that time…

Four years.
Three redesigns.
Two bosses.
One (old and outdated) WordPress site.

Oh, and I got married too. That’s kinda big, I’d be remiss if I didn’t mention that.

So my goal is to try and post something weekly. Probably on Fridays. Preferably related to software engineering. Ideally I’ll learn something along the way. And hopefully, someone else will too. That’s probably worth it, right?

As I’ve heard several people say (but most recently Gregg Hurwitz): “You can’t edit a blank page.” So here goes…

Georgetown

US News’ D.C. office is located on Thomas Jefferson Street NW in what is known as the Georgetown historical district. Georgetown predates the rest of the capital by about 50 years, and while its mostly known for embassy’s, retail, and films such as The Exorcist and Wedding Crashers, it’s also a really really cool place to work. The office is right next to the C&O Canal trail: Washington Harbor waterfront to the left, M street to the right. I gotta tell ya it’s pretty awesome grabbing a sandwich and just strolling down to the waterfront for lunch. So if you work in DC, or are just passing through sometime – give me a call, e-mail or text, and let’s grab some lunch or a beer!

star dot ico

It’s a tiny, seemingly insignificant, sixteen by sixteen pixel image.

But let’s be honest: it’s the first thing site visitors will notice when your site loads, and the only thing that will differentiate you from pretty much every other Bluehost WordPress site out there. And with how so very simple it is to change, let’s get a new favicon up there, shall we?

For those of you who don’t know what I’m talking about, a “favicon” is that square image thingy you notice in the left-hand corner of your browser tab when you visit a site. Standards provide you with the ability to define an individual one for your own site – but if you don’t, a default one will be used. The following steps are for this site (which is WordPress), but it should be easy enough to replicate for all. It’s a simple as:

  1. Using an image editor (cheap, Windows junkie I am, I use GIMP), create an image 64px x 64px.
  2. Design your image, but remember it’s going to have to look great as 16px x 16px. Less it more. Mine is the letter “b”. I am also not a designer.
  3. Scale the image to 16px by 16px.
  4. Save or export your image as a “favicon.ico”. If that extension is not possible with your image editor, you can either (a) get a plugin, or (b) save it as a GIF, JPG or PNG and Google any number of favicon generators out there… those can be hit or miss though.
  5. Upload the “favicon.ico” image to your site. Often, this will be the root directory. But in my case, WordPress was looking for the image elsewhere based on a link tag with the attribute of “shortcut icon”. In that case, I’d rename the existing image to archive it, and upload your new image there.
  6. Ensure the aforementioned link tag is in fact pointing to your new image. If the tag does not exist, it’s not a terrible idea to add it to the <head> block: <link rel="shortcut icon" href="favicon.ico" />
  7. You may need to flush your browser’s cache in order to get it to show up properly.

And you’re done! Now was worth sixty seconds of your time, wasn’t it?

Back From Bristol

March 11 was my last day working at ESPN. After nearly three and a half years working for “The Worldwide Leader,” I’ve accepted a very exciting Senior Web Developer position at “US News and World Report” for their Travel and Auto vertical, located in the Georgetown sector of Washington D.C.

There have been so many memories from ESPN through those few years: From Magical Unicorns to Deadspin announcing layoffs during the summer of 2013. From crazy “Reply-All” e-mail threads to the annual NCAA tournament pot-luck. From the Ooyala Video Migration to Jim Abbot pitching batting practice.

Trying to “steal” Rita LeBlanc’s Super Bowl Ring…

Rita LeBlanc’s Super Bowl Ring.

Conquering the Mt. Snow with the Tough Mudder Crew…

ESPN’s EXT Team: Tough Mudder, 2011.

Shark attacks…

We’re gonna need a bigger boat.

The Stanley Cup…

The Stanley Cup comes to visit ESPN.

Imperial entanglements…

You do not know the power of the Dark Side… we have cookies.

Blizzard of February, 2013.

Through hard times like numerous blizzards, two earthquakes, two hurricanes, the “Franken-Storm”, Newtown and the Boston Marathon Bombing…

Through three reorganizations…

Through working with all the various groups at ESPN: Sports Production, API group, X-Games, International, Editorial and WatchESPN…

It was a blast working with such talented and fun people.

My brother Matty and I on the ESPN News set.

My only regret is that I never got into a “This is Sportsceneter” spot like Lucas and Wong. Though is that really Wong in the green shirt? Now I’m not so sure…

Oh well, there are days when this might as well be me.

So as honestly as I can, to all those that I had the pleasure of working with or knowing, I’d like to say: thanks.

Please keep in touch!