My django app's urls are setup as follows for my development machine:
urls.py:
urlpatterns = [
url(r'^$', home, name='home'),
url(r'^signin$', signin, name='signin'),
url(r'^signout$', signout, name='signout'),
url(r'^advisor/', include('apps.advisor.urls', namespace='advisor')),
]
This setup works fine while developing the app using Django's builtin server (e.g. http://127.0.0.1:8000). I have to deploy the app to a machine and the Django app is exposed by the following url:
http://ip address/appname/
I'd like to have my urls.py file configured so the regular expression in the url tests to see if the url request starts with "appname" or "" (empty string). This method would mean I don't have to create to urls.py files (dev and prod versions). Thanks for any help!
You do not have to do this at all. When your app is deployed via WSGI, the server should pass on the SCRIPT_NAME parameter which identifies the path it is mounted at. As long as you have consistently used {% url %} and reverse() throughout your app rather than hard-coding links, everything will just work.
Related
These are the packages that I am using:
Django==3.2
django-storages==1.12.3
I am trying to deploy a django REST API with Vuejs frontend on azure. This is my directory structure for the django API.
I have used djang-storages[azure] to use an azure container blob to store media files. I went through a tutorial to setup the blob connection with django. Some configuration that I did with settings.py are these
Settings.py
MEDIA_LOCATION = "media"
AZURE_ACCOUNT_NAME = "my account name"
AZURE_ACCOUNT_KEY="my token"
AZURE_CUSTOM_DOMAIN = f'{AZURE_ACCOUNT_NAME}.blob.core.windows.net'
AZURE_LOCATION="media"
AZURE_CONTAINER="media"
STATIC_LOCATION = "static"
STATIC_URL = f'https://{AZURE_CUSTOM_DOMAIN}/{STATIC_LOCATION}/'
STATICFILES_STORAGE = 'storages.backends.azure_storage.AzureStorage'
DEFAULT_FILE_STORAGE = 'el.custom_azure.AzureMediaStorage'
AZURE_CONNECTION_TIMEOUT_SECS=100
and my custom_azure.py looks like this:
custom_azure.py
from storages.backends.azure_storage import AzureStorage
class AzureMediaStorage(AzureStorage):
account_name="eltechstorage"
account_key="my token"
azure_container="media"
expiration_specs=None
urls.py
from django.contrib import admin
from django.urls import path,include
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('admin/', admin.site.urls),
path("",include("main.urls"))
]
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
When I am using azure blob container to upload media files it is working perfectly in development environment and when I am testing the API from the deployed url, it is giving me the path of the file as expected on which if i go to, downloads the file for me, everything is working perfect. Below is attached a sample response from the API.
The Problem
But when I use the deployed version of both Django and Vuejs App, and I open the page, where the API returns the object containing link to the file. it displays a 404 error.
according to django doc, the static helper is only workable in debug mode. therefore, in your production environment, if you don't have debug mode enabled, then you static view will not be there. as a temporary measure, you can enable debug by put DEBUG=True in your application settings.
as recommendation by django, you should serve your static files in a dedicate server in production environment.
I've deployed my Django (DRF API) project on DigitalOcean apps. The path "/" is used by my static site that uses this API so I set route for this component to "/api" which works correctly.
The problem:
I go to /api/admin/ and it redirects me to /admin/login but the django is served on /api url so this URL is invalid.
Do you know how to make this work?
Is there a way to tell django to use absolute URL everywhere?
urls.py
urlpatterns = [
...
path("api/admin/", admin.site.urls),
...
]
I understand the concept of what I want to do (there is a rather nice question here: Django, REST and Angular Routes)
Django has a route for DRF, Admin, and needs at least one more, for the angular page.
But I'm not sure on the implementation details, particularly in where to put the frontend/static files, what to put in urls.py, and how to configure it for dev+production.
My url patterns currently look like this:
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^api/', include(router.urls)),
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]
Ideally, in production, I want serve the HTML without touching django - straight from nginx or similar (probably using AWS EB, but that is outside the scope of this question).
For Dev - I don't mind, as long as it works!
Skipping djangos templating system for angular would be great, rather than altering angulars operators. I don't intend to use django templates (except in djangos admin, and DRFs browsable views)
For development, I use something like this, at then end of the main urls.py file, to serve static files from various directories:
if settings.DEBUG:
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.conf.urls.static import static
# this connects STATIC_URL to STATIC_ROOT
urlpatterns += staticfiles_urlpatterns()
# connect other paths to directories
urlpatterns += static(settings.MEDIA_URL,
document_root=settings.MEDIA_ROOT)
urlpatterns += static('/app/',
document_root=join(settings.BASE_DIR, '../ng_app/'))
For production, you set the webserver to handle the requests. First the known routes like /admin/, /api/, /api-auth/ and files in /static/.
And then a catch-all route / that would always serve your index.html with the Angular app for any route. So that HTML5 routes in Angular will always load the app first, and the app then uses its own routes to build the correct page from API data.
The actual app files could be anywhere, even on a different server.
Here is a quote from Two Scoops of Django: Best Practices For Django 1.6:
In the past, we placed all API view code into a dedicated Django app
called api or apiv1, with custom logic in some of the REST views,
serializers, and more. In theory it’s a pretty good approach, but in
practice it means we have logic for a particular app in more than just
one location.
Our current approach is to lean on URL configuration. When building a
project-wide API we write the REST views in the views.py modules, wire
them into a URLConf called something like core/api.py or
core/apiv1.py and include that from the project root's urls.py
module. This means that we might have something like the following
code:
# core/api.py
""" Called from the project root's urls.py URLConf thus:
url(r" ˆ api/", include("core.api"), namespace="api"),
"""
from django.conf.urls.defaults import patterns, url
from flavors import views as flavor_views
from users import views as user_views
urlpatterns = patterns("",
# {% url "api:flavors" %}
url(
regex=r" ˆ flavors/ $ ",
view=flavor_views.FlavorCreateReadView.as_view(),
name="flavors"
),
# {% url "api:flavors" flavor.slug %}
url(
regex=r" ˆ flavors/(?P<slug>[-\w]+)/ $ ",
view=flavor_views.FlavorReadUpdateDeleteView.as_view(),
name="flavors"
),
# {% url "api:users" %}
url(
regex=r" ˆ users/ $ ",
view=user_views.UserCreateReadView.as_view(),
name="users"
),
# {% url "api:users" user.slug %}
url(
regex=r" ˆ users/(?P<slug>[-\w]+)/ $ ",
view=user_views.UserReadUpdateDeleteView.as_view(),
name="users"
),
)
But I don't understand where to put core/api.py. Is this a separate Django app called core? Where api.py should sit?
It means create the file you have as core/api.py (along with an empty core/__init__.py file) and then add the line url(r" ˆ api/", include("core.api"), namespace="api") to the root urls.py file of your project.
You don't have to call it core/api.py, that is just a suggestion from the authors
what does we write the REST views in the views.py modules mean?
It means what you've done, for each of the Django apps in your project, such as flavors, users they will have a views.py (or views/*.py) in them where you'd put the code for both the API and non-API views. (this is just a sane naming convention, nothing more... Django relies on the urlpatterns to tell it how to connect url routes to view code)
It's great to build up stuff like this from scratch as a way to learn Django. If you're doing a serious REST API project have a look at Django REST framework.
When I was using the built-in simple server, everything is OK, the admin interface is beautiful:
python manage.py runserver
However, when I try to serve my application using a wsgi server with django.core.handlers.wsgi.WSGIHandler, Django seems to forget where the admin media files is, and the admin page is not styled at all:
gunicorn_django
How did this happen?
When I look into the source code of Django, I find out the reason.
Somewhere in the django.core.management.commands.runserver module, a WSGIHandler object is
wrapped inside an AdminMediaHandler.
According to the document, AdminMediaHandler is a
WSGI middleware that intercepts calls
to the admin media directory, as
defined by the ADMIN_MEDIA_PREFIX setting, and serves those images.
Use this ONLY LOCALLY, for development! This hasn't been tested
for
security and is not super efficient.
And that's why the admin media files can only be found automatically when I was using the test server.
Now I just go ahead and set up the admin media url mapping manually :)
Django by default doesn't serve the media files since it usually is better to serve these static files on another server (for performance etc.). So, when deploying your application you have to make sure you setup another server (or virtual server) which serves the media (including the admin media). You can find the admin media in django/contrib/admin/media. You should setup your MEDIA_URL and ADMIN_MEDIA_URL so that they point to the media files. See also http://docs.djangoproject.com/en/dev/howto/static-files/#howto-static-files.
I've run into this problem too (because I do some development against gunicorn), and here's how to remove the admin-media magic and serve admin media like any other media through urls.py:
import os
import django
...
admin_media_url = settings.ADMIN_MEDIA_PREFIX.lstrip('/') + '(?P<path>.*)$'
admin_media_path = os.path.join(django.__path__[0], 'contrib', 'admin', 'media')
urlpatterns = patterns('',
url(r'^admin/', include(admin.site.urls)),
url(r'^' + admin_media_url , 'django.views.static.serve', {
'document_root': admin_media_path,
}, name='admin-media'),
...
)
Also: http://djangosnippets.org/snippets/2547/
And, of course, #include <production_disclaimer.h>.