toolness / hive-django

A Django-based Hive website for member organizations, their employees, and other community members.
https://directory.hivelearningnetworks.org
1 stars 10 forks source link

Support multiple hive cities in one Django installation #27

Closed toolness closed 10 years ago

toolness commented 10 years ago

Problem

Other cities (Chicago, Toronto, Chattanooga, Kansas City, etc) want to have their own Hive Directory.

I originally started this project as a single-city directory, assuming that other Hives could host their own instance, but there's a few wrinkles with this plan:

One of the advantages of the current Hive Directory app, though, is the fact that it has a local context. Many people in Hive NYC, for example, don't usually want or need to connect with people in other cities, and showing them information about Hive networks around the world may be confusing. At the same time, though, there are use cases for cities to get up-and-running with their own directory quickly, and for some users to be able to explore the breadth of Hive networks around the world (particularly when their local context doesn't meet their needs).

Solution

Use Django's sites framework to make it possible for a site to represent either a specific city in its installation or the entire Hive ecosystem at large. Because all sites share the same database, changes made on one are automatically reflected in the others.

To illustrate, here's an example of two sites, each powered by the same Django installation:

Clicking on the "New York City" link in the second screen-shot will take the user to a page at /nyc/ that looks similar (but not identical) to the first screen-shot.

Implementation

The solution requires adding a City model to the project and optionally associating it with a Site object (for cities like NYC that have their own individual sites). Multi-city, global-context sites are indicated by simply not associating the site with a city object. This can be done on-the-fly through the Django admin interface, without needing to restart the server.

When a site is multi-city, the URL structure changes such that the home page (/) is just a list of Hive cities, each of which is linked to a path like /nyc/ or /chicago/, which contains a specific directory scoped to each city. By "directory" we mean organization list view and search functionality; organization detail pages are still hosted at /orgs/, users are still at /users/, and so forth. Views can subtly alter their display to cater to either the global or local context through various methods on the City object, and site.city can also be used to obtain information about the current city if the context is local. A new city_url template tag can also be used to reverse-map directory-related URLs regardless of the context (e.g., the tag will automatically prepend /nyc/ to the beginning of the URL if necessary).

Consequences

There will be a lot more data in the database, so new city-related filters and columns have been added to many admin views to make it possible to easily navigate the database for records pertaining to a specific city.

Other models have been tailored to relate to cities in specific ways:

Instead of making these changes, we could build APIs that allow completely separate Hive directory instances to communicate with each other when needed. Services like bitnami and tools like Docker could also be leveraged to reduce the cost of getting an instance up and running.

toolness commented 10 years ago

After talking to @ryanpitts, it seems like a better solution to settings.MULTI_CITY may be to create a SiteProfile class that has a one-to-one relationship with Site (analogous to the best practice for creating user profile models, which our app essentially does with the Membership model). This way we can use site.profile.is_multi_city to determine whether a site is multi-city. (The alternative would be to simply check if site.city is falsy, but this isn't very readable/intuitive.)

toolness commented 10 years ago

Arg, so now I'm running into a problem whereby Django creates the very first site during syncdb before the SiteProfile table is created, so my trigger that auto-creates a site profile for every site crashes there. Ugh. Might just need to do one of the following:

toolness commented 10 years ago

Okay, I decided to get rid of settings.MULTI_CITY, and added a convenience method called is_multi_city, which returns whether the current site is multi-city or not. I also obviated the need to specifically test for multi-city logic in templates by adding City.should_be_mentioned, which looks at the site and tells the caller (usually a template) whether or not a city should be mentioned by name.

Updated the original PR description to reflect the current reality.