Use anchored urls in django (anchored by the id of http objects) - django

My level in front-end development is pretty low.
Nevertheless, I want to implement the very wide-spread behaviour of having several parts anchored in one single page instead of several separate pages, and refer to these parts in the url.
So instead of having mysite.com/how_to_walk and mysite.com/how_to_run as two different pages and templates, I would like to have one page mysite.com/how_to_do_stuff and then depending on if you want to #walk or #run, refer to the html headers with the id field as suffixes of the url.
I don't really know how to do it with django. I'd like to create only one url dispatcher that - I guess - will look like that:
url(r'^how_to_stuff/#(?P<partId>[-\w]*)', views.how_to, name='how_to')
...and then I have to create a simple view, but how to refer to the id in the render() call, I have no idea.

I found the answer to my own question. The crucial element is that when the client (browser) goes for such an anchored url mysite.com/how_to_do_stuff#run, it sends to the server only the root url mysite.com/how_to_do_stuff and then applies the anchor to it locally. So you need:
A classic, simple url/view/template combination that loads the page mysite.com/how_to_do_stuff when it is asked by the client.
A way to send the client to these anchored pages and reference them for development. I do this through an other url/view couple that redirects the client to the right anchored url.
Below is the result:
In urls.py:
...
url(r'^how_to_do_stuff/(?P<part_id>[-\w]+)', views.how_to_redirect, name='how_to'),
url(r'^how_to_do_stuff', views.how_to)
In views.py:
def how_to_redirect(request, part_id):
return HttpResponseRedirect("/how_to_do_stuff/#"+part_id)
def how_to(request):
return render(request, "GWSite/how_to_do_stuff.html")
And then I refer to these in my templates through:
{% url "how_to" "run"}

From django project website
Take a look at how you they send the num var to views.py
# URLconf
from django.conf.urls import url
urlpatterns = [
url(r'^blog/$', 'blog.views.page'),
url(r'^blog/page(?P<num>[0-9]+)/$', 'blog.views.page'),
]
# View (in blog/views.py)
def page(request, num="1"):
# Output the appropriate page of blog entries, according to num.
...

Related

Django: what is the difference between redirect to a view function and redirect to a url (from urls.py file)

Which is better/standard practice?
return redirect('index')
return redirect('/users/new')
index is view function
/users/new is urlpatterns from urls.py
Using URLs directly is discouraged by Django's documentation (my bold):
A common need when working on a Django project is the possibility to obtain URLs in their final forms either for embedding in generated content (views and assets URLs, URLs shown to the user, etc.) or for handling of the navigation flow on the server side (redirections, etc.)
It is strongly desirable to avoid hard-coding these URLs (a laborious, non-scalable and error-prone strategy). Equally dangerous is devising ad-hoc mechanisms to generate URLs that are parallel to the design described by the URLconf, which can result in the production of URLs that become stale over time.
In other contexts you may wish to use reverse() or {% url %}, or to add a get_absolute_url() method to your models.
I think that index in your example is not a view function, but a url-name
url(r'^some/url/to/index', views.index_2, name='index')
view functions can have index_2 name and any url path, but you use "index" to redirect, for example return redirect(reverse('index')).
As you can see, redirect only accept an url path, then reverse function receive a url name and return an url path, in the example reverse will return "some/url/to/index"

Django url patterns - how to make slug url work for multiple views

I see a url patterns in some websites which shows the same pattern for different objects like categories and products.
For example, when you go to tablet cases and sony camera you see the same pattern like www.website/tablet-cases and www.website/sony-camera.
How is it possible to do that in Django without getting an error as below.
Page not found (404)
Request Method: GET
Request URL: http://127.0.0.1:8000/tablet-cases/
Raised by: Product.views.category_detail_view
I mean, how can I use the same pattern for both categories and products as below:
url(r'^(?P<slug>[\w-]+)/$', ProductDetailView.as_view(), name='product_detail'),
url(r'^(?P<slug>[\w-]+)/$', CategoryDetailView.as_view(), name='category_detail'),
Django matches the first regex, in this case the product_detail view. By default, Django doesn't have a way to try each url in turn, so the category view will never be called with your current urls.
The easiest fix is to namespace your urls. This might be a good idea - at the moment, you'll have problems if you ever have a category and a product with the same slug.
url(r'^products/(?P<slug>[\w-]+)/$', ProductDetailView.as_view(), name='product_detail'),
url(r'^categories/(?P<slug>[\w-]+)/$', CategoryDetailView.as_view(), name='category_detail'),
Another option is to create a single view, say product_or_category. In that, you could test to see whether the slug matches a category or slug, and continue. This will work, but you might have a bit of duplicated code, and it might not seem as as elegant as the two class based views you currently have.
url(r'^(?P<slug>[\w-]+)/$', product_or_category, name='product_or_category'),
Finally, there's a project django-multiurl that appears to do what you want. I have never used it, so I can't make any claims for it.

django url parse formatted url

I'm in the design stages of a single page web app, and would like to make it so that a user can click on a formatted URL and the data requests will load in the page.
For example, a url of http://www.mysite.com/?category=some_cat will trigger the Category view with the relevant data.
My intention is to parse the URL, gather the data, then pass it to the index.html template for rendering on page load. Once the page has been loaded, a Javascript trigger setting will trigger the appropriate button to load the client view.
However, I'm having an issue setting up the URL parser, as the following settings are not matching the example url above.
from app.views import app_views, photo_views, user_views, admin_views
urlpatterns = patterns("",
url(r'^/(?P<category>\d+)/$', app_views.index)
)
You're confusing between sending information through your urls with GET and formatting you urls with arguments for the view functions. Say I am visiting a site called http://www.mysite.com/ and the page has a form that looks like this:
<form>
<input type='text' name='category' id='category'></input>
<button type='submit'>Send!</button>
</form>
upon clicking, the url will automatically change to http://www.mysite.com/?category=<value of input>. The ? marks that everything afterwards should be treated as GET data, with the syntax of <id>=<value>. You can then access them like so:
def response(request):
category = request.GET['category']
formatting urls is different, because it means looking for patterns that are part of the url. i.e. a pattern that looks like r'^/(?P<category>\d+)/$' will look for this: http://www.mysite.com/<category>/ and it will send it to the request in your views as an additional argument like so:
def response(request, category):
...
The regex is used to define how you recognize that part of the url. For example, the \d+ you're using means that category needs to be a number. You can search how to define different types of patterns according to your needs
Note that with GET you are sending the data to the same view function that rendered the page you are currently visiting, while using a different url means you tell it where to go through your urls.py (usually a different function). Does that make things a bit clearer?

Django-CMS AppHooks with conflicting urls?

I'm trying to use django-cms app hooks in a different way. I have only an app, with different website pages. For each page, i created an AppHook, since i want to have control of all of them with the cms.
To do that, inside the app, i did a package, with urls.py file for each of the page, example:
/urls
/home_urls.py
/portfolio_urls.py
/contacts_urls.py
Here are the definition of some app hooks:
class WebsiteHome(CMSApp):
name = _("cms-home")
urls = ["website.urls.home_urls"]
apphook_pool.register(WebsiteHome)
class WebsiteServices(CMSApp):
name = _("cms-services")
urls = ["website.urls.services_urls"]
apphook_pool.register(WebsiteServices)
Anyway, the problem is: i don't have any control on the regular expressions. Each one, is entering on the first regular expression that it founds, in this case, the urlpattern in the
website.urls.home_urls
Despite, having different apphHooks.
Example:
if i write a slug contacts (that has an apphook to WebsiteContacts), it still goes to the home_urls.py file, associated with the WebsiteHome (app hook).
Did anyone had a similiar problem?
Basically, what I'm trying to say is that it's something wrong with the regular expression. I can't make:
url(r'^$', [...]),
only:
url(r'^', [...]),
If I put the '$', it doesn't enter on any regex. If I take it, it enters always on the
website.urls.home_urls.py
Despite the slugs having different Apphooks, associated with different urls.py files.
Have you tried r'^/$'? I'm using r'^/?$' in some app-hook urls, but I wonder if r'^$' is failing for you because of a '/'?
As you've defined each of those URL files as individual app hooks in CMS then they'll each get attached to a certain page in the CMS e.g.
www.mysite.com/home
www.mysite.com/contacts
www.mysite.com/services
etc
Because those URL files are attached to pages this should prevent conflict between urlpatterns. For example, I've got an URLs file attached to a CMS app called News which looks like this;
urlpatterns = patterns(
'',
url(r'^(?P<slug>[-_\w]+)/$', NewsDetailView.as_view(), name='news_detail'),
url(r'^$', NewsListView.as_view(), name='news_list'),
)
Which is attached to a page at mysite.com/news so if I go to mysite.com/news/myslug I hit that NewsDetailView and if I go to mysite.com/news I hit NewListView.
Using this example, if you had a slug for a contact you'd go to mysite.com/contacts/contact-slug to hit that NewsDetailView.
And just a sidenote on the urlpatterns in case you're not aware, the ^ in the regex signifies the start of a pattern to match, and the $ signifies the end. URL dispatcher docs

What is reverse()?

When I read Django code sometimes, I see in some templates reverse(). I am not quite sure what this is but it is used together with HttpResponseRedirect. How and when is this reverse() supposed to be used?
reverse() | Django documentation
Let's suppose that in your urls.py you have defined this:
url(r'^foo$', some_view, name='url_name'),
In a template you can then refer to this url as:
<!-- django <= 1.4 -->
link which calls some_view
<!-- django >= 1.5 or with {% load url from future %} in your template -->
link which calls some_view
This will be rendered as:
link which calls some_view
Now say you want to do something similar in your views.py - e.g. you are handling some other URL (not /foo/) in some other view (not some_view) and you want to redirect the user to /foo/ (often the case on successful form submission).
You could just do:
return HttpResponseRedirect('/foo/')
But what if you want to change the URL in the future? You'd have to update your urls.py and all references to it in your code. This violates the DRY (Don't Repeat Yourself) principle and the whole idea of editing in one place only - which is something to strive for.
Instead, you can say:
from django.http import HttpResponseRedirect
from django.urls import reverse
return HttpResponseRedirect(reverse('url_name'))
This looks through all URLs defined in your project for the URL defined with the name url_name and returns the actual URL /foo/.
This means that you refer to the URL only by its name attribute - if you want to change the URL itself or the view it refers to you can do this by editing one place only - urls.py.
The existing answers are quite clear. Just in case you do not know why it is called reverse: It takes an input of a url name and gives the actual url, which is reverse to having a url first and then give it a name.
Existing answers did a great job at explaining the what of this reverse() function in Django.
However, I'd hoped that my answer shed a different light at the why: why use reverse() in place of other more straightforward, arguably more pythonic approaches in template-view binding, and what are some legitimate reasons for the popularity of this "redirect via reverse() pattern" in Django routing logic.
One key benefit is the reverse construction of a url, as others have mentioned. Just like how you would use {% url "profile" profile.id %} to generate the url from your app's url configuration file: e.g. path('<int:profile.id>/profile', views.profile, name="profile").
But as the OP have noted, the use of reverse() is also commonly combined with the use of HttpResponseRedirect. But why?
I am not quite sure what this is but it is used together with HttpResponseRedirect. How and when is this reverse() supposed to be used?
Consider the following views.py:
from django.http import HttpResponseRedirect
from django.urls import reverse
def vote(request, question_id):
question = get_object_or_404(Question, pk=question_id)
try:
selected = question.choice_set.get(pk=request.POST['choice'])
except KeyError:
# handle exception
pass
else:
selected.votes += 1
selected.save()
return HttpResponseRedirect(reverse('polls:polls-results',
args=(question.id)
))
And our minimal urls.py:
from django.urls import path
from . import views
app_name = 'polls'
urlpatterns = [
path('<int:question_id>/results/', views.results, name='polls-results'),
path('<int:question_id>/vote/', views.vote, name='polls-vote')
]
In the vote() function, the code in our else block uses reverse along with HttpResponseRedirect in the following pattern:
HttpResponseRedirect(reverse('polls:polls-results',
args=(question.id)
This first and foremost, means we don't have to hardcode the URL (consistent with the DRY principle) but more crucially, reverse() provides an elegant way to construct URL strings by handling values unpacked from the arguments (args=(question.id) is handled by URLConfig). Supposed question has an attribute id which contains the value 5, the URL constructed from the reverse() would then be:
'/polls/5/results/'
In normal template-view binding code, we use HttpResponse() or render() as they typically involve less abstraction: one view function returning one template:
def index(request):
return render(request, 'polls/index.html')
But in many legitimate cases of redirection, we typically care about constructing the URL from a list of parameters. These include cases such as:
HTML form submission through POST request
User login post-validation
Reset password through JSON web tokens
Most of these involve some form of redirection, and a URL constructed through a set of parameters. Hope this adds to the already helpful thread of answers!
This is an old question, but here is something that might help someone.
From the official docs:
Django provides tools for performing URL reversing that match the
different layers where URLs are needed: In templates: Using the url
template tag. In Python code: Using the reverse() function. In higher
level code related to handling of URLs of Django model instances: The
get_absolute_url() method.
Eg. in templates (url tag)
2012 Archive
Eg. in python code (using the reverse function)
return HttpResponseRedirect(reverse('news-year-archive', args=(year,)))
The function supports the dry principle - ensuring that you don't hard code urls throughout your app. A url should be defined in one place, and only one place - your url conf. After that you're really just referencing that info.
Use reverse() to give you the url of a page, given either the path to the view, or the page_name parameter from your url conf. You would use it in cases where it doesn't make sense to do it in the template with {% url 'my-page' %}.
There are lots of possible places you might use this functionality. One place I've found I use it is when redirecting users in a view (often after the successful processing of a form)-
return HttpResponseRedirect(reverse('thanks-we-got-your-form-page'))
You might also use it when writing template tags.
Another time I used reverse() was with model inheritance. I had a ListView on a parent model, but wanted to get from any one of those parent objects to the DetailView of it's associated child object. I attached a get__child_url() function to the parent which identified the existence of a child and returned the url of it's DetailView using reverse().
There is a doc for that
https://docs.djangoproject.com/en/dev/topics/http/urls/#reverse-resolution-of-urls
it can be used to generate an URL for a given view
main advantage is that you do not hard code routes in your code.
The reverse() is used to adhere the django DRY principle i.e if you change the url in future then you can reference that url using reverse(urlname).