django tastypie override url - django

i have a tastypie auto generated url
/api/v1/categories/?format=json
i want only this particular url to get data from a view instead of tastypie resource.
the reason i want to do is this because all my clients are using this and don't want to change that.
i tried to put my url under
url(r'^api/', include(v1_api.urls)),
url(r'^api/v1/categories/\?format=json','categories.views.raw_data'),
in urls.py
that doesn't seem to work

change the order:
url(r'^api/v1/categories/\?format=json','categories.views.raw_data'),
url(r'^api/', include(v1_api.urls)),
django looks for matches from top to bottom.
How Django processes a request

it can be done this way from tastypie instead of overriding it in urls.py by using override_urls in your resources
def override_urls(self):
return [url(r"^(?P<resource_name>%s)/$" % self._meta.resource_name,'categories.views.raw_data', name="categories_views_raw_data"),]

Related

Reversing to django admin index page

I am trying to redirect django index url to admin url which I can do something like below:
# url.py
path("", admin.site.urls,),
url("^admin/", admin.site.urls, name="admin"),
However, this generating warning
WARNINGS:
?: (urls.W005) URL namespace 'admin' isn't unique. You may not be able to reverse all URLs in this namespace
Hence, I decided to create a index view and use django.view.genertic.redirectview to pass to Django admin root URL as url attribute. I am trying find better way to generate Django admin root url using reverse function.
Ahh, found it. might help to someone.
reverse('admin:index', current_app=self.name)

redirect vs reverse django

I have experienced using reverse within get_absolute_url method in the model, but I wish I have an idea about the difference between reverse and redirect, I have tried to search on google about it but there is almost nothing
I don't know what should I write also to convince stack overflow that I don't have any other description
Reverse and redirect have a different meaning. Here is a simple explanation:
reverse in Django is used to find the URL of a given resource. Let's say that you have a blog website and from the main page, you want to provide links to your blog posts. You can of course just hard-code /posts/123/ and just change the ID of your blog post in URL, but that makes it hard to change your URL for the post in the future. That's why Django comes with reverse function. All you need to do is to pass the name of your URL path (defined in your urlpatterns) and Django will find for you the correct URL. It is called reverse because it is a reverse process of determining which view should be called for a given URL (which process is called resolving).
Redirects are not specific to Django or any other web frameworks. Redirect means that for a given URL (or action), the user should be instructed to visit a specific URL. This can be done by sending a special redirect request and from there the browser will handle it for the user, so no user action is required in that process. You can use reverse in redirect process to determine the URL that the user should be redirected to.
GwynBleidD has given you the answer, but there is a reason why you might be getting confused. The Django redirect shortcut accepts arguments in several different forms. One of them is a URLpattern mane, with arguments, that is then passed to reverse to generate the actual URL to redirect to. But that's just a shortcut, to enable a common pattern.
here's an example
app/views
#imports
def indexView(request):
....
return render(request, 'index.html', context)
def loginView(request):
....
return redirect('index')
def articleDetailView(request, id):
....
return redirect(reverse('article-comments', kwargs={'id':id})
def articleCommentsView(request, id):
....
return render(request, 'comment_list.html', context)
proj/urls
#imports
urlpatterns = [
....,
path('', include(app.urls))
]
app/urls
#imports
urlpatterns = [
....,
path('index/', index, name='index'),
path('login/', loginView, name='login'),
path('article/<int:id>/detail', articleDetailView, name='article-detail'),
path('article/<int:id>/comments/',articleCommentsView, name='article-comments')
....,
]
For loginView redirect will return url as-is i.e. 'index' which will be appended to base(project) urlpatterns. Here redirect(reverse('index')) will also work since kwargs is None by default for reverse function and 'index' view doesn't require any kwarg. It returns '/index/' which is passed to redirect(which again will be appended to base urls).
One thing to note is that reverse is used to make complete url - needed for redirect - that is shown in 'articleDetailview'.
The most basic difference between the two is :
Redirect Method will redirect you to a specific route in General.
Reverse Method will return the complete URL to that route as a String.

Upgrading from 1.8 to 1.9 Django Admin get_urls not working

I am using the Django admin and have just upgraded from 1.8 to 1.9. In 1.8, I added a click button to the change_form that takes me to another html template using the get_urls override. Like this:
def get_urls(self):
urls = super(arunAdmin, self).get_urls()
my_urls = patterns('',
(r'(\d+)/tarrespgraph/$', self.admin_site.admin_view(self.tarrespgraph)),
)
return my_urls + urls
Following some of the recommendations I saw online, I have changed this to:
def get_urls(self):
urls = super(arunAdmin, self).get_urls()
my_urls = [
url(r'^tarrespgraph/$', self.admin_site.admin_view(self.tarrespgraph)),
]
return my_urls + urls
But am receiving this error:
NBI Graph object with primary key '132/change/tarrespgraph' does not exist.
Django finds the customized change_form.html without a problem. My custom template (tarrespgraph.html) is in the same folder as my customized change_form.html. Where is Django looking for my custom template? Should I move the tarrespgraph.html, or change the reference to the url? Thanks in advance for your assistance!
You probably shouldn't have removed the (\d+) group from your url pattern. Try the following:
my_urls = [
url(r'^(\d+)/tarrespgraph/$', self.admin_site.admin_view(self.tarrespgraph), name='tarrespgraph'),
]
Note that I've added a name, which will let us reverse the url later.
Without the (\d+) group, the new url pattern does not match the url, so it is handled by the admin change view which gives the error.
You also need to change the link in your template. In Django 1.9, Django has appended change to the admin change url (e.g it is now /admin/app/model/132/change/ instead of /admin/app/model/132/. That means that your relative link 'tarrespgraph/' now points to /admin/app/model/132/change/tarrespgraph/ instead of /admin/app/model/132/tarrespgraph/. You could change the relative link to ../tarrespgraph/. However, it would be less fragile to use the url tag instead:
<a class="tarrespgraph" href="{% url 'admin:tarrespgraph' object_id %}">

Overriding a Django app url to make it Non-accessible

I'm using userena for handling the users' profiles. I created an app that override some of userena views and urls.
In particular I've created two different signup forms, so now I have two separate urls:
url(r'^signup/customer/$',....
url(r'^signup/owner/$',...
The original userena signup form was accessible at r'^signup/$'.
Question: How do I override the userena original signup url in order to make it unavailable?
The original url should not be accessible to anyone, so I guess Django should show a 404 page.
In your root urls.py conf, just override the url which you want to disable and direct it to Django 404 (page not found) view:
from django.views.defaults import page_not_found
url(r'^signup/$',
page_not_found,
name='userena_signup'),
If you are already overriding some views and URLs, you could override the signup URL with a view that just returns a 404 response.

How to get rid of the version information in API url in tastypie django?

I am creating REST based APIs for an app using Tastypie with Django. The problem is default API url in Tastypie contains version info in url patterns i.e.
http://lx:3001/api/v1/vservers/?username=someuser&api_key=someapikey
I want my url to be free from API version info like this:
http://lx:3001/api/vservers/?username=someuser&api_key=someapikey
urls.py
v1_api = Api()
v1_api.api_name = ''
v1_api.register(UserResource())
...
url(r'^api/', include(v1_api.urls)),
I am overwriting api_name with an empty string still
http://lx:3001/api/vservers/?username=someuser&api_key=someapikey does not work.
How can I get rid of the version info altogether?
Thanks..
Subclass Api and override urls to remove all the api_name-related bits:
class MyApi(Api):
#property
def urls(self):
"""
Provides URLconf details for the ``Api`` and all registered
``Resources`` beneath it.
"""
pattern_list = [
url(r"^%s$" % trailing_slash(), self.wrap_view('top_level'), name="api_top_level"),
]
for name in sorted(self._registry.keys()):
pattern_list.append((r"^/", include(self._registry[name].urls)))
urlpatterns = self.override_urls() + patterns('',
*pattern_list
)
return urlpatterns
Although tastypie makes supplying api_name optional, failing to provide one simply defaults api_name to "v1". This behavior can be modified by subclassing Api and overriding the urls property within api.py to behave independently of api_name. To achieve the desired URLconf, however, there's still one correction to #dokkaebi's solution worth noting:
pattern_list.append((r"^/", include(self._registry[name].urls)))
should instead read:
pattern_list.append((r'', include(self._registry[name].urls)))
in order to avoid the dreaded // that would direct your clients to
http://lx:3001/api//vservers/?username=someuser&api_key=someapikey
in place of
http://lx:3001/api/vservers/?username=someuser&api_key=someapikey
as intended.
For convenience, I've included the modified code below.
Solution
class MyApi(Api):
"""
An API subclass that circumvents api_name versioning.
"""
#property
def urls(self):
"""
Provides URLconf details for the ``Api`` and all registered
``Resources`` beneath it.
"""
pattern_list = [
url(r"^%s$" % trailing_slash(), self.wrap_view('top_level'), name="api_top_level"),
]
for name in sorted(self._registry.keys()):
pattern_list.append((r'', include(self._registry[name].urls)))
urlpatterns = self.override_urls() + patterns('',
*pattern_list
)
return urlpatterns
Convention
One of Django’s core philosophies is that URLs should be beautiful; a clean, elegant URL scheme is an important detail in any high-quality Web application. With respect to the validity of this approach, using a custom request header or an accept header will get the versioning job done without convoluting the scheme with the (subjectively) ugly v1/. That is not to say that the URL versioning strategy is without its share of caveats; however, it's quick to implement and predictable in its response.