Esempio n. 1
0
def profile(username):
    """
    User Profile Page.

    Users can view their own recipes, view their saved recipes from others,
    update their password, or delete their account.
    """
    username = get_user_lower(session["user"])["username"]
    # find all recipes belonging to user
    user = get_user_lower(session["user"])["_id"]
    user_recipes = recipes_collection.find({"author": user})\
        .sort([("recipe_name", 1)])
    # find all recipes that the user saved
    user_favs_list = get_user_lower(session["user"])["user_favs"]
    user_favs = recipes_collection.find({"_id": {"$in": user_favs_list}})\
        .sort([("recipe_name", 1)])
    # get the user's avatar
    user_avatar = get_user_lower(session["user"])["user_avatar"]
    # ADMIN-only: get list of all database users
    admin_list = users_collection.find().sort([("username", 1)])
    return render_template("profile.html",
                           username=username,
                           user_recipes=user_recipes,
                           user_favs=user_favs,
                           user_avatar=user_avatar,
                           admin_list=admin_list)
Esempio n. 2
0
def admin_delete_user(username):
    """
    ADMIN: Delete users if necessary.

    The ADMIN account has option to delete users from database if it needs to.
    This would delete all of that user's recipes, too.
    """
    user = get_user_lower(username)
    # find all recipes belonging to user being deleted
    user_recipes = [recipe for recipe in user.get("user_recipes")]
    # for each user recipe, remove it from database and pull from others' favs
    for recipe in user_recipes:
        recipes_collection.remove({"_id": recipe})
        users_collection.update_many({}, {"$pull": {"user_favs": recipe}})
    # find all recipes that the user saved
    user_favs = [recipe for recipe in user.get("user_favs")]
    # decrement each recipe the user liked by -1
    for recipe in user_favs:
        recipes_collection.update_one({"_id": recipe},
                                      {"$inc": {
                                          "user_favs": -1
                                      }})
    flash(
        Markup(f"<i class='fas fa-user-times red-text'></i>\
        User has been successfully deleted."))
    # delete the user from database using .remove()
    users_collection.remove({"_id": user.get("_id")})
    return redirect(url_for("users.profile", username="******"))
Esempio n. 3
0
def profile_change_password(username):
    """
    Update user hashed password.

    Each user has the option to update their password.
    User must first verify their current password though.
    """
    user = get_user_lower(session["user"])
    # check if stored hashed password matches current password in form
    if check_password_hash(user["user_password"],
                           request.form.get("current_password")):
        flash(
            Markup(f"<i class='far fa-check-circle green-text'></i>\
            Your password has been updated successfully!"))
        users_collection.update_one(
            {"username_lower": session["user"].lower()}, {
                "$set": {
                    "user_password":
                    generate_password_hash(request.form.get("new_password"))
                }
            })
    else:
        # password does not match
        flash(
            Markup(f"<i class='fas fa-exclamation-circle red-text'></i>\
            Whoops! Looks like your <span class='pink-text text-lighten-2'>\
            password</span> is incorrect. Please try again."))
    # redirect back to profile
    return redirect(url_for("users.profile", username=username))
Esempio n. 4
0
def desserts_delete(recipe_id, slugUrl):
    """
    Delete recipe from database.

    Remove the recipe from the collection, pull the recipe from the
    user's recipe list, and pull the recipe from all other users' favorites.
    """
    if "user" in session:  # users must be logged in
        recipe = get_recipe(recipe_id)
        session_user = get_user_lower(session["user"])["username"]
        recipe_author = users_collection.find_one(
            {"_id": ObjectId(recipe.get("author"))})["username"]
        # check that someone isn't brute-forcing the url to delete recipes
        if session_user == recipe_author or session_user == "Admin":
            author = users_collection.find_one_and_update(
                {"_id": ObjectId(recipe.get("author"))},
                {"$pull": {"user_recipes": ObjectId(recipe_id)}})
            users_collection.update_many(
                {}, {"$pull": {"user_favs": ObjectId(recipe_id)}})
            recipes_collection.remove({"_id": ObjectId(recipe_id)})
            flash(Markup(
                f"<i class='fas fa-trash-alt red-text'></i>\
                Your recipe has been deleted."))
        else:
            flash(Markup(
                f"<i class='far fa-sad-tear yellow-text'></i>\
                You are not authorized to delete this recipe!"))
    else:  # no user in session
        flash(Markup(
            f"<i class='far fa-sad-tear yellow-text'></i>\
            You must be logged in to delete this recipe."))
    return redirect(url_for("recipes.desserts"))
Esempio n. 5
0
def profile(username):
    """
    User Profile Page.

    Users can view their own recipes, view their saved recipes from others,
    update their password, or delete their account.
    """
    username = get_user_lower(session["user"])["username"]
    # find all recipes belonging to user
    user = get_user_lower(session["user"])["_id"]
    user_recipes = recipes_collection.find({"author": user})\
        .sort([("recipe_name", 1)])
    # find all recipes that the user saved
    user_favs_list = get_user_lower(session["user"])["user_favs"]
    user_favs = recipes_collection.find({"_id": {"$in": user_favs_list}})\
        .sort([("recipe_name", 1)])
    # get the user's avatar
    user_avatar = get_user_lower(session["user"])["user_avatar"]
    # ADMIN-only: get list of all database users and visitors
    admin_list = users_collection.find().sort([("_id", 1)])
    date_joined = [user["_id"].generation_time.date().strftime(
        "%d %b %Y") for user in deepcopy(admin_list)]
    zip_data = zip(admin_list, date_joined)
    visitors = list(visitors_collection.find())
    # get total views and total views by grouped country
    total_views = list(visitors_collection.aggregate([
        {"$facet": {
            "total": [
                {"$group": {"_id": "", "total": {"$sum": "$visits"}}}
            ],
            "countries": [
                {"$group": {"_id": "$country", "total": {"$sum": "$visits"}}}
            ]
        }}
    ]))
    # end ADMIN-ONLY section
    return render_template(
        "profile.html",
        username=username,
        user_recipes=user_recipes,
        user_favs=user_favs,
        user_avatar=user_avatar,
        admin_list=admin_list,
        date_joined=date_joined,
        zip_data=zip_data,
        visitors=visitors,
        total_views=total_views)
Esempio n. 6
0
def logout():
    """ Remove the user from 'Session' cookies with session.pop(). """
    username = get_user_lower(session["user"])["username"]
    flash(
        Markup(f"<i class='far fa-sad-tear yellow-text'></i>\
        Missing you already, <span class='pink-text text-lighten-2 bold'>" +
               username + "</span>!"))
    session.pop("user")
    return redirect(url_for("main.home"))
Esempio n. 7
0
def profile_delete_account(username):
    """
    Delete entire user account if desired.

    Each user has the option to delete their account.
    This would delete all of their recipes, too.
    """
    user = get_user_lower(session["user"])
    # check if stored hashed password matches current password in form
    if check_password_hash(user["user_password"],
                           request.form.get("verify_password")):
        # find all recipes belonging to user
        user_recipes = [recipe for recipe in user.get("user_recipes")]
        # for each user recipe, remove from database and pull from others' favs
        for recipe in user_recipes:
            recipes_collection.remove({"_id": recipe})
            users_collection.update_many({}, {"$pull": {"user_favs": recipe}})
        # find all recipes that the user saved
        user_favs = [recipe for recipe in user.get("user_favs")]
        # decrement each recipe the user liked by -1
        for recipe in user_favs:
            recipes_collection.update_one({"_id": recipe},
                                          {"$inc": {
                                              "user_favs": -1
                                          }})
        flash(
            Markup(f"<i class='fas fa-user-times red-text'></i>\
            Your account and recipes have been successfully deleted."))
        # remove user from session cookies and delete user from database
        session.pop("user")
        users_collection.remove({"_id": user.get("_id")})
        return redirect(url_for("main.home"))

    else:
        # password does not match, so redirect back to profile
        flash(
            Markup(f"<i class='fas fa-exclamation-circle red-text'></i>\
            Whoops! Looks like your <span class='pink-text text-lighten-2'>\
            password</span> is incorrect. Please try again."))
        return redirect(url_for("users.profile", username=username))
Esempio n. 8
0
def login():
    """
    Log In to user account.

    Authentication and Authorization checks that user exists, user hashed
    password matches, then logs in to account if all successful.
    """
    if request.method == "POST":
        # check if username is in database
        existing_user = get_user_lower(request.form.get("username"))
        if existing_user:
            # ensure hashed password matches user input
            if check_password_hash(existing_user["user_password"],
                                   request.form.get("password")):
                session["user"] = request.form.get("username").lower()
                return redirect(
                    url_for("users.profile", username=session["user"]))
            else:
                # invalid password match
                flash(
                    Markup(
                        f"<i class='fas fa-exclamation-circle red-text'></i>\
                    Whoops! Looks like the\
                    <span class='pink-text text-lighten-2'>username</span>\
                    or <span class='pink-text text-lighten-2'>password</span>\
                    is incorrect."))
                return redirect(url_for("users.login"))
        else:
            # username doesn't exist
            flash(
                Markup(f"<i class='fas fa-exclamation-circle red-text'></i>\
                    Hmm... username <span class='pink-text text-lighten-2'>\
                    {request.form.get('username')}</span>\
                    doesn't seem to exist."))
            return redirect(url_for("users.login"))
    return render_template("log_reg.html")
Esempio n. 9
0
def register():
    """
    Register a new account.

    Authentication and Authorization checks that user does not already exist,
    username does not contain 'test' or most special characters, length of
    username and password, and assigns an avatar from a list of 16 avatars.
    """
    if request.method == "POST":
        # check if username already taken
        existing_user = get_user_lower(request.form.get("new_username"))
        if existing_user:
            flash(
                Markup(f"<i class='fas fa-exclamation-circle red-text'>\
            </i> <span class='pink-text text-lighten-2'>\
            {request.form.get('new_username')}</span>\
            is an excellent choice! (but it's already taken)"))
            return redirect(url_for("users.register"))
        # check if username is alphanumeric or contains 'test'
        username_input = request.form.get("new_username").lower()
        username_check = re.search(r"(?!\-)[\W]|t+e+s+t+", username_input,
                                   re.I)
        if username_check:
            if " " in {username_check.group(0)}:
                flash(
                    Markup(
                        f"<i class='fas fa-exclamation-circle red-text'></i>\
                    Usernames containing\
                    <span class='pink-text text-lighten-2'>spaces</span>\
                    are not permitted."))
                return redirect(url_for("users.register"))
            else:
                flash(
                    Markup(
                        f"<i class='fas fa-exclamation-circle red-text'></i>\
                    Usernames containing\
                    <span class='pink-text text-lighten-2'>\
                    {username_check.group(0).upper()}</span>\
                    are not permitted."))
                return redirect(url_for("users.register"))
        # username should be 3-5 alphanumeric
        if len(request.form.get("new_username")) < 3 or len(
                request.form.get("new_username")) > 15:
            flash(
                Markup(f"<i class='fas fa-exclamation-circle red-text'></i>\
                Usernames should be <span class='pink-text text-lighten-2'>\
                3-15 characters</span> long."))
            return redirect(url_for("users.register"))
        # password should be 5-15 characters
        if len(request.form.get("new_password")) < 5 or len(
                request.form.get("new_password")) > 15:
            flash(
                Markup(f"<i class='fas fa-exclamation-circle red-text'></i>\
                Passwords should be <span class='pink-text text-lighten-2'>\
                5-15 characters</span> long."))
            return redirect(url_for("users.register"))
        # assign random avatar to user
        avatars = [
            "birthday-cake", "cherry-cake", "cherry-flan", "flan",
            "ice-lolly-bear", "ice-lolly-panda", "lemon-pie", "macaroon-blue",
            "macaroon-green", "macaroon-pink", "mousse-pie",
            "neapolitan-torte", "raspberry-cheesecake",
            "raspberry-chocolate-cream-cake", "strawberry-cream-pie",
            "tiramisu-mousse"
        ]
        user_avatar = random.choice(avatars)
        # add successful user to database
        register = {
            "username":
            request.form.get("new_username"),
            "username_lower":
            request.form.get("new_username").lower(),
            "user_password":
            generate_password_hash(request.form.get("new_password")),
            "user_avatar":
            user_avatar,
            "user_recipes": [],
            "user_favs": []
        }
        users_collection.insert_one(register)
        # put the user in 'session'
        session["user"] = request.form.get("new_username").lower()
        return redirect(url_for("users.profile", username=session["user"]))
    return render_template("log_reg.html")
Esempio n. 10
0
def desserts_new():
    """
    Create recipe for database.

    Inject all form data to new recipe document on submit.
    """
    if request.method == "GET":
        allergen_list = dropdown_allergens()
        dessert_list = dropdown_dessert_type()
        measurement_list = dropdown_measurement()
        return render_template(
            "desserts_new.html",
            allergens=allergen_list,
            desserts=dessert_list,
            measurements=measurement_list)

    if request.method == "POST":
        # get today's date and date recipe was last edited
        today = datetime.now().strftime("%d %B, %Y")
        last_edit = int(datetime.now().strftime("%Y%m%d"))
        # get user / author details
        session_user = get_user_lower(session["user"])["username"]
        author = users_collection.find_one({"username": session_user})["_id"]
        # get and convert total time
        hours = int(request.form.get(
            "total_hrs")) * 60 if request.form.get(
                "total_hrs") else ""
        total_time = int(request.form.get(
            "total_mins")) + hours if hours else int(request.form.get(
                "total_mins"))
        # slugify url to be user-friendly
        slugUrl = slugify(request.form.get("recipe_name"))
        # get form data prior to submitting
        submit = {
            "recipe_name": request.form.get("recipe_name"),
            "recipe_slug": slugUrl,
            "description": request.form.get("description"),
            "dessert_type": request.form.get("dessert_type"),
            "ingredient_amount": request.form.getlist("ingredient_amount"),
            "ingredient_measurement": request.form.getlist(
                "ingredient_measurement"),
            "ingredient_name": request.form.getlist("ingredient_name"),
            "directions": request.form.getlist("directions"),
            "total_hrs": request.form.get("total_hrs"),
            "total_mins": request.form.get("total_mins"),
            "total_time": total_time,
            "allergens": request.form.getlist("allergens"),
            "img_src": request.form.get("img_src"),
            "author": author,
            "date_added": today,
            "date_updated": today,
            "last_edit": last_edit,
            "views": 0,
            "user_favs": 0
        }
        # get the new _id being created on submit
        newID = recipes_collection.insert_one(submit)
        # add recipe _id to user's recipe list
        users_collection.update_one(
            {"_id": ObjectId(author)},
            {"$push": {"user_recipes": newID.inserted_id}})
        flash(Markup(
            f"<i class='far fa-check-circle green-text'></i>\
                Sounds delicious! Thanks for adding this recipe!"))
        # if selected, add recipe to user-favs as well
        if request.form.get("add_favs"):
            users_collection.update_one(
                {"_id": ObjectId(author)},
                {"$push": {"user_favs": newID.inserted_id}})
            # increase number of favorites on this recipe by +1
            recipes_collection.update_one(
                {"_id": newID.inserted_id},
                {"$inc": {"user_favs": 1}})

        # # send me an email when a recipe gets added (personal backup)
        # msg = MIMEMultipart()
        # msg["From"] = MY_ADDRESS
        # msg["To"] = SEND_TO
        # msg["Subject"] = "2BN-Desserts | New Recipe Added: " + slugUrl
        # formatEmail = "<br><br>".join(["%s: %s" % kv for kv in submit.items()])
        # msg.attach(MIMEText(str(formatEmail), "html"))  # must convert to str()
        # smtpserver = smtplib.SMTP("smtp.gmail.com", 587)  # access server
        # smtpserver.ehlo()  # identify ourselves to smtp gmail client
        # smtpserver.starttls()  # secure our email with tls encryption
        # smtpserver.ehlo()  # re-identify ourselves as an encrypted connection
        # smtpserver.login(MY_ADDRESS, PASSWORD)  # login to the server
        # smtpserver.send_message(msg)  # send the message
        # smtpserver.quit()  # quit the server

        # add recipe to admin's profile as back-up (in lieu of email)
        users_collection.update_one(
            {"username": "******"},
            {"$push": {"new_recipes": submit}})

        return redirect(url_for(
            "recipes.desserts_recipe",
            recipe_id=newID.inserted_id,
            slugUrl=slugUrl))
Esempio n. 11
0
def desserts_recipe(recipe_id, slugUrl):
    """
    Read recipe in database.

    Gather details from document for displaying to user.
    """
    recipe = get_recipe(recipe_id)
    author = users_collection.find_one(
        {"_id": ObjectId(recipe.get("author"))})["username"]
    user_avatar = users_collection.find_one(
        {"_id": ObjectId(recipe.get("author"))})["user_avatar"]
    amounts = recipe.get("ingredient_amount")
    measurements = recipe.get("ingredient_measurement")
    ingredients = recipe.get("ingredient_name")
    amount = []
    measurement = []
    units = []
    """
    if amount contains valid unicode fraction, convert it
    (ie: input 1/2 converts to &frac12; for display)
    """
    fractions = (
        ["1/2", "1/3", "1/4", "1/5", "1/6", "1/8", "2/3", "2/5",
            "3/4", "3/5", "3/8", "4/5", "5/6", "5/8", "7/8"])
    for num in amounts:
        if "/" in num:
            if any(frac in num for frac in fractions):
                frac_match = re.match(r"^(.*?)(\d\/\d)(.*?)$", num)
                new_num = (
                    frac_match.group(1) + "&frac" +
                    re.sub("/", "", frac_match.group(2)) +
                    ";" + frac_match.group(3))
                amount.append(html.unescape(new_num))
            else:
                amount.append(num)
        else:
            amount.append(num)
    # only display the abbreviated unit of measurement
    for unit in measurements:
        units.append(unit)
        match = re.search(r"\(([a-zA-Z]+)\)$", unit)
        if match:
            measurement.append(match.group(1))
        else:
            measurement.append(unit)
    # zip ingredient items into single full_ingredient
    full_ingredient = zip(amount, measurement, ingredients)
    # get user favorites (if available)
    try:
        user_favs = get_user_lower(session["user"])["user_favs"]
    except:
        user_favs = []
    # increment number of views by +1
    recipes_collection.update_one(
        {"_id": ObjectId(recipe_id)}, {"$inc": {"views": 1}})

    """
    Display Recommendations:
    Get the Previous and Next recipes in collection to display.
    If currently on last document, then get the first document for display.
    If currently on first document, then get the last document for display.
    """
    first_recipe = recipes_collection.find().sort("_id", 1).limit(1)
    last_recipe = recipes_collection.find().sort("_id", -1).limit(1)
    previous_recipe = recipes_collection.find(
        {"_id": {"$lt": ObjectId(recipe_id)}})\
        .sort([("_id", -1)])\
        .limit(1) if str(recipe_id) != str(first_recipe[0]["_id"])\
        else last_recipe
    next_recipe = recipes_collection.find(
        {"_id": {"$gt": ObjectId(recipe_id)}})\
        .sort([("_id", 1)])\
        .limit(1) if str(recipe_id) != str(last_recipe[0]["_id"])\
        else first_recipe
    return render_template(
        "desserts_recipe.html",
        recipe=recipe,
        full_ingredient=full_ingredient,
        units=units,
        author=author,
        user_favs=user_favs,
        user_avatar=user_avatar,
        previous_recipe=previous_recipe,
        next_recipe=next_recipe)
Esempio n. 12
0
def desserts():
    """
    Read all recipes from database.

    Display all recipes initially, with option to Search.
    Search function works by reading url args for existing data.
    """
    # show correct authors on cards
    authors = [author for author in users_collection.find({}, {"username": 1})]
    # dropdowns for search
    allergen_list = dropdown_allergens()
    dessert_list = dropdown_dessert_type()

    # arg variables
    args = request.args.get
    args_list = request.args.getlist

    # URL args : search / sort / order / pagination
    search_keyword_args = args(str(
        "search_keyword")) if args(str(
            "search_keyword")) else ""
    search_dessert_args = args(str(
        "search_dessert")) if args(str(
            "search_dessert")) else ""
    search_allergen_args = args_list(
        "search_allergen") if args_list(
            "search_allergen") else []
    sort_args = args(str("sort")) if args(str("sort")) else "recipe_name"
    order_args = int(args("order")) if args("order") else 1
    page_args = int(args("page")) if args("page") else 1
    limit_args = int(args("limit")) if args(
        "limit") else int(args("limit")) if args("limit") else 12

    # prepare form data for searching
    search_keyword = (
        search_keyword_args.split() if search_keyword_args is not None else "")
    search_dessert = (
        search_dessert_args if search_dessert_args is not None else "")
    search_allergen = (
        search_allergen_args if search_allergen_args != [] else "")

    # pagination settings for sorting
    all_recipes_count = (
        range(1, (math.ceil(recipes_collection.count() / limit_args)) + 1))
    all_recipes_pages = [page for page in all_recipes_count]
    previous_page = page_args - 1 if page_args != 1 else 1
    next_page = (
        page_args + 1 if page_args < all_recipes_pages[-1] else page_args)

    # show results - without search
    sorting = recipes_collection.find().sort(
        [(sort_args, order_args)])\
        .skip((page_args * limit_args) - limit_args)\
        .limit(limit_args)

    # string search items together and search
    new_search = (
        '"' + '" "'.join(search_keyword) + '" "' +
        ''.join(search_dessert) + '"' + ' -' + ' -'.join(search_allergen))
    if not search_keyword and not search_dessert and not search_allergen:
        search_results = ""
    else:
        if not args("limit"):
            # get all results on single page if user selects 'All'
            search_results = recipes_collection.find(
                {"$text": {"$search": new_search}})\
                .sort([(sort_args, order_args)])
        else:
            # otherwise, get the limit they've selected, or the default of 12
            search_results = recipes_collection.find(
                {"$text": {"$search": new_search}})\
                .sort([(sort_args, order_args)])\
                .skip((page_args * limit_args) - limit_args)\
                .limit(limit_args)

    # get search results count
    results_count = search_results.count() if search_results else ""

    # pagination for search
    search_recipes_count = (
        range(1, (math.ceil(int(
            results_count) / limit_args)) + 1) if results_count else "")
    search_recipes_pages = ([
        page for page in search_recipes_count] if search_recipes_count else "")

    # get the next page variables
    if not search_recipes_pages or search_recipes_pages == []:
        next_page_search = ""
    else:
        next_page_search = (
            page_args +
            1 if page_args < search_recipes_pages[-1] else page_args)

    # get total of recipes to display per page
    # (without search)
    count_display = (
        page_args * limit_args if (
            page_args * limit_args) < sorting.count() else sorting.count())
    # (with search)
    if not search_results:
        count_display_search = ""
    else:
        count_display_search = (
            page_args * limit_args if (
                page_args * limit_args) < search_results.count(
                ) else search_results.count())

    """
        Get visitor's IP and Location for Admin tracking.
        Get last item in 'X-Forwarded-For' list to avoid
        getting the Heroku server IP address instead
        https://stackoverflow.com/a/37061471
    """
    # https://stackoverflow.com/a/35123097 (excellent!!)
    # http://httpbin.org/ip | http://icanhazip.com
    # https://ipapi.co/json/ or https://ipapi.co/<ip>/json/ (10k/mo)
    # https://ipinfo.io/json or https://ipinfo.io/<ip>/json (1k/day)

    # check if guest or registered user
    username = get_user_lower(
        session["user"])["username"] if "user" in session else "guest"

    if os.environ.get("DEVELOPMENT"):
        # local development
        url = "https://ipapi.co/json/"
        response = requests.get(url).json()
        client_ip = response["ip"]
    else:
        # live server on Heroku
        client_ip = request.access_route[-1]
        url = "https://ipapi.co/" + client_ip + "/json/"
        url2 = "https://ipinfo.io/" + client_ip + "/json"
        response = requests.get(url).json()

    if response:
        datetimenow = datetime.now().strftime("%d %B, %Y @ %H:%M")
        pattern = "^\-?[0-9]*\.?[0-9]*$"
        lat = str(response["latitude"])
        lon = str(response["longitude"])
        if bool(
            re.match(rf"{pattern}", lat)) and bool(
                re.match(rf"{pattern}", lon)):
            latitude = lat
            longitude = lon
            proceed = True
        else:
            response2 = requests.get(url2).json()
            if response2:
                latitude = str(response2["loc"].split(",")[0])
                longitude = str(response2["loc"].split(",")[1])
                proceed = True
        # check if existing ip visitor already exists
        if proceed and visitors_collection.count_documents(
                {"ip": client_ip}, limit=1) == 0:
            visitor = {
                "ip": client_ip,
                "username": username,
                "city": response["city"],
                "region": response["region"],
                "country": response["country_name"],
                "iso2": response["country_code"].lower(),
                "iso3": response["country_code_iso3"].lower(),
                "latitude": latitude,
                "longitude": longitude,
                "timezone": response["timezone"],
                "utc_offset": response["utc_offset"],
                "datetime": [datetimenow],
                "visits": 1
            }
            visitors_collection.insert_one(visitor)
        elif proceed:
            # update username from guest to session user if logged in
            user = visitors_collection.find_one({"ip": client_ip})["username"]
            username = user if user != "guest" else username
            # if existing visitor ip, then increment their view count
            visitors_collection.update_one(
                {"ip": client_ip},
                {"$push": {"datetime": datetimenow},
                    "$set": {"username": username},
                    "$inc": {"visits": 1}})

    # render results on page and pass all data to template
    return render_template(
        "desserts.html",
        recipes_start=sorting,
        recipes_search=search_results,
        authors=authors,
        allergens=allergen_list,
        desserts=dessert_list,
        search_keyword_args=search_keyword_args,
        search_dessert_args=search_dessert_args,
        search_allergen_args=search_allergen_args,
        sort_args=sort_args,
        order_args=order_args,
        limit_args=limit_args,
        all_recipes_pages=all_recipes_pages,
        search_recipes_pages=search_recipes_pages,
        previous_page=previous_page,
        next_page=next_page,
        next_page_search=next_page_search,
        results_count=results_count,
        page_args=page_args,
        count_display=count_display,
        count_display_search=count_display_search)
Esempio n. 13
0
def desserts_new():
    """
    Create recipe for database.

    Inject all form data to new recipe document on submit.
    """
    if request.method == "GET":
        allergen_list = dropdown_allergens()
        dessert_list = dropdown_dessert_type()
        measurement_list = dropdown_measurement()
        return render_template("desserts_new.html",
                               allergens=allergen_list,
                               desserts=dessert_list,
                               measurements=measurement_list)

    if request.method == "POST":
        # get today's date and date recipe was last edited
        today = datetime.now().strftime("%d %B, %Y")
        last_edit = int(datetime.now().strftime("%Y%m%d"))
        # get user / author details
        session_user = get_user_lower(session["user"])["username"]
        author = users_collection.find_one({"username": session_user})["_id"]
        # get and convert total time
        hours = int(request.form.get("total_hrs")) * 60 if request.form.get(
            "total_hrs") else ""
        total_time = int(
            request.form.get("total_mins")) + hours if hours else int(
                request.form.get("total_mins"))
        # slugify url to be user-friendly
        slugUrl = slugify(request.form.get("recipe_name"))
        # get form data prior to submitting
        submit = {
            "recipe_name":
            request.form.get("recipe_name"),
            "recipe_slug":
            slugUrl,
            "description":
            request.form.get("description"),
            "dessert_type":
            request.form.get("dessert_type"),
            "ingredient_amount":
            request.form.getlist("ingredient_amount"),
            "ingredient_measurement":
            request.form.getlist("ingredient_measurement"),
            "ingredient_name":
            request.form.getlist("ingredient_name"),
            "directions":
            request.form.getlist("directions"),
            "total_hrs":
            request.form.get("total_hrs"),
            "total_mins":
            request.form.get("total_mins"),
            "total_time":
            total_time,
            "allergens":
            request.form.getlist("allergens"),
            "img_src":
            request.form.get("img_src"),
            "author":
            author,
            "date_added":
            today,
            "date_updated":
            today,
            "last_edit":
            last_edit,
            "views":
            0,
            "user_favs":
            0
        }
        # get the new _id being created on submit
        newID = recipes_collection.insert_one(submit)
        # add recipe _id to user's recipe list
        users_collection.update_one(
            {"_id": ObjectId(author)},
            {"$push": {
                "user_recipes": newID.inserted_id
            }})
        flash(
            Markup(f"<i class='far fa-check-circle green-text'></i>\
                Sounds delicious! Thanks for adding this recipe!"))
        # if selected, add recipe to user-favs as well
        if request.form.get("add_favs"):
            users_collection.update_one(
                {"_id": ObjectId(author)},
                {"$push": {
                    "user_favs": newID.inserted_id
                }})
            # increase number of favorites on this recipe by +1
            recipes_collection.update_one({"_id": newID.inserted_id},
                                          {"$inc": {
                                              "user_favs": 1
                                          }})
        return redirect(
            url_for("recipes.desserts_recipe",
                    recipe_id=newID.inserted_id,
                    slugUrl=slugUrl))