My Django project has two applications in it: a web tool and a REST interface.
I run the REST interface on my database system (e.g. db.myhost.com). This interface only has URL patterns that correspond to the various REST endpoints:
app_name = "rest"
urlpatterns = [
url(r'^report/id/(?P<rid>[0-9]+)/$', views.ReportByID.as_view()),
url(r'^report/slug/(?P<slug>[a-z0-9-]+)/$', views.ReportBySlug.as_view()),
]
Part of the data that these views ultimately show need links to the other application in my project (which I host on a separate system). That application also has URL patterns:
app_name = "mytool"
urlpatterns = [
url(r'^some/cool/path/$', views.some_cool_path),
]
The REST interface only enables the REST URL patterns, since I only want to serve REST endpoints via that host:
# On my REST system
ROOT_URL = "myproject.rest_urls"
Is there a way that I can get the REST application to load the mytool URL patterns without activating them? I don't want a user to be able to browse to db.myhost.com/some/cool/path/ and get an error because that path isn't served on that host, it's served by the web tool server instead. It would be helpful, however, to be able to use reverse() to get the mytool URLs, even if they are just relative fragments (i.e. /some/cool/path ... I could always prepend the server name, which is unlikely to ever change).
I could hard-code the necessary paths, but I'd like to avoid having to do that in case they need to change in the future.
We can do it using django test utils override_settings decorator. It will use temporary settings so, it will not have any effect on the live site.
settings.py
INSTALLED_APPS = [
# .....
'mytool',
# .....
]
ROOT_URL = "myproject.rest_urls"
mytool/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('news/<slug:slug>/', views.NewsDetailView.as_view(), name='news_detail'),
]
mytool/utils.py
from django.test.utils import override_settings
from django.urls import reverse
def temp_reverse(url_conf, url_name, url_args=(), url_kwargs={}):
#override_settings(ROOT_URLCONF=url_conf)
def get_reverse(url_name, *args, **kwargs):
return reverse(url_name, args=args, kwargs=kwargs)
return get_reverse(url_name, *url_args, **url_kwargs)
accessing the reverse for unregistered urls
from mytool.urils import temp_reverse
url = temp_reverse('mytool.urls', 'news_detail', url_kwargs={'slug': 'django-awesome'})
print(url)
# output: /news/django-awesome/
Related
I'm using Django 3.0, dj-stripe 2.0, and the Stripe CLI. dj-stripe provides native support for Stripe webhooks, and their documentation says to include the following in my django project's main urls.py file to expose the webhook endpoint:
url(r"^stripe/", include("djstripe.urls", namespace="djstripe")),
I have done this, but how do I now leverage the endpoint?
As a separate experiment, I created a payments app, setup the URL conf, and successfully called the view when triggering the non dj-stripe webhook endpoint via the Stripe CLI. But it doesn't use any dj-stripe functionality:
# project urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('stripe/', include("djstripe.urls", namespace="djstripe")),
path('payments/', include("payments.urls", namespace="payments")),
]
# payments/urls.py
from django.urls import path
from . import views
app_name="payments"
urlpatterns = [
path("", views.my_handler, name="my-handler"),
]
# payments/views.py
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
#csrf_exempt
def my_handler(request, **kwargs):
print(request.body)
return HttpResponse(status=200)
Running stripe listen --forward-to localhost:8000/payments/ and, in a separate window, stripe trigger product.created returns a 200 response.
But stripe listen --forward-to localhost:8000/stripe/webhook/ and stripe trigger product.created returns a 500.
Thank you in advance for your help.
[UPDATE]
I have not modified the default DJSTRIPE_WEBHOOK_URL or DJSTRIPE_WEBHOOK_VALIDATION settings. In settings.py I have:
STRIPE_LIVE_PUBLIC_KEY = os.environ.get("STRIPE_LIVE_PUBLIC_KEY")
STRIPE_LIVE_SECRET_KEY = os.environ.get("STRIPE_LIVE_SECRET_KEY")
STRIPE_TEST_PUBLIC_KEY = os.environ.get("STRIPE_TEST_PUBLIC_KEY")
STRIPE_TEST_SECRET_KEY = os.environ.get("STRIPE_TEST_SECRET_KEY")
STRIPE_LIVE_MODE = os.environ.get("STRIPE_LIVE_MODE")
DJSTRIPE_WEBHOOK_SECRET = "*************************************"
The test keys are pulled from env/bin/activate:
export STRIPE_LIVE_PUBLIC_KEY="pk_live_****...."
export STRIPE_LIVE_SECRET_KEY="sk_live_****...."
export STRIPE_TEST_PUBLIC_KEY="pk_test_****...."
export STRIPE_TEST_SECRET_KEY="sk_test_****...."
export STRIPE_LIVE_MODE="False"
When I run stripe listen --forward-to localhost:8000/stripe/webhook/ and trigger stripe trigger customer.created I get the following 500 error:
stripe.error.InvalidRequestError: Request req_NTtzsTFS8uVdfL: No such customer; a similar object exists in test mode, but a live mode key was used to make this request.
But I don't understand how my keys could be getting mixed up, because the webhooks work fine when I trigger the same event and listen via the /payments/ endpoint.
Thank you again for your time.
In summary, you need to decorate a handler function using the #webhooks.handler decorator.
You have some examples in the webhooks section of the dj-stripe documentation.
I have a custom directory for allauth templates. I need some custom urlpatterns as well as I don't want some default views. I wanted to start with glueing in the entire allauth and change things that I need later on.
My main app config/urls.py file
from django.urls import include, path
urlpatterns = [
path("account/", include("users.urls")),
]
Users app:
users/urls.py
app_name = "users"
urlpatterns = [
path("login/", allauth_views.login, name="account_login"),
path("logout/", allauth_views.logout, name="account_logout"),
path("signup/", allauth_views.signup, name="account_signup"),
]
With this basic setup, if I go to /account/login it routes correctly to the desired view, but it is defined in users app with the app_name = "users", therefore, I have to access it in other views with reverse(users:account_login). The problem is that allauth LoginView has this method
def get_context_data(self, **kwargs):
ret = super(LoginView, self).get_context_data(**kwargs)
signup_url = passthrough_next_redirect_url(self.request,
reverse("account_signup"),
self.redirect_field_name)
redirect_field_value = get_request_param(self.request,
self.redirect_field_name)
site = get_current_site(self.request)
ret.update({"signup_url": signup_url,
"site": site,
"redirect_field_name": self.redirect_field_name,
"redirect_field_value": redirect_field_value})
return ret
which does the lookup on reverse("account_signup") but Django gets lost and throws django.urls.exceptions.NoReverseMatch.
Two solutions:
If I set those allauth urlpatterns in my main urls file it works correctly but I want to keep this file small and define allauth urls in my users app.
If I don't define app_name in my users/urls.py it works properly but I want it for other routes. I consider adding app_name to be a good practice. I could have created another app for allauth without an app name but then I'd have users stuff in two apps.
None of these satisfy me.
What I want:
Can I somehow include them without a namespace? I tried path("account/", include("users.urls", namespace=None)) without any luck.
I wasn't thinking... I can keep my custom users urls in users/urls.py with an app name and create another urls file like users/allauth_urls.py in users app and things work correctly.
Then, with
path("account/", include("users.allauth_urls")),
Things work as exepcted.
I'm starting using Wagtail + Django.
Generally, in Django you set the urls path in a urls.py file.
However, I cannot find the url.py that says to my app, when users visits main domain (local http://127.0.0.1:8000/) show home_page.html view.
I'm following the get_started tutorial.
And used this command to generate the basic apps:
wagtail start elim
This generated: a) elim, b) home, c) search apps.
Only elim app contains a urls.py, but it doesn't set a path for home:
from django.conf import settings
from django.conf.urls import include, url
from django.contrib import admin
from wagtail.admin import urls as wagtailadmin_urls
from wagtail.core import urls as wagtail_urls
from wagtail.documents import urls as wagtaildocs_urls
from search import views as search_views
urlpatterns = [
url(r'^django-admin/', admin.site.urls),
url(r'^admin/', include(wagtailadmin_urls)),
url(r'^documents/', include(wagtaildocs_urls)),
url(r'^search/$', search_views.search, name='search'),
]
This is my project structure:
So how does going to "/" open the home page???
The home dir is served by wagtail internal mechanism. Scroll to the end of the file elim/urls.py to find this :
urlpatterns = urlpatterns + [
# For anything not caught by a more specific rule above, hand over to
# Wagtail's page serving mechanism. This should be the last pattern in
# the list:
url(r"", include(wagtail_urls)),
# Alternatively, if you want Wagtail pages to be served from a subpath
# of your site, rather than the site root:
# url(r"^pages/", include(wagtail_urls)),
]
So, continue to read the tutorial, I'm sure you will soon or later discover the Page models and everything provided by wagtail.
Try adding a view function in your app's views.py file that renders home_page.html when the user goes to "/".
in views.py write this:
def home_page(response):
return render(response, "home/home_page.html")
then map this to ur urs.py file
url_patterns = [
path("", views.home_page)
]
then add this url to your url conf
I have a Python+Django website working under control of uWSGI and NginX.
On the production environment, each of the addresses below directs to an article. APPEND_SLASH=True setting makes the first URL (non-slash) redirect to the second URL (with one slash) - this is the part which I understand.
What is making third, fourth and every each URL with any number of slashes working?
1. http://example.com/my-article-slug
2. http://example.com/my-article-slug/
3. http://example.com/my-article-slug//
4. http://example.com/my-article-slug///
5. ...
URLs with many slashes just resolve the Django View (ArticleDetail) properly and show the article, without redirect (!).
However, on the Django local development web server, only first two of above links works. Http404 is returned if URL has more than one slash.
The DEBUG setting has nothing to do with this issue, according to my investigation.
It is worth noting that this behavior is a problem when I want to resolve a Django View from an URI, because addresses with many trailing slashes work correctly (on the production), but they are not resolved correctly by django.urls.resolve:
>>> from django.urls import resolve
>>> resolve('/my-article-slug/')
ResolverMatch(func=articles.views.ArticleDetail, args=(), kwargs={'slug': 'my-article-slug'}...
>>> resolve('/my-article-slug//')
django.urls.exceptions.Resolver404...
Django URLs cofiguration:
# urls.py
from django.urls import include, path
urlpatterns = [
path('', include('articles.urls')),
]
# articles/urls.py
from django.urls import path
from articles.views import ArticleDetail
urlpatterns = [
...
path('<slug:slug>/', ArticleDetail.as_view(), name='article-detail'),
...
]
By the way, I've noticed that it is quite common behavior, i.e.:
https://www.djangoproject.com////////////
https://docs.djangoproject.com/en/3.0////////////
https://www.dropbox.com////////////
https://www.dropbox.com/individual////////////
https://www.quora.com////////////
https://www.quora.com/answer////////////
Perhaps is it NginX-related issue?
I've installed django version 2.0 and default for urls is path I know that if in django 1.x can be urls and follow with regular expression, how do I use path for parameters instead of urls, and so I dont want to use urls because django by default add path not urls if its can be or use urls still I want to know how to use a path with parameters in django 2.0
here's my code
from django.urls import include, path
from . import views
urlpatterns = [
path('', views.articles_list),
path('add', views.articles_add),
path('edit', views.articles_edit)
]
path('edit/<int:id>', views.articles_edit)
you can add parameters like this
in view
def edit(request, id):
Application urls.py File Add Following code
path('blog/< int:blogid >', views.blog)
Application views.py file, add following code:
def blog(request, blogid):
Make sure both place name should be same (blogid)