On Thu, Feb 25, 2016 at 12:45 PM, Malik Rumi <malik.a.rumi@gmail.com> wrote:
Assuming it can be done, what is the proper way to namespace two models in the same app, where both use slugs in the url but have different views and templates?In the docs, https://docs.djangoproject.com/en/1.9/topics/http/urls/#url-namespaces, it talks about how to do this, but it always refers to 'applications' rather than 'models'.
That's because models are only a portion of the functionality of the framework, and usually each app has multiple models associated with it. URL's can and often do point to views that don't reference models at all. Part of the philosophy of Django is loose-coupling of URL's and models (and every other function of Django, as much as possible).
Normally the URL layout would match the intended application:
fruit/apple/
fruit/bananna/
Where you want to use something like:
apple/
bananna/
This isn't a technical restriction that you are dealing with, it is a design issue. What if you wanted to list all of the fruit available?
#App based
fruit/ #list all fruit
#Model based
fruit/
However, now you've hit an inconsistency with your URL's and models, since you probably don't have a concrete model named Fruit.
You can design your URL's however you like, just some food for thought.
So can I do:urls.pyurl(r'^model1/', include('app.urls', appview4model1, namespace='app.model1')url(r'^model2/', include('app.urls', appview4model2, namespace='app.model2')
Sure, although I'm not sure if those namespace strings are valid. I use dashes, and in this case i would just use 'model1' and 'model2'.
app_name = "app.model1"urlpatterns [ ....]app_name = "app.model2"urlpatterns [ ....]Frankly, I want the shortest urls possible, so if there was a way to do this without putting 'model1' or 'model2' in the url, that would be great, but I'm not seeing a way around it - assuming the app_name = 'app.model1' thing even works.
If that's the case, use something like a letter and the PK of the object: url(r'a/(?P<pk>\d+)/')
Short URL's are a great thing to have, but don't twist yourself into a pretzel to attain them. Ultimately there are only marginal benefits. It's means you need to simplify your URL structure, and you can already see what kind of complication that simplification brings...
Another option I thought of but don't know if possible:try url(r'^(?P<slug>) )except url(r'^modelname(?P<slug>) )I've never seen anything like that, though. If it did work, I doubt it would fit inside urlpatterns[ ], but maybe I could put it after?Or I could hack the code that handles url name collisions (once I find it)
There's no practical limit to what a url() tag can contain. URL's can be thousands of characters long. If your models have a slug attached to them, you can just use the slug at the top level of the URL structure. It will likely incur a lookup for each type of model though, and you would need some extra checking when creating/updating models to ensure that the slugs are unique between the two. There are various tricks on how to do that (usually in the save() method of your models) or a related table that keeps a list of slugs used for both models with uniqueness enforced (maybe even a GenericForeignKey). Your URL/view can also accept a slug and perform a lookup against ModelA, and if it doesn't find anything, look again via ModelB. This is slightly more challenging with a CBV, but is entirely possible.
Using the bare slug at the top level also hampers your ability to generate URL's elsewhere due to the overlap with other keywords (although still possible if you are careful). Technically, keywords like 'contact' are considered valid slugs, and may incur a lookup against ModelA/B when in fact you wanted the user to see the contact page.
This method is exactly how URL shorteners work. The system provides the slug/hash correlated to the real URL in the database, and the shortener system redirects based on the matching real URL found for the hash.
Unless there is a business requirement for it, I would recommend for your own sanity each model would live in its own namespace so that wouldn't have to worry about overlapping slugs, etc.
You should also have a look at app namepaces vs. instance namespaces: https://docs.djangoproject.com/en/1.9/topics/http/urls/#url-namespaces-and-included-urlconfs
-James
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/CA%2Be%2BciVo739FURrsFMWyTc9o_Vd%2BYb%2BFZEjJZiVMJP4qWGawWQ%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.
No comments:
Post a Comment