Django routes - check route from DB - django

Morning,
With my django website, I want to make the urls as short as possible.
So instead of,
/user/john
/user/ronald
I just want it like /john and /ronald
So in my routes I have it configured that all the requests go to one
urlpatterns = patterns('',
....
(r'^about/$', 'frontend.views.about'),
(r'^(.*?)/$', 'users.views.index')
)
which means basically that all requests will be handled by the users controller if not handled else where, which isn't to bad.
But I want to do the same cakes.
so instead of /cakes/chocolate-coated-cake just have /chocolate-coated-cake
So really, it'd be nice if in my users method, instead of raising a 404 I could just some how call try next route, so it's conditional on a DB field.
Make sense?

In this case I'll prefer to have a separate dispatcher view (not related to users because it is not about users). There you could set up order of models in a list and iterate through it until the first sucess and call the appropriate view (user view, cake view) with this result as an argument).
P.S. Hope that you will not have a user and a cake with the same name :)

Related

Process Views outside viewflow.frontend

I want to integrate processes, starting them etc., outside of the standard viewflow.frontend. To do I have been trying to create a simple page where I can start a new process, but have been struggling to find a way to implement it.
One approach was to defined a url to url('^start_something, CustomStartView.as_view()) with CustomStartView subclassing CreateProcessView from viewflow.flow.views.start. This ended in getting error after error, whenever I fixed one. I am quite sure now that this isn't the right way to do it, also because the View is used as a parameter of the Flow class itself and probably needs to be used differently than a common view.
What is the right way to do it?
The Viewflow views need to be parametrized by flow_class and flow_task instance. So you can include a start view as following::
url('^start/', CreateProcessView.as_view(), {
'flow_class': MyFlow,
'flow_task': MyFlow.start})
To add a task view URL config, you need to use process_pk and task_pk parameters
url('^(?P<process_pk>\d+)/approve/(?P<task_pk>\d+)/', ApproveView.as_view(), {
'flow_class': MyFlow,
'flow_task': MyFlow.approve
})
For each node, you also can enable detail, and various actions URLs, ex:
url('^(?P<process_pk>\d+)/approve/(?P<task_pk>\d+)/detail/', DetailTaskView.as_view(), {
'flow_class': MyFlow,
'flow_task': MyFlow.approve
}),
url('^(?P<process_pk>\d+)/approve/(?P<task_pk>\d+)/cancel/', CancelTaskView.as_view(), {
'flow_class': MyFlow,
'flow_task': MyFlow.approve
}),
All of that's a big cumbersome.
Recommended way
You can just include Flow.instance.urls that contains all URLs collected and ready for inclusion into an URL config.
url('^myflow', include(MyFlow.instance.urls, namespace='myflow'))
And at the last, to enable task list views, you can put URL entries manually, ex
url('^myflow/inbox/', TaskListView.as_view(), {
'flow_class': MyFlow}, name="tasks")
or just use as viewflow.flow.viewset.FlowViewSet class
myflow_urls = FlowViewSet(MyFlow).urls
urlpatterns = [
url(r'^myflow/', include(myflow_urls, namespace='myflow'))
]
This is the recommended way to include viewflow URLs into a django URL Config. To customize views used in that URL config, you can subclass the FlowViewSet class and provide views in the nodes definition, ex
class MyFlow(Flow):
start = flow.Start(detail_view_class=MyDetailTaskView)
For the sample usage, you can checkout the Viewflow Custom UI cookbook example - https://github.com/viewflow/cookbook/tree/master/custom_ui

Ignore params in urls

I need to bolt a quick city-specific thing onto a site I am currently building. I am going to do it something like this - http://example.com/XX/normal-slug. What I have set up in my urls.py is this:
url(r'^(?P<city>[a-zA-Z]{2})/', include('homepage.urls', namespace='homepage')),
url(r'^(?P<city>[a-zA-Z]{2})/section/', include('section.urls', namespace='section')),
# etc
The problem I am encountering now is that all of a sudden my methods all are now expecting a "city=XX" param. I plan to process the actual city business logic in a middleware. My question is... is there anyway have django "ignore" the named param? I don't want to modify all my views now to take either **kwards or 'city' param. If I hard code the city code, it does what I expect:
url(r'^XX/section/', include('section.urls', namespace='section')),
So can I replicate that behaviour, but dynamically?
(Also, I plan on something more robust further down the line, probably Django Sites)
You can use a non-capturing regex to accept the parameter but not pass it to the views.
r'^[a-zA-Z]{2}/section'
Set the param as optional in the regexp with ?:
url(r'^((?P<city>[a-zA-Z]{2})/)?section/', include('section.urls', namespace='section')),
If city is not sent in the URL, your view will receive city=None

Django Forbid HttpResponse

I am working on a tiny movie manager by using the out-of-the-box admin module in Django.
I add a "Play" link on the movie admin page to play the movie, by passing the id of this movie. So the backend is something like this:
import subprocess
def play(request, movie_id):
try:
m = Movie.objects.get(pk=movie_id)
subprocess.Popen([PLAYER_PATH, m.path + '/' + m.name])
return HttpResponseRedirect("/admin/core/movie")
except Movie.DoesNotExist:
return HttpResponse(u"The movie is not exist!")
As the code above reveals, every time I click the "play" link, the page will be refreshed to /admin/core/movie, which is the movie admin page, I just do not want the backend to do this kind of things, because I may use the "Search" functions provided by the admin module, so the URL before clicking on "Play" may be something like: "/admin/core/movie/?q=gun", if that response takes effect, then the query criteria will be removed.
So, my thought is whether I can forbid the HttpResponse, in order to let me stay on the current page.
Any suggestions on this issue ?
Thanks in advance.
I used the custom action in admin to implement this function.
So finally I felt that actions are something like procedures, which have no return values, and requests are something like methods(views) with return values...
Thanks !

Turn down webpage depending on time of day (DJANGO)

How can i use django templates to remove the contents of a page depending on the time of day?
I'm creating an online food delivery site. The delivery orders are sectioned off into times.
For example for a 7pm delivery drop, i would want the page to show normally until 6pm that day. Then at 6:01pm i would want the page to say something like "This delivery time is not available"
To be honest you shouldn't rely on template logic if you want to prevent unwanted behaviour.
You can create two variables, e.g.
from django.conf import settings
TIME_OPEN = getattr(settings, 'TIME_OPEN', datetime.now().replace(hour=10, minute=30, second=0, microsecond=0).time())
TIME_CLOSED = getattr(settings, 'TIME_CLOSED', datetime.now().replace(hour=21, minute=30, second=0, microsecond=0).time())
In your url patterns you could add something like:
if TIME_OPEN < datetime.now().time() < TIME_CLOSED:
urlpatterns += patterns('shop.customers.views',
(r'^checkout/$', 'checkout'),
)
Based on your new variables you could add a context_processor that supplies a context variable to each template for UI logic, e.g. {'shop_open': True}.
Mind you these examples rely on server time, so you would have to check, because it can differ from your local machine. Another approach could be to create a decorator which can be wrapped around views that require certain times.
So, just to make sure; Don't rely on template logic, protect your views

Django: Passing data to view from url dispatcher without including the data in the url?

I've got my mind set on dynamically creating URLs in Django, based on names stored in database objects. All of these pages should be handled by the same view, but I would like the database object to be passed to the view as a parameter when it is called. Is that possible?
Here is the code I currently have:
places = models.Place.objects.all()
for place in places:
name = place.name.lower()
urlpatterns += patterns('',
url(r'^'+name +'/$', 'misc.views.home', name='places.'+name)
)
Is it possible to pass extra information to the view, without adding more parameters to the URL? Since the URLs are for the root directory, and I still need 404 pages to show on other values, I can't just use a string parameter. Is the solution to give up on trying to add the URLs to root, or is there another solution?
I suppose I could do a lookup on the name itself, since all URLs have to be unique anyway. Is that the only other option?
I think you can pass a dictionary to the view with additional attributes, like this:
url(r'^'+name +'/$', 'misc.views.home', {'place' : place}, name='places.'+name)
And you can change the view to expect this parameter.
That's generally a bad idea since it will query the database for every request, not only requests relevant to that model. A better idea is to come up with the general url composition and use the same view for all of them. You can then retrieve the relevant place inside the view, which will only hit the database when you reach that specific view.
For example:
urlpatterns += patterns('',
url(r'^places/(?P<name>\w+)/$', 'misc.views.home', name='places.view_place')
)
# views.py
def home(request, name):
place = models.Place.objects.get(name__iexact=name)
# Do more stuff here
I realize this is not what you truly asked for, but should provide you with much less headaches.