Adding Dietary Preference Button to Python Streamlit Diet Recommendation App

I’m developing a Python Streamlit application for a diet recommendation system, and I’m looking to enhance it by allowing users to choose their dietary preferences. Here’s a breakdown of what I’m trying to achieve:

Description: My Streamlit application currently generates diet recommendations based on user input such as age, weight, gender, etc. I want to expand its functionality by adding a new button that enables users to specify their dietary preferences, such as vegan, vegetarian, or normal (non-vegetarian).
Proposed Enhancement: Upon landing on the diet recommendation page, users should see a new button labeled “Dietary Preference” or similar. When clicked, this button should display options for vegan, vegetarian, or normal preferences.
Functionality: After selecting their dietary preference, users should click a “Submit” or “Apply” button to update the recommendations accordingly. The application should then generate food recommendations that align with the chosen preference. based on Name column or Keyword column thats contains word Vegan or Vegetarian


import streamlit as st
import pandas as pd
from Generate_Recommendations import Generator
from random import uniform as rnd
from ImageFinder import get_images_links as find_image
from streamlit_echarts import st_echarts
from streamlit_space import space
from PIL import Image 


# Initialize session state for navigation
if "current_page" not in st.session_state:
    st.session_state.current_page = "welcome"  # Start with the welcome page

# Function to navigate between pages
def navigate_to(page):
    st.session_state.current_page = page



# Render different content based on the current page
if st.session_state.current_page == "welcome":
    
    st.set_page_config(page_title="Diet IQ Welcome Page", page_icon="????", layout="wide")
    col1, col2, col3 = st.columns(([4, 5 ,4]))
    
    # Welcome Page
    with col2:
        logo = Image.open("DietIQ.png")
        st.image(logo, width=500, use_column_width=True)  # Center image

    st.markdown("<h1 style='font-size: 35px;text-align: center; color:#232e57;'>Welcome to Diet Recommendation System</h1>", unsafe_allow_html=True)
    space(lines=1)
    st.markdown("<h1 style='font-size: 20px;text-align: center; color:#232e57;'>Click the button below to go to the main page.</h1>", unsafe_allow_html=True)

    col4, col5, col6 = st.columns(([8, 5 ,4]))
    with col5:
        # Button to "navigate" to the Diet Recommendation page
        st.markdown("""
            <style>
                .stButton>button {
                    background-color: #283564; /* Change color to desired color */
                    color: white; /* Text color */
                    border-radius: 30px; /* Rounded corners */
                    padding: 10px 20px; /* Padding */
                    font-size: 16px; /* Font size */
                    border: none; /* No border */
                    cursor: pointer; /* Cursor style */
                }
                .stButton>button:hover {
                    background-color: #3c3160; /* Change color on hover */
                }
            </style>
        """, unsafe_allow_html=True)
        if st.button("Click here"):
            navigate_to("diet_recommendation")

elif st.session_state.current_page == "diet_recommendation":
    # Diet Recommendation Page
    st.set_page_config(page_title="Diet IQ Main Page", page_icon="????", layout="wide")






    # Custom CSS to change the background color
    bg_color = """
        <style>
        .stApp {
            background: linear-gradient(to right, #a4b3d8, #92bbd1); /* Light blue to green gradient */
        }
        </style>
    """

    # Insert custom CSS into Streamlit
    st.markdown(bg_color, unsafe_allow_html=True)



    nutritions_values=['Calories','FatContent','SaturatedFatContent','CholesterolContent','SodiumContent','CarbohydrateContent','FiberContent','SugarContent','ProteinContent']
    # Streamlit states initialization
    if 'person' not in st.session_state:
        st.session_state.generated = False
        st.session_state.recommendations=None
        st.session_state.person=None
        st.session_state.weight_loss_option=None
    class Person:

        def __init__(self,age,height,weight,gender,activity,meals_calories_perc,weight_loss):
            self.age=age
            self.height=height
            self.weight=weight
            self.gender=gender
            self.activity=activity
            self.meals_calories_perc=meals_calories_perc
            self.weight_loss=weight_loss
        def calculate_bmi(self,):
            bmi=round(self.weight/((self.height/100)**2),2)
            return bmi

        def display_result(self,):
            bmi=self.calculate_bmi()
            bmi_string=f'{bmi} kg/m²'
            if bmi<18.5:
                category='Underweight'
                color='blue'
            elif 18.5<=bmi<25:
                category='Normal'
                color='yellow'
            elif 25<=bmi<30:
                category='Overweight'
                color='pink'
            else:
                category='Obesity'    
                color='orange'
            return bmi_string,category,color

        def calculate_bmr(self):
            if self.gender=='Male':
                bmr=10*self.weight+6.25*self.height-5*self.age+5
            else:
                bmr=10*self.weight+6.25*self.height-5*self.age-161
            return bmr

        def calories_calculator(self):
            activites=['Little/no exercise', 'Light exercise', 'Moderate exercise (3-5 days/wk)', 'Very active (6-7 days/wk)', 'Extra active (very active & physical job)']
            weights=[1.2,1.375,1.55,1.725,1.9]
            weight = weights[activites.index(self.activity)]
            maintain_calories = self.calculate_bmr()*weight
            return maintain_calories

        def generate_recommendations(self,):
            total_calories=self.weight_loss*self.calories_calculator()
            recommendations=[]
            for meal in self.meals_calories_perc:
                meal_calories=self.meals_calories_perc[meal]*total_calories
                if meal=='breakfast':        
                    recommended_nutrition = [meal_calories,rnd(10,30),rnd(0,4),rnd(0,30),rnd(0,400),rnd(40,75),rnd(4,10),rnd(0,10),rnd(30,100)]
                elif meal=='launch':
                    recommended_nutrition = [meal_calories,rnd(20,40),rnd(0,4),rnd(0,30),rnd(0,400),rnd(40,75),rnd(4,20),rnd(0,10),rnd(50,175)]
                elif meal=='dinner':
                    recommended_nutrition = [meal_calories,rnd(20,40),rnd(0,4),rnd(0,30),rnd(0,400),rnd(40,75),rnd(4,20),rnd(0,10),rnd(50,175)] 
                else:
                    recommended_nutrition = [meal_calories,rnd(10,30),rnd(0,4),rnd(0,30),rnd(0,400),rnd(40,75),rnd(4,10),rnd(0,10),rnd(30,100)]
                generator=Generator(recommended_nutrition)
                recommended_recipes=generator.generate().json()['output']
                recommendations.append(recommended_recipes)
            for recommendation in recommendations:
                for recipe in recommendation:
                    recipe['image_link']=find_image(recipe['Name']) 
            return recommendations

    class Display:
        def __init__(self):
            self.plans=["Maintain weight","Mild weight loss","Weight loss","Extreme weight loss", "Mild weight gain" , " Weight gain", "Extreme weight gain"]
            self.weights=[1,0.9,0.8,0.6,1.1,1.2,1.4]
            self.losses=['-0 kg/week','-0.25 kg/week','-0.5 kg/week','-1 kg/week','+0.25 kg/week','+0.5 kg/week','+1 kg/week ']
            pass

        def display_bmi(self,person):
            st.header('BMI CALCULATOR')
            bmi_string,category,color = person.display_result()
            space(lines= 0)
            
            st.write("Body Mass Index (BMI)")
            # st.markdown("<h6 style='font-size: 20px;text-align:center'>Body Mass Index (BMI)</h6>", unsafe_allow_html=True)
            st.metric(label=" ", value=bmi_string)
            space(lines=2)
            # Create bold text with proper alignment, font size, and color
            new_title = f'<p style="font-family:sans-serif; color:{color}; font-size: 35px; font-weight: bold;">{category}</p>'
            # Display the styled bold text in Streamlit
            st.markdown(new_title, unsafe_allow_html=True)
            space(lines=4)
            st.markdown(
                """
                Healthy BMI range: 18.5 kg/m² - 25 kg/m².
                """)   

        def display_calories(self,person):
            st.header('CALORIES CALCULATOR')        
            maintain_calories=person.calories_calculator()
            st.write('A guideline for how many calories to consume each day to maintain, lose, or gain weight at a chosen rate.')
            st.markdown("<h1 style='font-size: 30px;'>Calories Plan </h1>", unsafe_allow_html=True)
            for plan,weight,loss,col in zip(self.plans,self.weights,self.losses,st.columns(7)):
                calories_per_day = round(maintain_calories * weight)
    # Using newline to separate lines
                metric_text = f"{plan}n: {calories_per_day} Calories/day"

                # Displaying the metric with separate lines
                st.metric(label="", value=metric_text, delta=loss, delta_color="inverse")
        def display_recommendation(self,person,recommendations):
            space(lines=4)
            st.markdown("<h1 style='font-size: 30px;text-align: center;'>DIET RECOMMENDATOR </h1>", unsafe_allow_html=True)
            
            with st.spinner('Generating recommendations...'): 
                meals=person.meals_calories_perc
                space(lines=3)
                st.markdown("<h1 style='font-size: 25px;text-align: center;'>Recommended recipes </h1>", unsafe_allow_html=True)
            
                
                space(lines=3)
                for meal_name,column,recommendation in zip(meals,st.columns(len(meals)),recommendations):
                    with column:
                        #st.markdown(f'<div style="text-align: center;">{meal_name.upper()}</div>', unsafe_allow_html=True) 
                        st.markdown(f'##### {meal_name.upper()}')    
                        for recipe in recommendation:
                            
                            recipe_name=recipe['Name']
                            expander = st.expander(recipe_name)
                            recipe_link=recipe['image_link']
                            recipe_img=f'<div><center><img src={recipe_link} alt={recipe_name}></center></div>'     
                            nutritions_df=pd.DataFrame({value:[recipe[value]] for value in nutritions_values})      
                            
                            expander.markdown(recipe_img,unsafe_allow_html=True)  
                            expander.markdown(f'<h5 style="text-align: center;font-family:sans-serif;">Nutritional Values (g):</h5>', unsafe_allow_html=True)                   
                            expander.dataframe(nutritions_df)
                            expander.markdown(f'<h5 style="text-align: center;font-family:sans-serif;">Ingredients:</h5>', unsafe_allow_html=True)
                            for ingredient in recipe['RecipeIngredientParts']:
                                expander.markdown(f"""
                                            - {ingredient}
                                """)
                            expander.markdown(f'<h5 style="text-align: center;font-family:sans-serif;">Recipe Instructions:</h5>', unsafe_allow_html=True)    
                            for instruction in recipe['RecipeInstructions']:
                                expander.markdown(f"""
                                            - {instruction}
                                """) 
                            expander.markdown(f'<h5 style="text-align: center;font-family:sans-serif;">Cooking and Preparation Time:</h5>', unsafe_allow_html=True)   
                            expander.markdown(f"""
                                    - Cook Time       : {recipe['CookTime']}min
                                    - Preparation Time: {recipe['PrepTime']}min
                                    - Total Time      : {recipe['TotalTime']}min
                                """)    
        
        def display_meal_choices(self,person,recommendations):    
            st.subheader('Choose your meal composition:')
            # Display meal compositions choices
            if len(recommendations)==3:
                breakfast_column,launch_column,dinner_column=st.columns(3)
                with breakfast_column:
                    breakfast_choice=st.selectbox(f'Choose your breakfast:',[recipe['Name'] for recipe in recommendations[0]])
                with launch_column:
                    launch_choice=st.selectbox(f'Choose your launch:',[recipe['Name'] for recipe in recommendations[1]])
                with dinner_column:
                    dinner_choice = st.selectbox(f'Choose your dinner:', [recipe['Name'] for recipe in recommendations[2]])  
                choices = [breakfast_choice, launch_choice, dinner_choice]     
            elif len(recommendations) == 4:
                breakfast_column, morning_snack, launch_column, dinner_column = st.columns(4)
                with breakfast_column:
                    breakfast_choice = st.selectbox(f'Choose your breakfast:', [recipe['Name'] for recipe in recommendations[0]])
                with morning_snack:
                    morning_snack = st.selectbox(f'Choose your morning_snack:', [recipe['Name'] for recipe in recommendations[1]])
                with launch_column:
                    launch_choice = st.selectbox(f'Choose your launch:', [recipe['Name'] for recipe in recommendations[2]])
                with dinner_column:
                    dinner_choice = st.selectbox(f'Choose your dinner:', [recipe['Name'] for recipe in recommendations[3]])
                choices = [breakfast_choice, morning_snack, launch_choice, dinner_choice]                
            else:
                breakfast_column, morning_snack, launch_column, afternoon_snack, dinner_column = st.columns(5)
                with breakfast_column:
                    breakfast_choice = st.selectbox(f'Choose your breakfast:', [recipe['Name'] for recipe in recommendations[0]])
                with morning_snack:
                    morning_snack = st.selectbox(f'Choose your morning_snack:', [recipe['Name'] for recipe in recommendations[1]])
                with launch_column:
                    launch_choice = st.selectbox(f'Choose your launch:', [recipe['Name'] for recipe in recommendations[2]])
                with afternoon_snack:
                    afternoon_snack = st.selectbox(f'Choose your afternoon:', [recipe['Name'] for recipe in recommendations[3]])
                with dinner_column:
                    dinner_choice = st.selectbox(f'Choose your  dinner:', [recipe['Name'] for recipe in recommendations[4]])
                choices = [breakfast_choice, morning_snack, launch_choice, afternoon_snack, dinner_choice] 
        
            # Calculating the sum of nutritional values of the choosen recipes
            total_nutrition_values = {nutrition_value: 0 for nutrition_value in nutritions_values}
            for choice, meals_ in zip(choices, recommendations):
                for meal in meals_:
                    if meal['Name'] == choice:
                        for nutrition_value in nutritions_values:
                            total_nutrition_values[nutrition_value] += meal[nutrition_value]

            total_calories_chose = total_nutrition_values['Calories']
            loss_calories_chose = round(person.calories_calculator() * person.weight_loss)
            # Display the numerical comparison
            with st.container():
                st.markdown(f'<h5 style="text-align: center;font-family:sans-serif;">Total Calories in Recipes vs {st.session_state.weight_loss_option} Calories:</h5>', unsafe_allow_html=True)
                st.markdown(f'<h2 style="text-align: center;font-family:sans-serif;font-size: 25px;color:black;">Total Calories in Recipes: {total_calories_chose}</h2>', unsafe_allow_html=True)
                st.markdown(f'<h2 style="text-align: center;font-family:sans-serif;font-size: 25px;color:black;">{st.session_state.weight_loss_option} Calories : {loss_calories_chose}</h2>', unsafe_allow_html=True)

            # Display corresponding graphs
            #st.markdown(f'<h5 style="text-align: center;font-family:sans-serif;">Total Calories in Recipes vs {st.session_state.weight_loss_option} Calories:</h5>', unsafe_allow_html=True)
            #total_calories_graph_options = {
        #"xAxis": {
            #"type": "category",
            #"data": ['Total Calories you chose', f"{st.session_state.weight_loss_option} Calories"],
        #},
        #"yAxis": {"type": "value"},
        #"series": [
            #{
                #"data": [
                    #{"value":total_calories_chose, "itemStyle": {"color":["#33FF8D","#FF3333"][total_calories_chose>loss_calories_chose]}},
                    #{"value": loss_calories_chose, "itemStyle": {"color": "#3339FF"}},
                #],
                #"type": "bar",
            #}
        #],
    #}

            #st_echarts(options=total_calories_graph_options,height="400px",)                       



    display=Display()
    # Apply padding to the title
    title = """
        <h1 style='text-align: center; padding-top: 5px; padding-bottom: 70;'>
             Diet Recommendation Main Page
        </h1>
    """
    st.markdown(title, unsafe_allow_html=True)

    # Other content followsv# Centered welcome message using custom HTML
    welcome_message = """
        <p style='text-align: center;font-size: 20px;'>
            Please select following options to Generate Recommendations
        </p>
    """
    st.markdown(welcome_message, unsafe_allow_html=True)


    with st.form("recommendation_form"):
        # Create a two-column layout for age and height
        col1, col2 ,col3= st.columns(([3, 2.5, 4]))

        # Display inputs within each column
        with col1:
            

            space(lines=1)
            st.markdown("<h1 style='font-size: 20px;'>Age</h1>", unsafe_allow_html=True)
            age = st.number_input('', min_value=2, max_value=120, step=1)

            space(lines=1)
            st.markdown("<h1 style='font-size: 20px;'>Height(cm)</h1>", unsafe_allow_html=True)
            
            height = st.number_input('', min_value=50, max_value=300, step=1)  # Input field
        
            
            space(lines=1)
            st.markdown("<h1 style='font-size: 20px;'>Weight(kg)</h1>", unsafe_allow_html=True)
            weight = st.number_input('', min_value=10, max_value=300, step=1)

            space(lines=1)
            st.markdown("<h1 style='font-size: 20px;'>Choose your weight loss/gain plan:</h1>", unsafe_allow_html=True)
            option = st.selectbox('',display.plans)
            st.session_state.weight_loss_option=option
            weight_loss=display.weights[display.plans.index(option)]

        with col2:
            st.write("")
            space(lines=40)
        
                    
            st.markdown("""
            <style>
                .stButton>button {
                    background-color: #283564; /* Change color to desired color */
                    color: white; /* Text color */
                    border-radius: 30px; /* Rounded corners */
                    padding: 10px 20px; /* Padding */
                    font-size: 16px; /* Font size */
                    border: none; /* No border */
                    cursor: pointer; /* Cursor style */
                }
                .stButton>button:hover {
                    background-color: #3c3160; /* Change color on hover */
                }
            </style>
        """, unsafe_allow_html=True)
            generated = st.form_submit_button("Click here to Generate Recommendations")
            

        with col3:
            
            space(lines=1)
            st.markdown("<h1 style='font-size: 20px;'>Gender</h1>", unsafe_allow_html=True)
            gender = st.radio('', ('Male', 'Female')) 
            space(lines=1)
            st.markdown("<h1 style='font-size: 20px;'>Activity</h1>", unsafe_allow_html=True)
            activity = st.radio('',options=['Little/no exercise', 'Light exercise', 'Moderate exercise (3-5 days/wk)', 'Very active (6-7 days/wk)', 
            'Extra active (very active & physical job)'])

            space(lines=1)
            st.markdown("<h1 style='font-size: 20px;'>Meals per day</h1>", unsafe_allow_html=True)
            number_of_meals=st.slider('',min_value=3,max_value=5,step=1,value=3)
            if number_of_meals==3:
                meals_calories_perc={'breakfast':0.35,'lunch':0.40,'dinner':0.25}
            elif number_of_meals==4:
                meals_calories_perc={'breakfast':0.30,'morning snack':0.05,'lunch':0.40,'dinner':0.25}
            else:
                meals_calories_perc={'breakfast':0.30,'morning snack':0.05,'lunch':0.40,'afternoon snack':0.05,'dinner':0.20}
            
        
        
    
        
        
        
    if generated:
        st.session_state.generated=True
        person = Person(age,height,weight,gender,activity,meals_calories_perc,weight_loss)
    

        col1, col2,col3 = st.columns(([9, 2 ,4]))

        with col1:
            
            with st.container():
                display.display_calories(person)
            

        with col2:
            
            st.write("")

        with col3:

            
            with st.container():
                display.display_bmi(person)

            
        space(lines=2)   
        with st.spinner('Generating recommendations...'):  
                recommendations=person.generate_recommendations()
                st.session_state.recommendations=recommendations
                st.session_state.person=person 
                    

    if st.session_state.generated:
        with st.container():
            display.display_recommendation(st.session_state.person,st.session_state.recommendations)
            st.success('Recommendation Generated Successfully !', icon="✅")
        with st.container():
            display.display_meal_choices(st.session_state.person,st.session_state.recommendations)

Specific Requests:
I need guidance on how to integrate the new button into my Streamlit application and capture the user’s preference selection.
Additionally, I’m seeking advice on how to modify the existing recommendation generation logic to consider the user’s chosen dietary preference.
Suggestions on how to structure the UI and user interaction flow for this new feature would be highly appreciated.
What I’ve Tried: So far, I’ve explored Streamlit’s documentation and experimented with adding new buttons using their components. However, I’m unsure about the best approach for integrating this specific functionality.

New contributor

Omar is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật