QueraTeam / django-nextjs

Next.js integration for Django projects
MIT License
351 stars 18 forks source link

_next/webpack-hmr' failed: / Too many redirects #11

Closed Amplitude88 closed 1 year ago

Amplitude88 commented 2 years ago

Hello,

i've try to install the package like described in the readme.

Environment:

Everything was installed successfully but i have several errors:

First of all on index js i get the error: WebSocket connection to 'ws://127.0.0.1:8000/_next/webpack-hmr' failed:

Bildschirmfoto 2022-08-09 um 19 40 11

But i can see the nextjs index.

Then i want to try to change the route to /test

I described a view and parsed it to the url. If i call the url i got the error: too many redirects and the page wouldn't load:

Bildschirmfoto 2022-08-09 um 19 43 54 Bildschirmfoto 2022-08-09 um 19 43 49

Here my Settings.py:

from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent.parent

SECRET_KEY = 'django-insecure-%2spqobsw&i$k(n(%(siwd#fxzh^h%wqk5nc3nx0_$upu8r5!q'

DEBUG = True

ALLOWED_HOSTS = []

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    "django_nextjs",
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'empire_next.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'empire_next.wsgi.application'

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_TZ = True

STATIC_URL = 'static/'

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

views.py

from django.shortcuts import render

# Create your views here.

from django_nextjs.render import render_nextjs_page_sync

def index(request):
    return render_nextjs_page_sync(request)

def test(request):
    return render_nextjs_page_sync(request)

urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path("", include("backend.urls")),
    path("", include("django_nextjs.urls")),
]

backend.urly.py:

from django.urls import path
from .views import index
urlpatterns = [
    path("", index, name="index"),
    path("test/", index, name="test"),
]

any solution for this?

danialkeimasi commented 2 years ago

Hi,

After Nextjs 12 the Webpack-HMR uses WebSocket and in order to get the WebSocket running, you should use the django-channels as mentioned in README.md.

So you don't need the path("", include("django_nextjs.urls")), in your urls.py and instead you should use the asgi.py file that is mentioned in README.md.

Besides the docs of django-channels and the README.md of this project, there are a couple of issues that showed common errors when you are running it: #4, #7

Amplitude88 commented 2 years ago

Hi,

thank you for your quick answer: Ok but how i have to work with the "too many redirects" error?

danialkeimasi commented 2 years ago

Oh sorry, I've missed that.

It's because of / at the end of your path. In your backend/urly.py change the path("test/", index, name="test"), to path("test", index, name="test"),.

Amplitude88 commented 2 years ago

Hey, if i do so

Django cant find the page anymore if i delete the "/" inside my app.urls.py. So i get a 404 error "Page not found". -> this is in my application

http://localhost:8000/login

If i do it from scratch, then it worked as expected. What im missing here?

Using the URLconf defined in empirex.urls, Django tried these URL patterns, in this order:

admin/
login [name='login']
logout/ [name='logout']
dashboard/ [name='dashboard']
dashboardtoken/ [name='dasboardToken']
ido/ [name='ido']
csrf/ [name='csrf']
[name='home']
botstart/ [name='startbot']
botsell/ [name='sellbot']
botapprove/ [name='approvebot']
getapprove/ [name='getapprovedToken']
proofapprove/ [name='proofApproved']
^media/(?P<path>.*)$
^static/(?P<path>.*)$

empirex.urls.py

path('login', views.login_user, name='login'),
    path('logout/', views.logout_user, name='logout'),
    path('dashboard/', views.dashboard, name='dashboard'),
    path('dashboardtoken/', views.dashboardToken, name='dasboardToken'),
    path('ido/', views.ido, name='ido'),
    path('csrf/', views.csrf, name='csrf'),
    path('', TemplateView.as_view(template_name='home.html'), name='home'),
    path('botstart/', views.startBot, name='startbot'),
    path('botsell/', views.sellBot, name='sellbot'),
    path('botapprove/', views.approveBot, name='approvebot'),
    path('getapprove/', views.getApprovedToken, name='getapprovedToken'),
    path('proofapprove/', views.proofApproved, name='proofApproved'),

views.py

async def login_user(request):
    if request.method == 'POST':
        username = request.POST['username']
        password = request.POST['password']
        user = authenticate(request, username=username, password=password)

        if user is not None:
            try:
                parameter = BotParameter.objects.get(user=user)
            except:
                BotParameter.objects.create(user=user)
                login(request, user)
                return redirect('dashboard')
            else:
                login(request, user)
                return redirect('dashboard')
        else:
            messages.error(request, 'Username oder Passwort falsch')
            return redirect('login')
    return await render_nextjs_page_async(request, 'registration/login.html')

asgi.py:

from channels.auth import AuthMiddlewareStack
import os
import django
from django.core.asgi import get_asgi_application
from django.urls import re_path, path

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'empirex.settings')
django.setup()

django_asgi_app = get_asgi_application()
from channels.routing import ProtocolTypeRouter, URLRouter
from backend.routing import ws_urlpatterns
from django_nextjs.proxy import NextJSProxyHttpConsumer, NextJSProxyWebsocketConsumer

from django.conf import settings

# put your custom routes here if you need
http_routes = [re_path(r"", django_asgi_app)]
websocket_routers = []

if settings.DEBUG:
    http_routes.insert(0, re_path(r"^(?:_next|__next|next).*", NextJSProxyHttpConsumer.as_asgi()))
    websocket_routers.insert(0, path("_next/webpack-hmr", NextJSProxyWebsocketConsumer.as_asgi()))

application = ProtocolTypeRouter({
    'http': django_asgi_app,
    'websocket': AuthMiddlewareStack(URLRouter(websocket_routers))
})
danialkeimasi commented 2 years ago

Do you have a Nextjs page sync with test path? Something like pages/test.tsx or pages/test/index.tsx.

Amplitude88 commented 2 years ago

So i tried it with a test route and then the 404 is gone on /test route. But even i see a blank page. First if put path("", include("django_nextjs.urls")), again into my url the server could find webpack etc. and my test page is loading.

And then the webpack error comes back. But without path("", include("django_nextjs.urls")) i only see a blank page.

But if i call my /login route for example i get still the 404.

Bildschirmfoto 2022-08-10 um 08 15 59

Bildschirmfoto 2022-08-10 um 08 15 43

One point to mention:

If i type in localhost:8000/login the server automatically put a "slash" at the end, so that the url looks like localhost:8000/login/ in the browser address bar.

This didn't happen if i type in my test route localhost:8000/test

Amplitude88 commented 2 years ago

I tried another route because i thought it could be a post issue. But also on a easy GET view it is the same behaviour.

Maybe i forgot to tell that my environment is using "celery" and Django REST Framework" could it be a decorator problem?

Because then i get: AssertionError at /dashboard/ Expected a Response, HttpResponse or HttpStreamingResponse to be returned from the view, but received a <class 'coroutine'>

@api_view(['GET'])
@renderer_classes([TemplateHTMLRenderer])
@login_required
async def dashboard(request):

    coins = Coins.objects.all().values('name', 'symbol', 'price', 'image')

    return await render_nextjs_page_async({'coins': coins, 'WS_URL': env('WS_URL'), 'SERVER_URL': env('SERVER_URL')}, template_name='dashboard.html')
HKanwal commented 2 years ago

Django has a convenience feature that redirects to the same URL with an appended slash if Django failed to find a resource at the original location.

I had the same issue as you but was able to fix it by adding APPEND_SLASH = False to my project's settings.py.

Source: https://stackoverflow.com/questions/41118819/http-1-0-301-moved-permanently-django

danialkeimasi commented 1 year ago

I've added this in README.