TypeError: argument of type 'NoneType' is not iterable

Hi Gurus,

I’m pretty new to Python and Django and trying to build a Web app. currently facing issue with Logout Route and Profile Route. But for now I need guidance from experts on Logout .

Thanks advance

Error and StackTrace


*** Template Location**  PyQuiz/logout.html
System check identified no issues (0 silenced).
September 16, 2024 - 09:45:10
Django version 5.1, using settings 'quiz.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

**** Arg values : -  <WSGIRequest: GET '/logout/'>


NEXT Argunment value


**** kwargs values *********
NEXT Argunment value


**** Logout values values ********* <PyQuiz.views.UserLogoutView object at 0x1026a3f10>
Internal Server Error: /logout/
Traceback (most recent call last):
  File "/Applications/Training/Project_Amplify/venv/lib/python3.10/site-packages/django/shortcuts.py", line 180, in resolve_url
    return reverse(to, args=args, kwargs=kwargs)
  File "/Applications/Training/Project_Amplify/venv/lib/python3.10/site-packages/django/urls/base.py", line 88, in reverse
    return resolver._reverse_with_prefix(view, prefix, *args, **kwargs)
  File "/Applications/Training/Project_Amplify/venv/lib/python3.10/site-packages/django/urls/resolvers.py", line 831, in _reverse_with_prefix
    raise NoReverseMatch(msg)
django.urls.exceptions.NoReverseMatch: Reverse for 'None' not found. 'None' is not a valid view function or pattern name.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Applications/Training/Project_Amplify/venv/lib/python3.10/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/Applications/Training/Project_Amplify/venv/lib/python3.10/site-packages/django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/Applications/Training/Project_Amplify/venv/lib/python3.10/site-packages/django/views/generic/base.py", line 104, in view
    return self.dispatch(request, *args, **kwargs)
  File "/Applications/Training/Project_Amplify/venv/lib/python3.10/site-packages/django/views/generic/base.py", line 143, in dispatch
    return handler(request, *args, **kwargs)
  File "/Applications/Training/Project_Amplify/quiz/PyQuiz/views.py", line 113, in get
    response = redirect(self.get_redirect_url())
  File "/Applications/Training/Project_Amplify/venv/lib/python3.10/site-packages/django/shortcuts.py", line 49, in redirect
    return redirect_class(resolve_url(to, *args, **kwargs))
  File "/Applications/Training/Project_Amplify/venv/lib/python3.10/site-packages/django/shortcuts.py", line 186, in resolve_url
    if "/" not in to and "." not in to:
TypeError: argument of type 'NoneType' is not iterable
[16/Sep/2024 09:45:48] "GET /logout/ HTTP/1.1" 500 95035

Code from view.py

from django.shortcuts import render, redirect
from django.contrib import messages
from .forms import  UserUpdateForm, profileUpdateForm, UserLoginForm, UserRegisterForm
from django.contrib.auth.decorators import login_required
from allauth.account.views import LoginView, LogoutView, SignupView
from allauth.utils import get_form_class, get_request_param
from allauth.account.views import _ajax_response
from django.urls import reverse, reverse_lazy
from django.contrib.sites.shortcuts import get_current_site
from .import app_settings
from django.shortcuts import resolve_url
from allauth.account.adapter import get_adapter, DefaultAccountAdapter
from django.views.generic import UpdateView, CreateView
from allauth.account.utils import (
    complete_signup,
    get_login_redirect_url,
    get_next_redirect_url,
    # logout_on_password_change,
    passthrough_next_redirect_url,
    perform_login,
    sync_user_email_addresses,
    url_str_to_user_pk,
)

# from django.http import HttpResponse
# from .models import Quiz

# Create your views here.


def register(request):
    # print("Registartion form : ",UserRegisterForm())
    if request.method == "POST":
        form = UserRegisterForm(request.POST)
        if form .is_valid():
            form.save()
            username = form.cleaned_data.get("username")
            print("checking what form.cleaned_data returns for username: ", username)
            messages.success(request, f"Account created for {username}!!")
            return redirect("users_login")
    else:
        form = UserRegisterForm()
        # print("FORM data from Regiter view ", form)
        return render(request, "singup.html", {"form": UserRegisterForm() })
        
@login_required
def profile(request):
    if request.method== "POST":
        u_form = UserUpdateForm(request.POST, instance= request.user)
        p_form = profileUpdateForm(request.POST,
                                   request.FILES,
                                   instance= request.user.profile)
        # print("I'm here in profile , u_form", u_form)
        # print("I'm here in profile p_form: ", p_form)
        
        if u_form.is_valid() and p_form.is_valid():
            u_form.save()
            p_form.save()
            messages.success(request, f"Account updated successfully!!")
            return redirect("user_profile")
        else:
            u_form = UserUpdateForm(instance= request.user)
            p_form = profileUpdateForm(instance=request.user.profile)
            
        context = {
            "u_form": u_form,
            "p_form": p_form
        }
        
        return render(request, "PyQuiz/profile.html", context)
    

class UserLoginView(LoginView):
    form_class = UserLoginForm
    template_name = "PyQuiz/login.html"
    def get_context_data(self, **kwargs):
        ret = super(LoginView, self).get_context_data(**kwargs)
        signup_url = passthrough_next_redirect_url(self.request,
                                                   reverse("users_signup"), # users_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
        
class UserLogoutView(LogoutView):
    template_name = "PyQuiz/logout.html"
    print("*** Template Location** ", template_name)
    def get(self, *args, **kwargs):
        print("**** Arg values : - " , *args)
        print("\n")
        print("NEXT Argunment value")
        print("\n")
        
        print("**** kwargs values *********" , **kwargs)
        
        print("NEXT Argunment value")
        print("\n")
        print("**** Logout values values *********" , self)
        
        
        if app_settings.LOGOUT_ON_GET:
            return self.post(*args, **kwargs)
        if not self.request.user.is_authenticated:
            response = redirect(self.get_redirect_url())
            # print("***Response from UserLogoutView:********* ", response)
            return _ajax_response(self.request, response)
        if self.request.user.is_authenticated:
            self.logout()
        ctx = self.get_context_data()
        response = self.render_to_response(ctx)
        return _ajax_response(self.request, response)
    
    def post(self, *args, **kwargs):
        url = self.get_redirect_url()
        if self.request.user.is_authenticated:
            self.logout()
        response = redirect(url)
        return _ajax_response(self.request, response)
    
    def get_redirect_url(self):
        return (
            get_next_redirect_url(
                self.request,
                self.redirect_field_name or get_adapter(self.request).get_logout_redirect_url(self.request)
            )
        )
    
class UserSignupView(SignupView):
    form_class = UserRegisterForm
    template_name = "PyQuiz/singup.html"
    
    def get(self, *args, **kwargs):
        output = super().get(*args, **kwargs)
        return output
    
    def get_context_data(self, **kwargs):
        ret = super(SignupView, self).get_context_data(**kwargs)
        form = ret["form"]
        email = self.request.session.get("account_verified_email")
        if email:
            email_keys = ["email"]
            if app_settings.SIGNUP_EMAIL_ENTER_TWICE:
                email_keys.append("email2")
                for email_key in email_keys:
                    form.fields[email_keys].initial = email
        login_url = passthrough_next_redirect_url(self.request,
                                                  reverse("users_login"),
                                                  self.redirect_field_name
                                                  )
        redirect_field_name = self.redirect_field_name
        redirect_field_value = get_request_param(self.request,
                                                 redirect_field_name)
        ret.update({"login_url": login_url,
                    "redirect_field_name": redirect_field_name,
                    "redirect_field_value": redirect_field_value})
        ret.update({"login_url": login_url,
                    "redirect_field_name": redirect_field_name,
                    "redirect_field_value": redirect_field_value})
        return ret
    
    def post(self, request, *args, **kwargs):
        output = super().post(request, *args, **kwargs)
        return output

class UserProfileView(UpdateView):
    template_name = "PyQUiz/profil.html"
    # print("I'm at UserProfileview class section")
    def get(self, request, *args, **kwargs):
        u_form = UserUpdateForm(instance=request.user)
        p_form = profileUpdateForm(instance=request.user.profile)
        
        # print("I'm at UserProfileview def section")
        
        context = {
            "u_form": u_form,
            "p_form": p_form
        }
        
        return render(request, "PyQUiz/profile.html", context)
    
    def post(self, request, *args, **kwargs):
        u_form = UserUpdateForm(request.POST, instance=request.user)
        p_form = profileUpdateForm(request.POST,
                                   request.FILES,
                                   instance=request.user.profile
            
        )
        
        if u_form.is_valid() and p_form.is_valid():
            u_form.save()
            p_form.save()
            messages.success(request, f"Account Update Successfully!!!")
            
        return redirect("PyQuiz_profile")

Code from Models.py

from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin # User
from django.utils import timezone

from django.db.models.signals import post_save
from django.dispatch import receiver
from PIL import Image

# Create your models here.

class Address(models.Model):
    name = models.CharField(max_length=30)
    address = models.CharField(max_length=50)
    city = models.CharField(max_length=60, default="")
    state = models.CharField(max_length=30, default="")
    postcode = models.CharField(max_length=6, default="")
    country = models.CharField(max_length=50)
    
    class Meta:
        verbose_name = "Address"
        verbose_name_plural = " Address"
        # app_label = "PyQuiz"
        
    def __str__(self):
        return self.name

class UserManager(BaseUserManager):
    
    def _create_user(self, email, password, is_staff, is_superuser, **extra_fields):
        if not email:
            raise ValueError("Users must have an email address")
        now = timezone.now()
        email = self.normalize_email(email)
        user = self.model(
            email = email,
            is_staff = is_staff,
            is_active = True,
            is_superuser = is_superuser,
            last_login = now, 
            date_joined= now,
            **extra_fields
        )
        user.set_password(password)
        user.save(using=self._db)
        return user
    
    def create_user(self, email, password, **extra_fields):
        return self._create_user(email, password, True, True, **extra_fields)
    
    def create_superuser(self, email, password, **extra_fields):
        user = self._create_user(email, password, True, True, **extra_fields)
        user.save(using= self._db)
        return user
    
    # class Meta:
    #     app_label = "PyQuiz"
    
class User(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(max_length=254, unique=True)
    name = models.CharField(max_length=254, null= True, blank= True)
    username = models.CharField(max_length=254, null=True, blank=True)
    is_staff = models.BooleanField(default=False)
    is_superuser = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    last_login = models.DateTimeField(null=True, blank=True)
    date_joined = models.DateTimeField(auto_now_add=True)
    
    USERNAME_FIELD = "email"
    EMAIL_FIELD = "email"
    REQUIRED_FIELDS = []
    
    objects = UserManager()
    
    def get_absolute_url(self):
        return "/users/%i/" % (self.pk)
    
class Profile(models.Model):
    user = models.OneToOneField(User, unique=True, on_delete=models.CASCADE, default=None)
    address = models.CharField(max_length=254, null=True, blank=True)
    image = models.ImageField(default="default.jpg", upload_to="profile_pics")
    
    def __str__(self):
        return f"{self.user.name} Profile"
    
    def save(self, *args, **kwargs):
        super.save(*args, **kwargs)
        
@receiver(post_save, sender= User)
def create_user_profile(sender, instance, created, **kwargs):
    if created:
        Profile.objects.create(user=instance)

@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwards):
    instance.profile.save()

App urls.py

from django.contrib import admin
from django.urls import path, include
from django.contrib.auth import views as auth_views
from . import views
from .views import UserLoginView, UserLogoutView  # ..PyQuiz.views
from allauth.account.views import login, logout, LogoutView

urlpatterns = [

    path('users/', include('allauth.urls')),
    path("login/", UserLoginView.as_view(template_name="PyQuiz/login.html"), name="users_login"),
    path("signup/", views.register, name="users_signup"),
    path("logout/", UserLogoutView.as_view(template_name="PyQuiz/logout.html"), name="users_logout"),
    path("profile/", views.profile, name="users_profile"),
]

*Project urls.py

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


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

wsgi.py

import os

from django.core.wsgi import get_wsgi_application

import django

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'PyQuiz.settings')

os.environ["DJANGO_ALLOW_ASYNC_UNSAFE"] = "true"

application = get_wsgi_application()

django.setup()

Hello there!
Learning how to read the traceback will help you improve as a developer, if you read it carefully, you would know the possible cause of the issue, based on the error message you received:

Just before this error message on the traceback you have the path that generated this error, in this case, 2 lines above that error. Normally on this situation, you should look on the traceback for your project path, since it’s most likely a problem with a code we wrote. Here’s how you identify your code, on the traceback.

Notice how it’s pointing to a file on your project, differently than this one that’s pointing to the django code on your virtual environment.

You can tell that by this path: /venv/lib/python3.10/site-packages/ that’s not your code.
So, back to the error, on the traceback of your code, you have this line as the last call from your code that generated this error:

It looks like the method get_redirect_url is returning None instead of a proper url (str) to redirect. That’s where you should look at next.

issue is resolved after updating below line in the UserLogoutView Code

Changed below code from

if not self.request.user.is_authenticated

Changed it to

if self.request.user.is_authenticated