AttributeError at /map/ 'NoneType' object has no attribute 'delete'

Hi, inside my urls.py file I have the following code:

from django.urls import path
from . import views

urlpatterns = [
    path('map/', views.DisplayMap, name='DisplayMap'),
]

I am getting the following error when trying to access http://127.0.0.1:8000/map/:

AttributeError at /map/

'NoneType' object has no attribute 'delete'

I have the following views.py file for an application called “map_app”:

from django.shortcuts import render, redirect
from django.http import HttpResponse
from .models import MapDatabase
from .forms import MapDataForm
import folium
import geocoder

# Create your views here.


def DisplayMap(request):
    if request.method == 'POST':
        mapForm = MapDataForm(request.POST)

        if mapForm.is_valid():
            mapForm.save()
            return redirect('/')
    else:
        mapForm = MapDataForm()

    address = MapDatabase.objects.all().last()
    location = geocoder.osm(address)

    lat = location.lat
    lng = location.lng

    country = location.country

    if lat == None or lng == None:
        address.delete() # **This is where I believe the problem is.**
        return HttpResponse('Your search input was invalid.')

    # Here there is a map object.
    mapObject = folium.Map(location=[19, -12], zoom_start=2)

    folium.Marker([latitude, longitude], tooltip='Click for description',
                  popup=country).add_to(mapObject)

    mapObject = mapObject._repr_html_()

    content = {
        'mapObject': mapObject,
        'mapForm': mapForm,
    }

    return render(request, 'map_app/DisplayMap.html', content)

Please provide any input in how I can resolve this problem. Thank you all.

Do you have data in your MapDatabase model?

If you run that query (MapDatabase.objects.all().last()) in the Django shell, what do you get?

Hi Mr. Whitesell.

I executed “python manage.py shell” in the SeniorProject → django_project directory where the manage.py file is located.

Then, I executed (MapDatabase.objects.all().last()) as well as MapDatabase.objects.all().last().
One with the parentheses and one without, but the result was still “NameError: name ‘MapDatabase’ is not defined” in both cases.
MapDatabase

The following code is inside my map_app → models.py file:

from django.db import models

# Create your models here.


class MapDatabase(models.Model):
    address = models.CharField(max_length=200, null=True)
    data = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.address

You need to import your models when you use the shell. See Writing your first Django app, part 2 | Django documentation | Django for an example.

1 Like

Yes Mr. Whitesell! Thank you for your help with this. After creating a object of “MapDatabase” within the admins page, I no longer get that same error. I appreciate all of your help.

For some reason though, when I click on the “Search” button on another web page, it takes me back to the http://127.0.0.1:8000/ page in my Django app. Why is this?

Instead, I want the correct location to be shown on the international map of the world.

After typing in “Rome” in the Search bar on the top right of the web page, the following image display what we should see:

The following is the code for the “Search” button inside DisplayMap.html file:

<form class="form-inline my-2 my-lg-0" method="POST">
            <!--The csrf_token is added for security.-->
            {% csrf_token %}
            {{ mapForm|crispy }}
            <button class="btn btn-outline-success my-2 my-sm-0 mx-4" type="submit">Search</button>
          </form>

This is on line 41 in the image below.

The following is the DisplayMap.html file:

{% load crispy_forms_tags %}
<!doctype html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" 
          href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css" 
          integrity="sha384-zCbKRCUGaJDkqS1kPbPd7TveP5iyJE0EjAuZQTgFLD2ylzuqKfdKlfG/eSrtxUkn" 
          crossorigin="anonymous">

    <title>Map Home Page</title>
  </head>
  <body>
    <!--Navigation Bar-->
    <nav class="navbar navbar-expand-lg navbar-light bg-light">
        <a class="navbar-brand" href="#">Geographical World Map</a>
        <button class="navbar-toggler" type="button" data-toggle="collapse" 
          data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" 
          aria-expanded="false" aria-label="Toggle navigation">
          <span class="navbar-toggler-icon"></span>
        </button>
      
        <div class="collapse navbar-collapse" id="navbarSupportedContent">
          <ul class="navbar-nav mr-auto">
            <li class="nav-item active">
              <a class="nav-link" href="{% url 'DisplayMap' %}">Global Map 
                <span class="sr-only">(current)</span></a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#">Link</a>
            </li>
          </ul>
          <form class="form-inline my-2 my-lg-0" method="POST">
            <!--The csrf_token is added for security.-->
            {% csrf_token %}
            {{ mapForm|crispy }}
            <button class="btn btn-outline-success my-2 my-sm-0 mx-4" type="submit">Search</button>
          </form>
        </div>
      </nav>

    <div class="container">
        <div class="row mt-4">
            <div class="col-md-10 offset-md-1">
                {{ mapObject|safe }}
            </div>
        </div>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js" 
            integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" 
            crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js" 
            integrity="sha384-fQybjgWLrvvRgtW6bFlB7jaZrFsaBXjsOMm/tB9LTS58ONXgqbR9W8oWht/amnpF" 
            crossorigin="anonymous"></script>
  </body>
</html>

And the following is the views.py file:

from django.shortcuts import render, redirect
from django.http import HttpResponse
from .models import MapDatabase
from .forms import MapDataForm
import folium
import geocoder

# Create your views here.


def DisplayMap(request):
    if request.method == 'POST':
        mapForm = MapDataForm(request.POST)

        if mapForm.is_valid():
            mapForm.save()
            return redirect('/')
    else:
        mapForm = MapDataForm()

    # For the following line to work, we must have at least one 'MapDatabase' object.
    address = MapDatabase.objects.all().last()
    location = geocoder.osm(address)

    latitude = location.lat
    longitude = location.lng

    country = location.country

    if latitude == None or longitude == None:
        address.delete()
        return HttpResponse('Your search input was invalid.')

    # Here there is a map object.
    mapObject = folium.Map(location=[19, -12], zoom_start=2)

    folium.Marker([latitude, longitude], tooltip='Click for description',
                  popup=country).add_to(mapObject)

    mapObject = mapObject._repr_html_()

    content = {
        'mapObject': mapObject,
        'mapForm': mapForm,
    }

    return render(request, 'map_app/DisplayMap.html', content)

Please let me know what you would suggest for my latest post. Thank you.

It’s this line in your view that is causing that behavior:

You go on to say:

So then your redirect needs to send you to the URL that will call the view that will do that.

Just fixed it! Thank you very much for explaining Mr. Whitesell!

In general, what does return redirect(’/’) mean?

You tell me, what does the redirect function do?

The redirect() function redirects the user to another page.

However, I am not quite sure what redirect(‘/’) will do? Does this redirect the user to the home page of a Django application? Or does this redirect a user to the previous page in a Django application?

From testing this, I would have to say that return redirect(‘/’) will redirect the user to the home page of the Django application. Please let me know if I am correct.

Yes, you are correct. If you specify a url in the redirect call, it takes you directly to that url - in this case, the root url of the site.

(Side note: If your Django application is running in an environment where it’s mounted under a different directory name, ‘/’ might not be the home page of that application.)

Okay. Thank you sir.