2

Honestly, I am not sure what question I should ask here. Maybe someone can edit my title to be more descriptive?

I have a python flask app that sometimes returns:

The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.

There is a pattern as to when this happens but I cannot figure out why it happens.

I have a home page where the user clicks a marker on google maps and then clicks a hyperlink "see forecast" button, which takes them to a weather forecast page: enter image description here

In my main python file (equivalent to index.py) I create the route for this next page as follows:

@app.route("/weather_forecast/<climbing_area>/<city_id>/<lat>/<lon>/<weather_site>")    #creates url using climbing area name, city id, lat, lon, and location of weather site
def weather_forecast(climbing_area, city_id, lat, lon, weather_site):

    return render_template('weather_forecast.html', 
                       climbing_area=climbing_area, 
                       city_id=city_id, 
                       daily_forecast=wf.format_daily_forecast(city_id), 
                       extended_forecast=wf.format_extended_forecast(city_id), 
                       historical_forecast=wf.get_historical_weather(lat, lon),
                       dates=wf.get_date_range(),
                       lat=lat,
                       lon=lon,
                       weather_site=weather_site,
                       sites=db.create_site_list_sqlite(),
                       api_key=os.environ.get('GOOGLE_MAPS_JS_API_KEY'),
                       image_url=wf.image_choice(lat, lon, city_id))

So as you see, there are many markers on the map and like 95% of them do the correct thing and go to a weather forecast page upon click. But a few of them do not. They consistently do not work.

The URL for each weather forecast site is dynamically generated by this template:

/weather_forecast/<climbing_area>/<city_id>/<lat>/<lon>/<weather_site>

These are variables returned from the /home page route. My first thought was: because these are dynamically generated variables from the back end (SQLite), maybe there is no data returned for those specific sites and this causes the page to fail? But I have verified for these select few sites that the data is available.

This URL works:

http://localhost:5000/weather_forecast/Humboldt%20County/5558953/41.03/-124.113/Arcata

This URL does not work:

http://localhost:5000/weather_forecast/Mount%20Yonah/Tallulah%20Gorge/4188197/34.637/-83.72200000000001/Clarkesville

I don't expect a magic code fix but can someone advise as to what else I could look for? Or what other information would be helpful to include in my question.

Erich Purpur
  • 1,337
  • 3
  • 14
  • 34

3 Answers3

1

The URL allowed is : /weather_forecast/<climbing_area>/<city_id>/<lat>/<lon>/<weather_site>

You may be trying to access the URL:

/weather_forecast/<climbing_area>/<city_id>/<lat>/<lon>/<weather_site>/

There's a slash in the end of the URL. Since the URL in the flask code doesn't have the slash in the end, it will throw the error.

Also, please post the URL that you're hitting. That'll help providing more accurate solutions.

Anuj Gupta
  • 576
  • 5
  • 9
1

i guess, you need to set the right field and the right precision to store google maps lat and lon as per this thread

in your model try this:

..

    lat = db.Column(db.Numeric(22, 16), nullable=False)
    lon = db.Column(db.Numeric(22, 16), nullable=False)

# or 

    lat = db.Column(db.DECIMAL(22, 16), nullable=False)
    lon = db.Column(db.DECIMAL(22, 16), nullable=False)

..

and i want to suggest you reviewing the code of weather_forecast() function, it returns a data that can be calculated in weather_forecast.html template using the same parameters like image_url

@app.route("/weather_forecast/<climbing_area>/<city_id>/<lat>/<lon>/<weather_site>")
def weather_forecast(climbing_area, city_id, lat, lon, weather_site):

..
    sites=db.create_site_list_sqlite()

..
    return render_template('weather_forecast.html', 
                       climbing_area=climbing_area, 
                       city_id=city_id, 
                       lat=lat,
                       lon=lon,
                       weather_site=weather_site,

                       sites=sites,  # to keep things coherent 
                       
                       wf=wf)

instead of sending

                       daily_forecast=wf.format_daily_forecast(city_id), 
                       extended_forecast=wf.format_extended_forecast(city_id), 
                       historical_forecast=wf.get_historical_weather(lat, lon),
                       dates=wf.get_date_range(),
                       image_url=wf.image_choice(lat, lon, city_id)

just send the wf object and in weather_forecast.html template just use it like:

<img src="{{ wf.image_choice(lat, lon, city_id) }}" atl="">

also you don't need to send api_key since you can get it directly from global config object in your template like

{{ config.GOOGLE_MAPS_JS_API_KEY }}
cizario
  • 3,995
  • 3
  • 13
  • 27
  • i'm sorry im mixing between django and flask models.DecimalField, i will update my answer , i used that code in my django project so i have just adapt the idea with flask with the right moeld field – cizario Jul 05 '20 at 13:57
  • thank you, why is is better to do this: `` instead of what I was previously doing? – Erich Purpur Jul 06 '20 at 12:52
  • 1
    with **less is more** in mind you can achieve more with **just essential** parameters passed to `render_templates()`, you have 5 parameters (`daily_forecast`, `extended_forecast`, `historical_forecast`, `dates` and `image_url`) that can be "reduced" to 1 parameter `wf`` besides they need (`city_id`, `lat`, `lon` and `weather_site`) already passed to the function. – cizario Jul 06 '20 at 13:08
0

I found the solution. It turns out I was passing a bad URL without knowing it.

This URL worked: http://localhost:5000/weather_forecast/Humboldt%20County/5558953/41.03/-124.113/Arcata

This URL did not work: http://localhost:5000/weather_forecast/Mount%20Yonah/Tallulah%20Gorge/4188197/34.637/-83.72200000000001/Clarkesville

The difference is this, in my weather_forecast() function, I created my route like this: @app.route("/weather_forecast/<climbing_area>/<city_id>/<lat>/<lon>/<weather_site>")

The reason why just a few of my sites (and URLs) failed is because the <climbing_area> variable had a / character in it, in the database record. So for example if the <climbing_area> = Mount Yonah/Tallulah Gorge, this added an extra / character into my URL, causing it to fail.

I could have figured out how to make flask accept the literal / character. But in this case I just changed my <climbing_area> names to remove the /. Problem solved.

Erich Purpur
  • 1,337
  • 3
  • 14
  • 34