0

had a few Python classes and tinkering with an old project. I'm using an API to help the user decide on a recipe to cook. One of the questions is if they have dietary/meal type requirements. The API documentation has parameters for the requirements but I don't know how to make it work if the user has no dietary/meal type requirements. I tried to do an if else statement but PyCharm got confused. This is my code:

import requests


def recipe_search(ingredient, mealtype, dietary):
    # You need to register as a developer with Edamame to get an Application ID and Key
    # These can be found in the applications section of the dashboard once you have signed in
    app_id = "INSERT APP ID"
    app_key = "INSERT APP KEY"
    result = requests.get(
        'https://api.edamam.com/search?q={}&app_id={}&app_key={}&mealType={}&health'.format(ingredient, app_id, app_key,
                                                                                            mealtype, dietary))
    data = result.json()

    return data["hits"]


def run():
    ingredient = input("Enter an ingredient: ")
    mealtype = input(
        "What type of meal do you want? \n Choose from breakfast/lunch/dinner/snack/teatime/any. You can input multiple meals but they must be seperated with commas.")
    dietary = input(
        'Do you have any dietary requirements? \n Choose and enter from vegan/vegetarian/paleo/dairy-free/gluten-free/wheat-free/fat-free/low-sugar/egg-free/peanut-free/tree-nut-free/soy-free/fish-free/shellfish-free. \n You can enter multiple dietary requirements, but they must be seperated with commas.')
    results = recipe_search(ingredient, mealtype, dietary)

    for result in results:
        recipe = result["recipe"]

        print(recipe["label"])
        print(recipe["uri"])
        print()


run()

This is the API that I'm using: https://developer.edamam.com/edamam-docs-recipe-api

Park
  • 2,446
  • 1
  • 16
  • 25

2 Answers2

0

I might suggest building your list of URL params in such a way that any param with an empty value is omitted:

def recipe_search(ingredient, mealtype, dietary):
    params = "&".join(f"{param}={value}" for param, value in {
        'app_id': "INSERT APP ID",
        'app_key': "INSERT APP KEY",
        'q': ingredient,
        'mealType': mealtype,
        'health': dietary,
    }.items() if value)
    return requests.get(f"https://api.edamam.com/search?{params}").json()

That way if the user inputs an empty string, the corresponding param is omitted from the API call completely instead of being sent as an empty string.

Samwise
  • 68,105
  • 3
  • 30
  • 44
  • Thank you so much for your reply, I tried it with my code and unfortunately, I got a TypeError of: string indices must be integers. When filling in my code, I gave answers of any and none to the questions of meal type and dietary requirements. Apologies if I'm asking too much, I'm trying to improve my skills. – user3482176 Feb 16 '22 at 16:21
  • Hard to guess what the problem might be without a full traceback. Maybe the API doesn't return a JSON response? – Samwise Feb 16 '22 at 17:24
  • I'm even more confused because I closed the program, reran it after seeing your advice and now I'm getting a different traceback. This is the new traceback: Traceback (most recent call last): line 33, in run() line 23, in run results = recipe_search(ingredient, mealtype, dietary) line 14, in recipe_search return data["hits"] KeyError: 'hits' I know that the API returns JSON responses because the original code I was given for this project had JSON as well. I have no idea why it has now come up with a different error. – user3482176 Feb 16 '22 at 19:17
  • Looking at the Edamam API plan that I'm on, I may have reached my API call limit, so I can't actually do anything about that – user3482176 Feb 16 '22 at 19:25
  • Sounds like it doesn't return a "hits" key. Maybe just return `request(...).json()` and examine the result to see what it actually contains. – Samwise Feb 16 '22 at 19:25
0

This sounds like a potential use case for the dataclass-wizard:

from dataclasses import dataclass
from dataclass_wizard import asdict, json_field


@dataclass
class RequestParams:
    app_id: str = json_field('app_id', all=True)
    app_key: str = json_field('app_key', all=True)
    q: str = ''
    meal_type: str = ''
    health: str = ''


def recipe_search(ingredient, mealtype, dietary):
    params = RequestParams("INSERT APP ID", "INSERT APP KEY",
                           ingredient, mealtype, dietary)

    return requests.get('https://api.edamam.com/search',
                        params=asdict(params, skip_defaults=True)).json()

Some notes for clarification:

  • The default key transform for serialization is camelCase, so mealType instead of meal_type.
  • skip_defaults is passed here to skip including fields that are blank in the serialized dict object (i.e. fields for which user provided no input)
  • json_field can be thought of as alias to dataclasses.field(). I'm using it here mainly to control the casing of the field in the serialized result.
rv.kvetch
  • 9,940
  • 3
  • 24
  • 53