Django Regular expression many slugs - python

I have the regular expression in my url that accepts pass one slug to my view, exemple:
127.0.0.1/cart/product_slug1
But I need a regex that accept pass one or more slugs, example:
127.0.0.1/cart/product_slug1/product_slug2/product_slug3/.../product_slugN
urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(
r'^cart/add/(?P<slug>[\w_-]+)/$', views.create_cartitem,
name='create_cartitem'
),
It's possible send many slugs?

[UPDATE]: It seems that you cannot do that. Instead, you can place a catch all pattern and capture the whole url. Then inside your views you can split it by / and get the parameters you want. Something like this:
urlpatterns = [
url(
r'^cart/add/(?P<slugs>[\w_/-]+)/$', views.create_cartitem, name='create_cartitem'
),
And then in your views, do this:
def my_view(request, slugs):
slugs = slugs.split('/')
# now slugs is a list of strings
Note, however, that this is error prone since both cart/add/h/e/l/l/o and cart/add/hell//o//to/you are valid.
-- OLD ANSWER --
Sure you can, but you cannot use both named captured parameters with unnamed ones.
So, change your urls.py to this:
urlpatterns = [
url(
r'^cart/add/([\w_-]+)/([\w_-]+/)*$', views.create_cartitem, name='create_cartitem'
),
And inside your views.py, instead of kwargs (like slug you already have) you must use args (positional arguments, now you're gonna have a list of slugs). Like this:
def my_view(request, *args):
for arg in args:
print(arg)
Now if you type 127.0.0.1:8000/cart/add/argv/argvv/argvvv/, inside your views you get them as a list ['argv', 'argvv', 'argvvv'].

Related

Dynamic Url's in Django

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 %}

Making a Django URL pattern with a variable which isn't a integer

I was busy doing the Django tutorials and they explain how you can have url patterns which make it possible to pass information back to the functions in the view.py file. For example
urlpatterns = patterns('',
url(r'^some_view/(?P<number>\d+)', views.some_view, name = 'some_view')
and the integer in the url slot '(?Pnumber>\d+)' is passed to the some_view function in the file views.py. Apparently the d+ stands for decimal but what should it be if I want to pass a string variable back to the some_views function.
You need to use this partern: (?P<anystring>.+)
urlpatterns = patterns('',
url(r'^some_view/(?P<anystring>.+)', views.some_view, name = 'some_view')

creating custom item in ADMIN_MENU_ORDER

I'm having trouble understanding how to use the custom functionality of ADMIN_MENU_ORDER?
I want to do something like so -
ADMIN_MENU_ORDER = (
("Content", ("pages.Page", "blog.BlogPost",
"generic.ThreadedComment", ("Media Library", "fb_browse"),)),
("Site", ("sites.Site", "redirects.Redirect", "conf.Setting")),
("Users", ("auth.User", "auth.Group",)),
("MYAPP", ("View1", "app_view1")),
)
From what I gather I need to use redirects from URLs but where and how am I doing this? What I'm assuming is I'm doing this in MYAPP?
urls.py:
urlpatterns = patterns('',
url(r'^view1/$', 'View1', name='app_view1'),
)
And then generate that in my views.py?
class View1():
queryset = model.objects.all().values('fielda', 'fieldb', 'fieldc')
def get(self):
return queryset
My custom menu items still don't show up. I'm guessing I need to parse them into a template or return the results in a format that can be consumed by the mezzanine code? In which case what does that format need to be?
You've pasted an example right there in your question:
("Media Library", "fb_browse")
From the docs: http://mezzanine.jupo.org/docs/admin-customization.html#custom-items
It is possible to inject custom navigation items into the
ADMIN_MENU_ORDER setting by specifying an item using a two item
sequence, the first item containing the title and second containing
the named urlpattern that resolves to the url to be used.
There's no need for redirects. You just need to use the urlpattern names. Your urlpatterns weren't named, they'd look like:
urlpatterns = patterns('',
url(r'^view1/$', 'view1', name='my_view1'),
url(r'^view2/$', 'view2', name='my_view2'),
)
Then:
ADMIN_MENU_ORDER = (
...
("MYAPP", (("First", "my_view1"), ("Second", "my_view2"))),
)

using HttpResponseRedirect

In one of my view function, under certain condition I want to redirect to another URL.
So I am doing
return HttpResponseRedirect(reverse(next_view, kwargs={'name': name1}))
Now I have another view function like
def next_view(request, name):
I also put following line in relevant urls.py file
from wherever import next_view
urlpatterns = patterns("",
url(r"^next_view/(?P<name>w+)/", next_view, name="next_view"),
)
This does not work, I get
Reverse for 'next_view' with arguments '()' and keyword arguments '{'name': u'test'}' not found.
I'm guessing that the regex isn't matching properly. How about:
r"^next_view/(?P<name>\w+)/"
Note the backslash before the 'w'.
For urls.py you want to add the backslash before the w+ and also add a $ sign at then end of the URL so that any other URL's joined onto this will be accepted:
urlpatterns = patterns("",
url(r"^next_view/(?P<name>\w+)/$", next_view, name="next_view"),
)
For views.py you want to add parenthesis around your view name:
def example_view(self):
# view code
return HttpResponseRedirect(reverse('next_view', kwargs={'name': name1}))

How to do reverse URL search in Django namespaced reusable application

Consider that I include namespaced reusable application:
urlpatterns = patterns('',
# ella urls
url('^ella/', include('ella.core.urls', namespace="ella")),
)
Now, the Ella applications has urls like that:
urlpatterns = patterns( '',
url( r'^(?P<category>[a-z0-9-/]+)/$', category_detail, name="category_detail" ),
# object detail
url( r'^(?P<category>[a-z0-9-/]+)/(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})/(?P<content_type>[a-z0-9-]+)/(?P<slug>[a-z0-9-]+)/$',
object_detail, name="object_detail" )
)
Now, calling {% url ella:category_detail category="cat" %} works fine. However, when object tries to generate link to it's details, it calls
from django.core.urlresolvers import reverse
url = reverse('object_detail', kwargs={'required' : 'params'})
This is not working, unless rewritten as
from django.core.urlresolvers import reverse
url = reverse('ella:object_detail', kwargs={'required' : 'params'})
So, if I understand it correctly, including reusable application into namespace breaks all inner reverse()s inside given application.
Is it true? What have I missed? Is there any way around?
Since you have name-spaced url configuration, you need to mention namespace:view-name pattern in order to reverse it properly (especially from view).
But, if you want to avoid this, you may also pass namespace/appname as current_app parameter.
There are multiple ways to specify current_app when you are in template. But if you are in view, you need to hard-code as you did, or pass to current_app parameter
url = reverse('object_detail',
kwargs={'foo':'bar'},
current_app=app_name_or_name_space)
refer: http://docs.djangoproject.com/en/dev/topics/http/urls/#reverse
URL Namespaces can be specified in two ways.
Firstly, you can provide the application and instance namespace as arguments to include() when you construct your URL patterns. For example,:
(r'^help/', include('apps.help.urls', namespace='foo', app_name='bar')),
This is right from http://docs.djangoproject.com/en/dev/topics/http/urls/#defining-url-namespaces.
Try changing include('ella.core.urls', namespace="ella") to include('ella.core.urls', namespace="ella", app_name="ella"). I'm not 100% this will work, but its worth a shot.
At least in Django 1.8 you can write something like this:
url = reverse('%s:object_detail' % request.resolver_match.namespace, kwargs={'required' : 'params'})
request.resolver_match.namespace is a string containing the namespace of the currently running view.

Categories

Resources