views:

241

answers:

3

I am trying to de-couple two apps:

  1. Locations - app containing details about some location (town, country, place etc)
  2. Directory - app containing details of places of interest (shop, railway station, pub, etc) - all categorised.

Both locations.Location and directory.Item contain lat/lng coords and I can find items within a certain distance of a specific lat/lng coord.

I'd like to use the following URL structure:

/locations/<location_slug>/directory/<category_slug>/

But I don't want to make my directory app reliant on my location app.

How can I translate this url to use a view like this in my directory app?

items_near(lat, lng, distance, category):

A work around would be to create a new view somewhere that translates this - but where should I put that? if it goes in the Directory app, then I've coupled that with my Location app, and vice versa.

Would a good idea be to place this workaround code inside my project URLs file? Thus keeping clear of both apps? Any issues with doing it like this?

A: 

From the django docs here if you're using django >=1.1 then you can pass any captured info into the included application. So splitting across a few files:

# in locations.urls.py

urlpatterns = ('',
  (r'location/(?P<location_slug>.*?)/', include('directory.urls')),
  #other stuff
  )


# in directory.urls.py

urlpatterns = ('',
  (r'directory/(?P<directory_slug>.*?)/', 'directory.views.someview'),
  #other stuff
  )

# in directory.views.py

def someview(request, location_slug = None, directory_slug = None):
 #do stuff

Hope that helps. If you're in django < 1.1 I have no idea.

JudoWill
+2  A: 

For your urlpattern to work, the view function invoked has to be aware of both Locations and Directories. The short answer is you can put this view function anywhere you want - it's just a python function. But there might be a few logical places for it, outside of your Directory or Location app, that make sense.

First off, I would not put that view code in in your top-level urls.py, as that file is intended for URLconf related code.

A few options of where to put your view:

  1. Create a new view function in a file that lives outside of any particular app. <project_root>/views.py is one possibility. There is nothing wrong with this view calling the item_near(..) view from the Directory app.

    # in myproject/urls.py
    
    
    urlpatterns = (
       ...
       (r'/locations/(?P<location_slug>[\w\-]+)/directory/(?P<category_slug>[\w\-]+)/', 
        'myproject.views.items_near_from_slug')
    )
    
    
    # in myproject/views.py
    
    
    from directory.views import items_near
    
    
    def items_near_from_slug(request, location_slug, category_slug):
      location = get_object_or_404(Location, slug=location_slug)
    
    
      distance = 2 # not sure where this comes from
    
    
      # And then just invoke the view from your Directory app
      return items_near(request, location.lat, location.lng, distance, category_slug)
    
  2. Create a new app and put the code there, in <my_new_app>/views.py. There is no requirement that a Django app need to have a models.py, urls.py, etc. Just make sure to include the __init__.py if you want Django to load the app properly (if, for instance, you want Django to automatically find templatetags or app specific templates).

Personally, I would go with option 1 only if the project is relatively simple, and <project_root>/views.py is not in danger of becoming cluttered with views for everything. I would go with option 2 otherwise, especially if you anticipate having other code that needs to be aware of both Locations and Directories. With option 2, you can collect the relevant urlpatterns in their own app-specific urls.py as well.

zlovelady
@zlovelady I didn't know that there might be a url `reverse()` problem ... I've never had occasion to use this feature so I've never seen that pitfall
JudoWill
@JudoWill I edited out the "reverse" pitfall after your comment mentioned it, and investigating further and realizing I was wrong. I was thinking of a different issue with URLconf and reverse(..) having to do with using reverse(..) in a Media definition of a widget. Thanks for mentioning it :)
zlovelady
cheers - this seems to be the most logical way of converting the location slug into it's lng and lat. The place for this should be in my overall project 'app' - the bit that brings it together...
Guy Bowden
A: 

Irrespective of how much ever "re-usable" you make your app, inevitably there is a need for site-specific code.

I think it is logical to create a "site-specific" application that uses the views of the reusable and decoupled apps.

Lakshman Prasad