Dynamic Url's in Django - python

So I have a list of items and I want to have all of the items direct the user to a standard info page about that item when clicked. I don't full understand the dynamic url system in django. My html file for the content is called detail.html. The goal is to click a movie item, and be directed to a page title "blahblah.com/specific_movie_title"
In views.py I have:
def detail(reuqest, movie_title):
moviePage = Movie.objects.get(pk=movie_title)
return render_to_response('detail.html', {'detail':moviePage, RequestContext(request))
In the urls.py the line I have to correspond with this is:
url(r'^$', views.detail, name='detail')
Could I get help with correcting these two chunks of code?

In django, urls are matched by a regular expression pattern.
The general format of the url line is:
url(the_pattern, the_view_name_or_callable, **any_extra_arguments)
The key point is the_pattern, which is a regular expression and whatever is matched can be passed as an argument to the view function.
It is important that any parts of the pattern that are captured and passed on to the view function, actually match the function's signature (the def line, where you define the name and arguments). Otherwise, django will throw an error.
So now, with that out of the way - lets deal with the actual issue.
Your want a url like /the_great_gatsby to redirect to the page for The Great Gatsby.
The first step is to identify a pattern that matches the_great_gatsby. You can use [_\w]+ which means "one or more word characters or _", and plug it into the URL:
url(r'/[_\w]+$', views.detail, name='detail')
Next, you have to tell django how to capture that pattern and pass it to the view method as an argument.
Your view method is: def detail(request, movie_title). So django must pass whatever is after the / in the url (and matches the pattern) to the argument name movie_title, so what we want is this:
def detail(request, movie_title)
^^^^^^^^^^^
---------------|
|
vvvvvvv
url(r'/[_\w]+$', views.detail, name='detail')
We modify the regular expression to make sure that django captures whatever matches, and then assigns it a name. To do that, wrap the part of the regular expression in (?P<name_of_variable>expression) like this:
url(r'/(?P<movie_title>[_\w+])$', views.detail, name='detail')
Now, whatever is captured after / will be passed as the argument movie_title to the views.detail method.
Of course, you have to make sure your view function is doing the right thing with the captured string. In your case, your view method is searching by the primary key and will fail to produce any results (and will raise an exception) since there is no movie that will have the title as the primary key; but that's another problem.

you can configure your url and view like this
urls.py
url(r'^movie/(?P<movie_title>\w+)$', views.movie_detail, name='detail')
views.py
def movie_detail(request, movie_title):
movie_object = Movie.objects.get(pk=movie_title)
return render(request, 'moview-detail.html', {'movie_object':movie_object}
and in your html {% url 'app_name:detail' movie_title %}

Related

Is there a way to add context to Django reverse function?

Is it possible to pass context through the reverse function in Django in some way like reverse('foo', context={'bar':'baz'})? Or is there a better workaround?
As already described by Sir WillemVanOnsem in the above comment.
You can't provide context in reverse as it only produces a string: a path, eventually it goes to view.
reverse() can only take args and kwargs, see Reversing namespaced URLs for more detail.
Reverse generates an URL. The URL can parse or supply extra context. In urls.py,
path( 'action/<str:context>/', MyView.as_view(), name='foo' )
then
reverse('app:foo', kwargs={'context':'bar:baz+quux:help'} )
will generate the URL ending
.../appname/action/bar:baz+quux:help
and your view will parse context:
context = self.kwargs.get( context, '')
context_dir = {}
for kv in context.split('+'):
keyval = kv.split(':')
context_dir[ keyval[0].strip() ] = keyval[1].strip()
or something like this, ending with context_dir as {'bar':'baz', 'quux':'help'}
Alternatively you can append a querystring to the URL returned by reverse and retrieve that in the view you redirect to via request.GET
url = reverse('foo') + '?bar=baz&quux=help'
redirect, and then in that view request.GET.get('bar') will return "baz" etc.
Finally you can stuff an almost arbitrarily complex context into the user's session (which gets stored either as a cookie in his browser, or an object in your database). This is the most general but also the most complex. See the doc for using Django sessions

Django: Make query using url ( Assigning variable using url )

I am trying to make a query system for my website, i think the best way and the most compact would be to assign search variable using url pattern.
So for example, i want to search objects of model User:
User sends HttpRequest to following url:
https://127.0.0.1/search/q="admin"
Now HttpRequest is also sent to search view, we somehow get q variable data.
def search(request):
for query in User.objects.all():
if q in query: # < We somehow need to get data of 'q'.
return HttpResponse(q)
Since i have admin in User.objects.all(), this should return HttpResponse of 'admin'.
How can this url pattern be made? So i can assign q variable from the url and then send it to system to find it?
I have problems with this URL:
https://127.0.0.1/search/q="admin"
There is no ? in the URL, so there is no query string, it's all part of the "path". Using characters like = and " in there will confuse a lot of things, if it works at all.
Either just do
https://127.0.0.1/search/admin
With an URL pattern like r'^search/(?P<querystring>.+)$', or
https://127.0.0.1/search/?q=admin
In this case the query string will be in request.GET['q']; it's also possible to use Django forms to process query parameters (e.g. for validating them).
You can capture named strings from URLs like this:
urls.py:
urlpatterns = [
url(r'^blog/page(?P<num>[0-9]+)/$', views.page),
]
views.py:
def page(request, num="1"):

Dynamically check if a slug exists

On a legacy app, I need to check if a URL exists, and if it does not, to redirect it to another location. The problem is that I need to check if that url is present in a set of values, in the urls file and I'm not clear on how best to do that.
For example, both projects and cities are sharing the same url pattern. e.g. /projects/london and /projects/my-project-name.
I want to first check if the slug matches a city, and if it does not to then return the project view (cities cannot match project names).
My urls are currently structured as follows:
url(r'^projects/(?P<project-name>[-\w]+)', get_project, name='project-view'),
url(r'^projects/.*', get_city, name='city-view'),
I know this is very messy, and a bad overall pattern but unfortunately it's not something that can be changed at the moment. So my goal is to figure out if I can first check if the project-name could be a city, and if it is, to redirect onto that view without falling into a redirect loop.
I wondered if I could do something like this:
url(r'^projects/(?P<city>london|paris|new-york)/', get_city, name='city-view'),
where london|paris|new-york are generated dynamically
You can dynamically generate a url with all of the city names, but the url will be cached once django accesses it the first time, so in order to modify the url regex, you'd have to restart the django process. If that's fine for your purposes, you can generate the url like this:
url(r'^projects/(?P<city>{})/$'.format(city_slugs.join('|')),
get_city, name='city-view')
But, it would probably be better to create a view routing method that implements the logic to send requests to their appropriate view:
# urls.py
# ...
url(r'^projects/(?P<slug>[-\w]+)/$',
project_city_router, name='project-city-router'),
# ...
# views.py
def is_a_city(slug):
# If they're in the database, something like:
# return City.objects.filter(slug=slug).exists()
return slug in ['london', 'paris', 'new-york', '...']
def project_city_router(request, slug=None):
if not slug:
# /projects/
return render(request, 'my/template.html', {'foo': 'bar'})
elif is_a_city(slug):
# /projects/<city>/
return get_city(request, city=slug)
else:
# /projects/<project-name/
return get_project(request, project_name=slug)
With this router, if the slug argument is a project or city, it returns the result of the get_project or get_city view itself.
This also allows for your list of cities to be checked dynamically against a database, or file.

regular expression in django for urls

What I am trying to do is as follows
I have urls like this /blog/1/sdc/?c=119 or /forum/83/ksnd/?c=100 What I want to do is to redirect these to a view, so that I can change the url to /blog/1/sdc/#c119
One way would be to do this is to make provision in views of each of the app, where such a url maybe generated, but that is not scalable. What I want to do is to catch any url that has ?c=<some_digit> at the end and redirect to my custom view.
Can anybody help, I am not good with regex.
You can't do this in your urlconf, it doesn't match anything in the query string. What you'll need to do is write a middleware along the lines of this:
class RedirectMiddleware:
def process_request(self, request):
if 'c' in request.GET:
# return a HttpResponseRedirect here
See https://docs.djangoproject.com/en/dev/topics/http/middleware/ for more details.

confusion in url and template in django

My url is :
1. http://localhost:8000/docs/[slug]
2. http://localhost:8000/docs/[slug]/login
1. url calls before number 2. url I want to send
the slug value to the function mapped by the url 2. In template
what should i wrote for form action event.
I agree, this is nearly incomprehensible, but I'm going to give it a go in terms of an answer.
In terms of calling sequence, there is none. A user might first visit url 2 or url 1. You have no way of guaranteeing which they will try to access first because they might directly input the url into their browser. The only thing you can do is set a variable in request.session's dict and test for it with your login url.
In terms of passing slug to another url, if you're having a url with this in it:
urls = ('',
url(r'docs/(?P<slug>\w+)', 'app.views.slug', name='slug-view'),
url(r'docs/(?P<slug>\w+)/login', 'app.views.slug_login', name='slug-login'),
#..
)
Then in your template you can do this:
<form action="{% url slug-login slugname %}" method="POST">
Your views.py would look something like this.
def slug(request, slug):
#
#
return render_to_response('templatename.html', {'slugname':slug}, context_instance=RequestContext(request))
def slug_login(request, slug):
# do something with slug.
This way, when you access the slug view, you pass into the template a variable called slugname, which the template uses with django's url library to resolve a specifically named url in urls.py with one named parameter, slug, which it will assign the value of slugname.
I suggest you try it.
I might also reccoment you read up on the django url dispatcher. Your use of regex without named parameters is acceptable but really not best practice. I'd also suggest django shortcuts (render_to_response) as a quick way to pass variables into templates and the django template language itself.

Categories

Resources