I have the following urlpatterns:
urlpatterns = patterns('',
url(r'^$', 'opeiaa.views.home', name='home'),
url(r'^store/$', 'opeiaa.views.store', name='store'),
url(r'^resume/$', 'opeiaa.views.resume', name='resume'),
url(r'^contact/$', 'opeiaa.views.contact', name='contact'),
url(r'^gallery/', include('gallery.urls')),
url(r'^admin/', include(admin.site.urls)),
)
... and am using this kind of template tag:
<a class='nav-link' href='{% url 'contact' %}'>Contact</a>
The URL gets rendered in the page as http://localhost:8000/contact/. Everything works fine, when using ./manage.py runserver for testing...
... but then I run ./manage.py runfcgi - then when I navigate to the contact page, the URL in the navigation points to http://localhost:8000/contact/contact/! I have tried putting a slash at the start to make the URL absolute, but the URLs appear to be absolute without it.
I am using nginx as a frontend, and the relevant config from there is:
location / {
include fastcgi_params;
fastcgi_pass unix:/tmp/django.sock;
fastcgi_param PATH_INFO $fastcgi_script_name;
fastcgi_pass_header Authorization;
fastcgi_intercept_errors off;
}
I am using Django 1.6 & Python 2.7.4. Anyone have any insight?
8 months later I had figured this out when it happened on another one of my sites, because SCRIPT_NAME was being set before include fastcgi_params!
The final working config snippet:
location / {
include fastcgi_params;
fastcgi_param SCRIPT_NAME "";
fastcgi_pass unix:/tmp/django.sock;
fastcgi_param PATH_INFO $fastcgi_script_name;
fastcgi_pass_header Authorization;
fastcgi_intercept_errors off;
}
Related
I'm working on a Django web app and it's running really fine and well, but I'm facing a small issue where after I deployed the app on a VPS, the Django Rest Framework default API URL is pointing at the home IP address like in the image below.
The issue here is that when I'm running my app on the server, the above highlighted URL is directing me toward my home IP address on my local machine.
How can I change this URL with the IP address of the VPS or domain? Is that possible?
Edit - 1:
Below is the code of my urls.py file if it can help
from django.views.static import serve
router = routers.DefaultRouter()
router.register(r'artfairs', views.ArtFairViewSet)
router.register(r'inquiries', views.InquiryViewSet)
router.register(r'mediums', views.MediumViewSet)
router.register(r'origins', views.OriginViewSet)
router.register(r'styles', views.StyleViewSet)
router.register(r'types', views.TypeViewSet)
router.register(r'users', views.UserViewSet)
router.register(r'artists', views.ArtistViewSet)
router.register(r'artworks', views.ArtworkViewSet)
router.register(r'shipping-addresses', views.ShippingAddressViewSet)
router.register(r'user-addresses', views.UserAddressViewSet)
router.register(
r'artworks-by-artist',
views.ArtworksByArtistViewSet,
basename='artworks-by-artist',
)
router.register(
r'cart',
views.CartViewSet,
basename='cart',
)
router.register(
r'latest-artworks',
views.LatestArtworksViewSet,
basename='latest-artworks',
)
router.register(
r'wishlist',
views.WishListViewSet,
basename='wishlist',
)
urlpatterns = [
path('', include(router.urls)),
# media and static files paths
url(r'^media/(?P<path>.*)$', serve,
{'document_root': settings.MEDIA_ROOT}),
url(r'^static/(?P<path>.*)$', serve,
{'document_root': settings.STATIC_ROOT}),
# paths related to JWT Authentication
path('api/token/', TokenObtainPairView.as_view(),
name='token_obtain_pair'),
path('api/token/refresh/',
TokenRefreshView.as_view(),
name='token_refresh'),
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) + static(
settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
After a lot of research, I was finally able to find my answer in these 2 links. The first one was from DRF documentation while the other one is a question previously asked on stackoverflow.
Routers Page in Django Rest Framework Documentation
How to change the Django Rest Framework's default url to a custom
I edited my location settings to look like this:
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://unix:/root/<my_app_directory>/<my_app.sock>;
}
I have a single page application created in Vue.js that utilizes the HTML5 History Mode for routing, and the html file is served with Django.
The urls.py of django is like so:
urlpatterns = [
url(r'^$', views.home),
url(r'^admin/', admin.site.urls),
url(r'^api-token-auth/', obtain_jwt_token),
]
And views.home:
def home(request):
return render(request, 'index.html')
Consider the following scenario:
User visits the home page (i.e., /)
Since, the home page responds with required index.html for the Single page Vuejs app, it works like its supposed to.
From there the user navigates to the about page (i.e., /username/12).
Its still working fine, as its navigating with the Vue router.
Now, the user refreshes the page.
Since there's no /username/12 in the urls.py patterns, it will show Page not found (404).
Now, I could provide another pattern in urls.py to catch all pattern in the last order as this:
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^api-token-auth/', obtain_jwt_token),
url(r'^.*$', views.home),
]
But other urls like the media or static urls will also point to the same catch all pattern regex. How can I solve this problem?
I have a similar problem.
How can I use vue-router and django rest
framework the same time?
This is my solution to this problem. Hope it helps you.
Expected results:
http://127.0.0.1:8000/ <-- TeamplateView index.html using vue
http://127.0.0.1:8000/course <-- vue-router
http://127.0.0.1:8000/api <-- rest framework
http://127.0.0.1:8000/admin <-- django admin
and I try this and it works!
urls.py
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
url(r'^api/', include(router.urls)),
url(r'^.*$', TemplateView.as_view(template_name="index.html")),
]
The order is important,
url(r'^.*$', TemplateView.as_view(template_name="index.html")),
is the last one
and this is my vue router
const router = new VueRouter({
mode: 'history',
base: __dirname,
routes: [{
path: '/courses',
component: CourseSet
}, {
path: '/',
component: hello
}]
})
My project on GitHub
Since you have mentioned "single page":
The server is supposed to serve just one page the index.html (or whatever else you would like to call it).
The server and the web application (front-end) code would communicate via api calls, such that the server provides resources and the web-app takes care of using that resource.
In case of a missing resource, the server still must not respond with a separate page, it should still respond with a message that the web-app can use.
I have a single page application created in Vue.js that utilizes the HTML5 History Mode for routing
I believe you are using vue-router, which simulates the single-page app to be a full-featured, multi-page application.
You may want to take a look at this and this, but the above holds true for a single page application.
You shared your urlpatterns:
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^api-token-auth/', obtain_jwt_token),
url(r'^.*$', views.home),
]
But other urls like the media or static urls will also point to the same catch all pattern regex. How can I solve this problem?
A way you can manage that would be either by, serving on a route other than '/' like mentioned above for /app.
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^api-token-auth/', obtain_jwt_token),
url(r'^.*$/app', views.home),
]
and in your router.js file:
new Router({
mode: 'History',
base: '/app'
routes: [
{
path: '/',
name: 'name',
component: ComponentName
}
]
})
Or prefixing the purpose served by the urls like
urlpatterns = [
url(r'^api/admin/', admin.site.urls),
url(r'^api/api-token-auth/', obtain_jwt_token),
url(r'^.*$', views.home),
url(r'^.*$/assets', your-static-assets)
]
I'm using VueJS router enabled history mode with Django 2.x by this way:
From app urls.py you need to repath your frontend url like this:
# urls.py
from django.urls import path, include
from django.urls import re_path
urlpatterns = [
path('', TemplateView.as_view(template_name="application.html"), name="app", ),
# ... rest of your urls
]
urlpatterns += [
re_path('^.*$', TemplateView.as_view(template_name="application.html")),
]
Now history mode working smoothly!
http://sample.com/#/users/login/
Become:
http://sample.com/users/login/
I solved the issue by using the negative look-ahead regex, so basically anything inside (?!ignore1|ignore2) will be ignored.
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^api-token-auth/', obtain_jwt_token),
url(r'^(?!admin|api-token-auth|static).*$', views.home),
]
Note: I tried not including admin and api-token-auth inside the negative look-ahead and it didn't work for me, it will still route path that starts with admin to the views.home, not sure why as according to my understanding, django should match the earlier ones first.
Since index.html is templated (a dynamic page) because it's served from your views instead of static, this becomes a bit weird.
For production, definitely use nginx or apache to serve the static content in a similar fashion.
For development, this is what I would do:
from django.contrib.staticfiles.views import serve
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^api-token-auth/', obtain_jwt_token),
]
# Serve your static media (regex matches *.*)
if settings.DEBUG:
urlpatterns.append(url(r'(?P<path>.*\..*)$', serve))
# Serve your single page app in every other case
urlpatterns.append(url(r'^.*$', views.home))
The answer provided above by #billi works fine, up to a point. My problem is that for my SPA I want (need?) to use the Vue <router-view> and <router-link> system. But the router.js maps paths to Vue components, and some of my paths are to Django views via Django urls.py - for example, this will result in a blank page if navigating to /api/places from the Vue router nav, but will resolve correctly to a Django if refreshed.
Ideas?
urls.py
urlpatterns = [
# Django
path('admin', admin.site.urls),
url(r'^api-auth/', include('rest_framework.urls')),
url(r'^api/places$', views.PlaceList.as_view()),
# catchall to Vue single page app
url(r'^.*$', TemplateView.as_view(template_name='myapp/spa.html'), name='home'),
]
router.js
export default new Router({
mode: 'history',
routes: [
{path: '/search', component: Search},
{path: '/about', component: About},
{path: '/', component: Home},
{path: '/api/places', }
]
})
App.vue
<template>
<div id="app">
<div>
<router-link to="/search">Search</router-link> ::
<router-link to="/about">About</router-link>
<router-link to="/">Home</router-link> ::
<router-link to="/api/places">Place API</router-link> ::
</div>
<router-view></router-view>
</div>
</template>
Don't know if anyone still looking for the solution.
I build Django Rest API and Vue front totally in a stand alone way. Then when i tried to put the dist folder items in static files of Django and tried to server through gunicorn and NGINX I just could not get the spa working.
Finally did this and very surprisingly it works.
Basically,
forward error page to the index.html of Vue.
Here's my NGINX config:
location /static/ {
root /root/bdn/bdn/server/;
}
location /media/ {
root /root/bdn/bdn/server/;
}
location ^~ /admin/ { # Define routes to be directed to backend as proxy
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://unix:/run/gunicorn.sock;
}
location ^~ /api/ { # Define routes to be directed to backend as proxy
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://unix:/run/gunicorn.sock;
}
location ^~ /api-auth/ {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://unix:/run/gunicorn.sock;
}
location ^~ /{
root /root/bdn/bdn/server/templates/;
index index.html;
}
error_page 404 /; # THIS IS WHAT IT CAME DOWN TO AFTER HOURS AND HOURS OF SEARCHING
Question says it almost all.
E.g. changing default url (http://127.0.0.1:8000) to a custom (https://api.example.com/v1)
I'm using HyperlinkedModels and everything seems to work properly in development. Moving the app to another server with custom url is giving me problems.
How do I change the default url:
To a custom one, let's say:
https://api.example.org/v1/
You are mixing two questions in one:
How to run django-rest-framework project on a different domain
How to change URL path of API
To answer the first one I'd say, "Just do it". Django's reverse uses request's domain to build absolute URL.
UPDATE: don't forget to pass Host header from nginx/apache. Below is a sample nginx config:
server {
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://127.0.0.1:8000;
}
}
The second (path, mount point) is set in the urls.py:
from django.conf.urls import url, include
from django.contrib import admin
from rest_framework import routers
from quickstart import views
router = routers.DefaultRouter()
router.register(r'users', views.UserViewSet)
router.register(r'groups', views.GroupViewSet)
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
url(r'^v1/', include(router.urls)), # <-------------- HERE
]
Django admin panel throws 404 when passing any url parameters
Example url:
/admin/app/model/ - OK
/admin/app/model/?foo=bar - 404
/admin/app/model/?p=1 - 404
Nginx+uwsgi
Project urls file (admin,admin_tools,application urls)
from django.conf.urls import patterns, include, url
from django.views.generic import TemplateView
import restaurant.views
import club.views
import hotel.views
import custom_app.views
import cart.views
from django.views.decorators.csrf import csrf_exempt
from django.contrib import admin
import settings
handler404 = 'custom_app.views.handler404'
admin.autodiscover()
urlpatterns = patterns('',
url(r'^admin_tools/', include('admin_tools.urls')),
(r'^$', custom_app.views.Index.as_view()),
(r'^restaurant$', restaurant.views.Index.as_view()),
(r'^which$', csrf_exempt(TemplateView.as_view(template_name='custom_app/which.html'))),
(r'^cart/add', cart.views.AddToCart.as_view()),
(r'^cart/delete', cart.views.RemoveFromCart.as_view()),
(r'^cart/send', cart.views.SendCart.as_view()),
(r'^cart/delivery', cart.views.SetDelivery.as_view()),
(r'^restaurant/about', restaurant.views.About.as_view()),
(r'^restaurant/payment', restaurant.views.Payment.as_view()),
(r'^restaurant/vip', restaurant.views.Vip.as_view()),
(r'^restaurant/menu/(?P<slug>.+)', restaurant.views.Menu.as_view()),
(r'^restaurant/menu/', restaurant.views.Menu.as_view()),
(r'^restaurant/cart/', cart.views.Basket.as_view()),
(r'^restaurant/tables/', restaurant.views.Tables.as_view()),
(r'^restaurant/success_ordering', restaurant.views.SuccesTableOrder.as_view()),
(r'^vacancy', custom_app.views.Vacancy.as_view()),
(r'^hotel$', hotel.views.Main.as_view()),
(r'^hotel/services', hotel.views.Services.as_view()),
(r'^hotel/room/(?P<room>\d+)$', hotel.views.Main.as_view()),
(r'^hotel/order/option/toggle$', hotel.views.ToggleOption.as_view()),
(r'^hotel/order/date/toggle$', hotel.views.ToggleDate.as_view()),
(r'^hotel/order/send$', hotel.views.Send.as_view()),
(r'^club/events/old/(?P<year>\d+)/(?P<month>\d+)', club.views.OldEvents.as_view()),
(r'^club/events/old/', club.views.OldEvents.as_view()),
(r'^club/about', club.views.About.as_view()),
(r'^club/event/(?P<pk>\d+)', club.views.DetailEvent.as_view()),
(r'^club$', club.views.Main.as_view()),
url(r'^admin/', include(admin.site.urls)),
(r'^ckeditor/', include('ckeditor.urls')),
)
if settings.DEBUG:
urlpatterns += patterns('',
url(r'^media/(?P<path>.*)$', 'django.views.static.serve', {
'document_root': settings.MEDIA_ROOT,
}),
)
Nginx configuration file:
server
{
listen %server_ip%;
server_name custom.ru www.custom.ru;
root /home/custom/www/;
location ~* ^/resize/([\d\-]+)/([\d\-]+)/(.+)$ {
alias /home/custom/www/custom/$3;
image_filter resize $1 $2;
image_filter_buffer 2M;
error_page 415 = /empty;
}
location ~* ^/crop/([\d\-]+)/([\d\-]+)/(.+)$ {
alias /home/custom/www/custom/$3;
image_filter crop $1 $2;
image_filter_buffer 2M;
error_page 415 = /empty;
}
location = /empty {
empty_gif;
}
location /
{
root /home/custom/www/custom/;
uwsgi_pass unix:///home/custom/tmp/uwsgi.sock;
include uwsgi_params;
uwsgi_param UWSGI_PASS unix:///home/custom/tmp/uwsgi.sock;
uwsgi_param UWSGI_CHDIR /home/custom/www/custom/;
uwsgi_param UWSGI_SCRIPT wsgi;
}
location /static
{
alias /home/custom/www/custom/static/;
}
location /media
{
alias /home/custom/www/custom/media/;
}
location = /favicon.ico { alias /home/custom/www/favicon.ico; }
}
Try
/admin/app/action?foo=bar
instead of /?
The extra / is looking for a resource at that location
Right now, any url just brings up a project default page ("welcome to django").
No matter what I put (example.com, example.com/hello, example.com/asdfjkasdf(&$(#$$#)
I'm new to django and am following a simple tutorial.
My nginx.conf has this:
location / {
# host and port to fastcgi server
fastcgi_pass 127.0.0.1:8801;
fastcgi_param PATH_INFO $fastcgi_script_name;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param SERVER_NAME $server_name;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_pass_header Authorization;
fastcgi_intercept_errors off;
}
My site files are stored in /var/www/firstsite/
My views.py has this:
from django.http import HttpResponse
def hello(request):
return HttpResponse("Hello world")
And my urls.py has this:
from django.conf.urls.defaults import *
from firstsite.views import hello
# Uncomment the next two lines to enable the admin:
# from django.contrib import admin
# admin.autodiscover()
urlpatterns = patterns('',
('^hello/$', hello),
# Example:
# (r'^firstsite/', include('firstsite.foo.urls')),
# Uncomment the admin/doc line below and add 'django.contrib.admindocs'
# to INSTALLED_APPS to enable admin documentation:
# (r'^admin/doc/', include('django.contrib.admindocs.urls')),
# Uncomment the next line to enable the admin:
# (r'^admin/', include(admin.site.urls)),
)
Do I need to restart the fcgi instance with each change(I wouldn't think so). I've been using: python manage.py runfcgi method="thread" host=127.0.0.1 port=8080
So yeah, how can I get urls working? Is there a way I can debug using django? For example, maybe print out the data it's receiving to make sure nginx is behaving correctly?
Don't start by trying to set Django up with FastCGI. Follow the actual tutorial, and use the built-in development server. Once you've got a grip on how the basic framework works, then you can move to understanding how to deploy it.
And why would you say you wouldn't think you would have to restart the instance with each change? That is precisely what you need to do.