How to load data to list using JSON

746 views
Skip to first unread message

John Zuriel

unread,
Feb 9, 2021, 9:21:17 AM2/9/21
to Kivy users support
1.PNG2.PNG 
Someone recommend me to use JSON now, I have an expansion panel with different name with the use of dictionary but inside it there's a OneLineListItem widget with a fixed text value so each one of expansion panel has same value, now with the use of json, how can I possibly populate them with different date on each expansion panel?
3.PNG
my second question is how can I possibly use JSON to fill a dialog with different data on each list I clicked?

here's a bit of the code that I use on this screen.
py:
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.list_items = []  # Dictionary where the items is stored
        self.category_list = ['Chicken', 'Pork', 'Beef', 'Fish', 'Vegetables']
        self.dialog = None

    def on_start(self):
        for category in self.category_list:
            self.root.ids.sm.get_screen('menu').ids.rlist.add_widget(
                MDExpansionPanel(
                    icon="recipe.png",
                    content=Content(),
                    panel_cls=MDExpansionPanelTwoLine(
                        text=category,
                        secondary_text="Tap to view recipes"
                    )
                )
            )

    def showinfo(self, widget):
        self.dialog = MDDialog(size_hint=(0.8, 0.8), text="Ingredients:", auto_dismiss=True)
        self.dialog.open()

class Content(MDBoxLayout, OneLineListItem):
    pass

kv:
<OneLineListItem>:
    id: onelst
    text: "Honey Garlic"
    on_release: app.showinfo(onelst)
    MDIconButton:
        icon:'plus'

<Content>
    adaptive_height: True

            MDBottomNavigationItem:
                name: 'screen 2'
                text: 'Recipe'
                icon: 'food'

                ScrollView:
                    MDList:
                        id: rlist

John Zuriel

unread,
Feb 9, 2021, 9:25:05 AM2/9/21
to Kivy users support
how can I possibly populate them with different data on each expansion panel?  

Elliot Garbus

unread,
Feb 9, 2021, 9:54:08 AM2/9/21
to kivy-...@googlegroups.com

Here is a simple example that saves data as a list, and at startup loads the data and creates widgets. In the example the file is saved when the app is closed, and read with the app is opened.

 

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button

from pathlib import Path
import json

kv =
"""
<MyButton>:
    size_hint_y: None
    height: 48
    on_release: print(f'Button {self.text} pressed')

RootBoxLayout:
    orientation: 'vertical'
    BoxLayout:
        size_hint_y: None
        height: 48
        TextInput:
            id: ti
            hint_text: 'Button Name'
            multiline: False
            on_text_validate:
                if self.text: root.create_a_button(self.text)
        Button:
            text: 'Create a Button'
            on_release:
                if ti.text: root.create_a_button(ti.text)
                ti.text = ''
                ti.focus = True
    BoxLayout:
        id:button_box
        orientation: 'vertical'
"""


class MyButton(Button):
   
pass


class
RootBoxLayout(BoxLayout):
   
def create_a_button(self, text):
       
self.ids.button_box.add_widget(MyButton(text=text))


class SaveButtonsApp(App):
   
def build(self):
       
return Builder.load_string(kv)

   
def on_stop(self):
       
# get the names of the buttons
       
names = [w.text for w in self.root.ids.button_box.children]
       
with open('saved_button.txt', 'w') as f:
            json.dump(names, f)

   
def on_start(self):
        p = Path(
'saved_button.txt')
       
if p.exists():
           
with open(p) as f:
                button_names = json.load(f)
               
for name in button_names:
                   
self.root.create_a_button(name)


SaveButtonsApp().run()

 

 

 

 

From: John Zuriel
Sent: Tuesday, February 9, 2021 7:25 AM
To: Kivy users support
Subject: [kivy-users] Re: How to load data to list using JSON

 

how can I possibly populate them with different data on each expansion panel?  

On Tuesday, February 9, 2021 at 10:21:17 PM UTC+8 John Zuriel wrote:

 

Someone recommend me to use JSON now, I have an expansion panel with different name with the use of dictionary but inside it there's a OneLineListItem widget with a fixed text value so each one of expansion panel has same value, now with the use of json, how can I possibly populate them with different date on each expansion panel?

--
You received this message because you are subscribed to the Google Groups "Kivy users support" group.
To unsubscribe from this group and stop receiving emails from it, send an email to kivy-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/887744e8-2af4-4da8-a093-3467a202db01n%40googlegroups.com.

 

John Zuriel

unread,
Feb 9, 2021, 10:14:56 AM2/9/21
to Kivy users support
I have a grasp now on how to save and load data, but for example I want to load a JSON file with different recipes to my onelinelistitem how can I possibly load it? I want it to be like this
4.PNG
because every list on expansion panel has the same value because of the fix text value "honey garlic".


Elliot Garbus

unread,
Feb 9, 2021, 10:30:46 AM2/9/21
to kivy-...@googlegroups.com

What is the underlying data structure you are using to store your data?

It seems like you might want to use a set of nested dictionaries where the keys relate to  the data as displayed.

 

From: John Zuriel
Sent: Tuesday, February 9, 2021 8:15 AM
To: Kivy users support
Subject: Re: [kivy-users] Re: How to load data to list using JSON

 

I have a grasp now on how to save and load data, but for example I want to load a JSON file with different recipes to my onelinelistitem how can I possibly load it? I want it to be like this

4.PNG

John Zuriel

unread,
Feb 9, 2021, 10:46:02 AM2/9/21
to Kivy users support

What is the underlying data structure you are using to store your data?

What do you mean by that? code I'm using to store my data? I still don't have a JSON file to load, since I'm still studying it, I only understand how to use a dictionary, but on my menuscreen, you're the one who change my code to store the data using JSON

It seems like you might want to use a set of nested dictionaries where the keys relate to  the data as displayed.

kinda, since i'm using a dictionary to load the name of expansion panel then load another dictionary for the menu on onelinelistitem

John Zuriel

unread,
Feb 9, 2021, 10:53:52 AM2/9/21
to Kivy users support
Here's the edited version of my project.
https://pastebin.com/iFfDUt0N

Elliot Garbus

unread,
Feb 9, 2021, 11:46:28 AM2/9/21
to kivy-...@googlegroups.com

The simple JSON example I shared used a list.  It looks like you’re your app, you would want to save your data in dictionaries, and then restore your data from dictionaries.

 

The keys and content would relate to how the data is displayed.

 

From: John Zuriel
Sent: Tuesday, February 9, 2021 8:54 AM
To: Kivy users support
Subject: Re: [kivy-users] Re: How to load data to list using JSON

 

Here's the edited version of my project.

https://pastebin.com/iFfDUt0N

On Tuesday, February 9, 2021 at 11:46:02 PM UTC+8 John Zuriel wrote:

What is the underlying data structure you are using to store your data?

What do you mean by that? code I'm using to store my data? I still don't have a JSON file to load, since I'm still studying it, I only understand how to use a dictionary, but on my menuscreen, you're the one who change my code to store the data using JSON

It seems like you might want to use a set of nested dictionaries where the keys relate to  the data as displayed.

kinda, since i'm using a dictionary to load the name of expansion panel then load another dictionary for the menu on onelinelistitem

On Tuesday, February 9, 2021 at 11:30:46 PM UTC+8 ElliotG wrote:

What is the underlying data structure you are using to store your data?

It seems like you might want to use a set of nested dictionaries where the keys relate to  the data as displayed.

 

From: John Zuriel
Sent: Tuesday, February 9, 2021 8:15 AM
To: Kivy users support
Subject: Re: [kivy-users] Re: How to load data to list using JSON

 

I have a grasp now on how to save and load data, but for example I want to load a JSON file with different recipes to my onelinelistitem how can I possibly load it? I want it to be like this

because every list on expansion panel has the same value because of the fix text value "honey garlic".

 

John Zuriel

unread,
Feb 9, 2021, 12:01:33 PM2/9/21
to Kivy users support
The idea of my recipe screen is to have a category of menu with the use of expansion panel then after clicking that panel, a list of recipes will show, then after clicking any recipes on the list, a dialog box will show with the ingredients of that recipe

John Zuriel

unread,
Feb 9, 2021, 12:06:12 PM2/9/21
to Kivy users support
I want that every panel to have their own data since right now i'm using a fix value to show the OneLineListItem the text "honey garlic", so every panel have "honey garlic" on them

Elliot Garbus

unread,
Feb 9, 2021, 12:21:47 PM2/9/21
to kivy-...@googlegroups.com

So perhaps something like:

{'Categories': ['Fish', 'Chicken', 'Beef']}

{'Recipes': [{'title':'Steamed Bass', 'directions': 'steam the fish',

              'shopping list':['Fish', 'parchment paper', 'tomatoes']},

            {'title':'CheeseBurger', 'directions': 'cook, flip, melt, eat',

              'shopping list':['ground beef', 'cheese', 'buns']},

             ]}

 

You may want to include the categories in the recipes or the recipes in the categories…

The idea is to use dictionaries to identify the types of data so you can save it and restore it.

John Zuriel

unread,
Feb 9, 2021, 12:36:52 PM2/9/21
to Kivy users support
YES DEFINITELY LIKE THAT!!! but I don't possibly know how to display that on my recipe screen since I'm really new to JSON, and is it possible to make a file with the categories and recipes on it? and just load it using on_start method?

Elliot Garbus

unread,
Feb 9, 2021, 12:53:44 PM2/9/21
to kivy-...@googlegroups.com

This not about JSON,  this is only about Python dictionaries and lists. 

Yes, you can iterate over the dicts and lists and populate your screens.

 

Much like the example that used a list, you can use JSON to store to dictionaries to disk, and load them.

John Zuriel

unread,
Feb 9, 2021, 1:07:09 PM2/9/21
to Kivy users support
Can you possibly show an example with my code? coz I really don't know how to make it work, I barely manage to display the categories on Expansion panel with your example the last time you help me.

John Zuriel

unread,
Feb 9, 2021, 1:13:19 PM2/9/21
to Kivy users support

This not about JSON,  this is only about Python dictionaries and lists. 

Ohhh okay, coz since yesterday I keep on studying how to use json on python

Much like the example that used a list, you can use JSON to store to dictionaries to disk, and load them

Yeah, I still have your code to store data on my main code.

Elliot Garbus

unread,
Feb 9, 2021, 1:42:15 PM2/9/21
to kivy-...@googlegroups.com

Here is an example of how to iterate through the example data.  Run it a play with it.  Add the categories as you like.

After you understand this – you would learn to create the data structure by pulling the data off of your widgets or creating widgets by reading the data.

 

card_file = {'Recipes': [{'title':'Steamed Bass', 'directions': 'steam the fish',
             
'shopping list':['Fish', 'parchment paper', 'tomatoes']},
            {
'title':'Cheese Burger', 'directions': 'cook, flip, melt, eat',
             
'shopping list':['ground beef', 'cheese', 'buns']},
             ]}

for recipe in card_file['Recipes']:
   
print(f"The {recipe['title']} uses ingredients: {recipe['shopping list']}")
   
print(f"The directions are: {recipe['directions']}\n")

John Zuriel

unread,
Feb 9, 2021, 2:15:21 PM2/9/21
to Kivy users support
Capture.PNG
This is what I want my recipe screen to display, the recipes on their own category with their own ingredients, I'll try to make it work, and I'll go back to you if I fail. Thanks.

    def showinfo(self, widget):
        self.dialog = MDDialog(size_hint=(0.8, 0.8), text="Ingredients:", auto_dismiss=True)
        self.dialog.open()

        for recipe in self.card_file['Recipes']:
            print(f"{recipe['title']} : {recipe['shopping list']}")

John Zuriel

unread,
Feb 10, 2021, 6:17:17 AM2/10/21
to Kivy users support
@ElliotG no luck on how can I put the "title" from "Recipes" on to my OneLineListItem
I tried this code but it doesn't work
1.png
Is it possible to load a text file with the dictionary you use?
like the one you did on my menuscreen, when adding and storing them after closing or running the app

capture 2.png
This is what I want to do, but after hours experimenting your code i only manage to print them, but fail display them on widget.

Elliot Garbus

unread,
Feb 10, 2021, 11:01:10 AM2/10/21
to kivy-...@googlegroups.com

This error, keyerror ‘nlst’, means you do not have an id “nlst” on the menu screen.

 

From: John Zuriel
Sent: Wednesday, February 10, 2021 4:17 AM
To: Kivy users support
Subject: Re: [kivy-users] Re: How to load data to list using JSON

 

@ElliotG no luck on how can I put the "title" from "Recipes" on to my OneLineListItem

I tried this code but it doesn't work

Is it possible to load a text file with the dictionary you use?

like the one you did on my menuscreen, when adding and storing them after closing or running the app

 

This is what I want to do, but after hours experimenting your code i only manage to print them, but fail display them on widget.

On Wednesday, February 10, 2021 at 3:15:21 AM UTC+8 John Zuriel wrote:

1.png
capture 2.png

John Zuriel

unread,
Feb 10, 2021, 11:31:33 AM2/10/21
to Kivy users support
Oh right because nlst is outside of menuscreen, but after removing the get_screen("menu") from this code:

        for recipeList in self.card_file['Recipes']:
            self.root.ids.sm.get_screen('menu').ids.nlst.add_widget(
                OneLineListItem(text=f"{recipeList['title']}")
            )

it gives the same keyerror.

John Zuriel

unread,
Feb 10, 2021, 11:49:02 AM2/10/21
to Kivy users support
Capture.PNG
Here's the code, can you check it out? can't seem to find what's the problem in it
py:
from kivy.lang import Builder
from kivymd.app import MDApp
from kivymd.uix.dialog import MDDialog
from kivymd.uix.list import OneLineListItem
from kivy.uix.screenmanager import Screen
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.expansionpanel import MDExpansionPanel, MDExpansionPanelTwoLine
from kivy.core.window import Window

Window.size = (300, 500)


class GroceryApp(MDApp):

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.list_items = []
        self.category_list = ['Chicken', 'Pork', 'Beef', 'Fish', 'Vegetables']
        self.dialog = None
        self.card_file = {'Recipes': [{'title': 'Steamed Bass', 'directions': 'steam the fish',
                                       'shopping list': ['Fish', 'parchment paper', 'tomatoes']},
                                      {'title': 'Cheese Burger', 'directions': 'cook, flip, melt, eat',
                                       'shopping list': ['ground beef', 'cheese', 'buns']},
                                      ]}

    def build(self):
        self.theme_cls.primary_palette = "Pink"
        self.theme_cls.theme_style = "Dark"
        return Builder.load_file('main.kv')

    def on_start(self):
        for category in self.category_list:
            panel = MDExpansionPanel(icon="recipe.png", content=Content(), panel_cls=MDExpansionPanelTwoLine(
                text=category, secondary_text="Tap to view recipes"))

            self.root.ids.sm.get_screen('menu').ids.rlist.add_widget(panel)

    def showinfo(self, widget):
        self.dialog = MDDialog(size_hint=(0.8, 0.8), text="Ingredients:", auto_dismiss=True)
        self.dialog.open()

        for recipe in self.card_file['Recipes']:
            print(f"{recipe['shopping list']}")


class MenuScreen(Screen):
    pass


class Content(MDBoxLayout, OneLineListItem):
    pass


GroceryApp().run()

kv:
Screen:
    ScreenManager:
        id: sm
        MenuScreen:
            id: ms
            name: "menu"

<Content>
    id: nlst
    height: self.minimum_height
    on_release: app.showinfo(nlst)
    MDIconButton:
        icon:'plus'


<MenuScreen>:
    BoxLayout:
        orientation: 'vertical'

        MDToolbar:
            id: toolbar
            elevation: 6
            title: "Grocery List"

            MDIconButton:
                icon: "trash-can-outline"
                pos_hint: {"center_y": .5}
                on_release:
                    app.qna()

        MDBottomNavigation:

            MDBottomNavigationItem:
                name: 'screen 2'
                text: 'Recipe'
                icon: 'food'

                ScrollView:
                    MDList:
                        id: rlist

            MDBottomNavigationItem:
                name: 'screen 3'
                text: 'Status'
                icon: 'google-analytics'

                MDLabel:
                    text: 'Status Window'
                    theme_text_color: "Primary"
                    halign: 'center'

Elliot Garbus

unread,
Feb 10, 2021, 12:00:30 PM2/10/21
to kivy-...@googlegroups.com

The id “nlst” is indicates the instance of the Content class.  I do not see where the Content class is instanced.

 

From: John Zuriel
Sent: Wednesday, February 10, 2021 9:49 AM
To: Kivy users support
Subject: Re: [kivy-users] Re: How to load data to list using JSON

 

Is it possible to load a text file with the dictionary you use?

like the one you did on my menuscreen, when adding and storing them after closing or running the app

 

This is what I want to do, but after hours experimenting your code i only manage to print them, but fail display them on widget.

Capture.PNG

John Zuriel

unread,
Feb 10, 2021, 12:14:41 PM2/10/21
to Kivy users support
I really don't know man, I'm kinda confused on my code too, I even tried putting the code to my content class yet it doens't work

class Content(MDBoxLayout, OneLineListItem):
    for recipeList in self.card_file['Recipes']:
        self.root.ids.sm.get_screen('menu').ids.nlst.add_widget(
            OneLineListItem(text=f"{recipeList['title']}")
        )

since I don't have "self" on reference, it really does not work, I just want to put the title: "Steamed bass" and "Cheese Burger" on their respective category using the OneLineListItem.

ElliotG

unread,
Feb 10, 2021, 12:43:25 PM2/10/21
to Kivy users support
You are instancing the Content class here:
def on_start(self):
        for category in self.category_list:
            panel = MDExpansionPanel(icon="recipe.png", content=Content(), panel_cls=MDExpansionPanelTwoLine(
                text=category, secondary_text="Tap to view recipes"))
            self.root.ids.sm.get_screen('menu').ids.rlist.add_widget(panel)

You could add a kivy property to Content and initialize it here.
or You need to figure out the path to the Content Instance.

From app the path would be:
self.root.ids.sm.get_screen('menu').ids.rlist.children is a list of the MDExpansionPanel instances you have created.
so to access the first the last item added, and the id you are looking for:
self.root.ids.sm.get_screen('menu').ids.rlist.children[0].content.ids.nlst...

John Zuriel

unread,
Feb 10, 2021, 1:01:20 PM2/10/21
to Kivy users support
It seems not working to me,  coz I don't know where to put in on my code, can you show how it works? but I'm getting the gist of what you're trying to explain.

Elliot Garbus

unread,
Feb 10, 2021, 1:23:55 PM2/10/21
to kivy-...@googlegroups.com

Create and share a  minimal runnable example.  I can show the issue.

Here's the code, can you check it out? can't seem to find what's the problem in it
py:

John Zuriel

unread,
Feb 10, 2021, 1:47:12 PM2/10/21
to Kivy users support
 Ok so here's a runnable example, and I change the dictionary to create a bit to example for "Chicken" category
Py:
from kivy.lang import Builder
from kivymd.app import MDApp
from kivymd.uix.dialog import MDDialog
from kivymd.uix.list import OneLineListItem
from kivy.uix.screenmanager import Screen
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.expansionpanel import MDExpansionPanel, MDExpansionPanelTwoLine
from kivy.core.window import Window

Window.size = (300, 500)


class GroceryApp(MDApp):

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.list_items = []
        self.category_list = ['Chicken', 'Pork', 'Beef', 'Fish', 'Vegetables']
        self.dialog = None

        self.card_file = {
            'Recipes': [{'title': 'Chicken Adobo', 'shopping list': ['Fish', 'parchment paper', 'tomatoes']},
                        {'title': 'Chicken Noodle Soup', 'shopping list': ['ground beef', 'cheese', 'buns']},
                        ]}

    def build(self):
        self.theme_cls.primary_palette = "Pink"
        self.theme_cls.theme_style = "Dark"
        return Builder.load_file('main.kv')

    def on_start(self):
        for category in self.category_list:
            panel = MDExpansionPanel(icon="recipe.png", content=Content(), panel_cls=MDExpansionPanelTwoLine(
                text=category, secondary_text="Tap to view recipes"))

            self.root.ids.sm.get_screen('menu').ids.rlist.add_widget(panel)

    def showinfo(self, widget):
        self.dialog = MDDialog(size_hint=(0.8, 0.8), text="Ingredients:", auto_dismiss=True)
        self.dialog.open()

        for recipe in self.card_file['Recipes']:
            print(f"{recipe['shopping list']}")


class MenuScreen(Screen):
    pass


class Content(MDBoxLayout, OneLineListItem):
    pass


GroceryApp().run()

Kv:
Screen:
    ScreenManager:
        id: sm
        MenuScreen:
            id: ms
            name: "menu"

<Content>
    id: nlst
    adaptive_height: True
    on_release: app.showinfo(nlst)
    MDIconButton:
        icon:'plus'


<MenuScreen>:
    BoxLayout:
        orientation: 'vertical'

        MDBottomNavigation:
            MDBottomNavigationItem:
                name: 'screen 2'
                text: 'Recipe'
                icon: 'food'

                ScrollView:
                    MDList:
                        id: rlist

This is what I'm trying to do, 
Capture.PNG
now after putting this code to on_start since I'm trying to put the title to OneLineListItem widget.

        for recipeList in self.card_file['Recipes']:
            self.root.ids.sm.get_screen('menu').ids.nlst.add_widget(
                OneLineListItem(text=f"{recipeList['title']}")
            )

the keyerror shows, because nlst is not on the menu class, now where do I need to put the code you give?

Elliot Garbus

unread,
Feb 10, 2021, 5:36:10 PM2/10/21
to kivy-...@googlegroups.com

I made an edit in the on_start routine.  There is a problem with the MDExpansionPanel.  As written Content() only supports one item.  I suspect you want an unlimited set of items there.  I’m not familiar enough with kivyMD to know if that is an option or not – but you can do those experiments. 

 

 

 

from kivy.lang import Builder
from kivymd.app import MDApp
from kivymd.uix.dialog import MDDialog
from kivymd.uix.list import OneLineListItem
from kivy.uix.screenmanager import Screen
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.expansionpanel import MDExpansionPanel, MDExpansionPanelTwoLine
from kivy.core.window import Window

Window.size = (
300, 500)


class GroceryApp(MDApp):

   
def __init__(self, **kwargs):
       
super().__init__(**kwargs)
       
self.list_items = []
       
self.category_list = ['Chicken', 'Pork', 'Beef', 'Fish', 'Vegetables']
       
self.dialog = None

       
self.card_file = {
           
'Recipes': [{'title': 'Chicken Adobo', 'shopping list': ['Fish', 'parchment paper', 'tomatoes']},
                        {
'title': 'Chicken Noodle Soup', 'shopping list': ['ground beef', 'cheese', 'buns']},
                        ]}

   
def build(self):
       
self.theme_cls.primary_palette = "Pink"
       
self.theme_cls.theme_style = "Dark"
       
return Builder.load_file('main.kv')

   
def on_start(self):
       
for category in self
.category_list:
           
if category == 'Chicken':
               
for recipe in self.card_file['Recipes']:
                    
print(recipe)
                    panel = MDExpansionPanel(
icon="recipe.png", content=Content(text=recipe['title']),
                                            
panel_cls=MDExpansionPanelTwoLine(text=category, secondary_text="Tap to view recipes"))
                    
self.root.ids.sm.get_screen('menu').ids.rlist.add_widget(panel)
           
else:
                panel = MDExpansionPanel(
icon="recipe.png", content=Content(text=recipe['title']),
                                        
panel_cls=MDExpansionPanelTwoLine(text=category,
                                                                          
secondary_text="Tap to view recipes"))
               
self.root.ids.sm.get_screen('menu').ids.rlist.add_widget(panel)

   
def showinfo(self, widget):
       
self.dialog = MDDialog(size_hint=(0.8, 0.8), text="Ingredients:", auto_dismiss=True)
       
self.dialog.open()

       
for recipe in self.card_file['Recipes']:
           
print(f"{recipe['shopping list']}")


class MenuScreen(Screen):
   
pass


class
Content(MDBoxLayout, OneLineListItem):
   
pass


GroceryApp().run()

 

 

 

 

 

 

From: John Zuriel
Sent: Wednesday, February 10, 2021 11:47 AM
To: Kivy users support
Subject: Re: [kivy-users] Re: How to load data to list using JSON

 

 Ok so here's a runnable example, and I change the dictionary to create a bit to example for "Chicken" category

Capture.PNG

ElliotG

unread,
Feb 10, 2021, 9:59:43 PM2/10/21
to Kivy users support
I made a few changes.  I changed Content() to be an MDList, and add the content as RecipeLines.... see the code.  There are still some rough edges here - but it gets you closer...

from kivy.lang import Builder
from kivymd.app import MDApp
from kivymd.uix.dialog import MDDialog
from kivy.uix.screenmanager import Screen
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.expansionpanel import MDExpansionPanel, MDExpansionPanelTwoLine
from kivymd.uix.list import MDList
from kivy.properties import StringProperty
from kivy.core.window import Window

Window.size = (300, 500)


class MenuScreen(Screen):
    pass


class Content(MDList):
    pass


class RecipeLine(MDBoxLayout):
    text = StringProperty()


class GroceryApp(MDApp):

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.list_items = []
        self.category_list = ['Chicken', 'Pork', 'Beef', 'Fish', 'Vegetables']
        self.dialog = None

        self.card_file = {
            'Chicken Recipes': [{'title': 'Chicken Adobo', 'shopping list': ['Fish', 'parchment paper', 'tomatoes']},
                        {'title': 'Chicken Noodle Soup', 'shopping list': ['ground beef', 'cheese', 'buns']},
                        ]}

    def build(self):
        self.theme_cls.primary_palette = "Pink"
        self.theme_cls.theme_style = "Dark"
        return Builder.load_file('main.kv')

    def on_start(self):
        for category in self.category_list:
            panel = MDExpansionPanel(icon="recipe.png", content=Content(),
                                     panel_cls=MDExpansionPanelTwoLine(text=category,
                                                                       secondary_text="Tap to view recipes"))
            self.root.ids.sm.get_screen('menu').ids.rlist.add_widget(panel)
            if category == 'Chicken':
                for recipe in self.card_file['Chicken Recipes']:
                    print(recipe)
                    rw = RecipeLine(text=recipe['title'])
                    self.root.ids.sm.get_screen('menu').ids.rlist.children[0].content.add_widget(rw)

    def showinfo(self, widget):
        self.dialog = MDDialog(size_hint=(0.8, 0.8), text="Ingredients:", auto_dismiss=True)
        self.dialog.open()

        for recipe in self.card_file['Chicken Recipes']:
            print(f"{recipe['shopping list']}")



GroceryApp().run()

=========== kv =====================

Screen:
    ScreenManager:
        id: sm
        MenuScreen:
            id: ms
            name: "menu"

#<Content>
#    id: nlst
#    adaptive_height: True
#    on_release: app.showinfo(nlst)
#    MDIconButton:
#        icon:'plus'


<RecipeLine>:
    adaptive_height: True
    OneLineListItem:
        text: root.text
        on_release: app.showinfo(None)
    MDIconButton:
        icon:'plus'




<MenuScreen>:
    BoxLayout:
        orientation: 'vertical'

        MDBottomNavigation:
            MDBottomNavigationItem:
                name: 'screen 2'
                text: 'Recipe'
                icon: 'food'

                ScrollView:
                    MDList:
                        id: rlist

John Zuriel

unread,
Feb 10, 2021, 10:45:23 PM2/10/21
to Kivy users support
I made an edit in the on_start routine.  There is a problem with the MDExpansionPanel.  As written Content() only supports one item.  I suspect you want an unlimited set of items there.  I’m not familiar enough with kivyMD to know if that is an option or not – but you can do those experiments.
owwww I see, i'm just reading the kivymdreadthedocs site on how to use the components, and copy the codes they use there unto my codes, so I thought I could use unlimited sets of item using that, hmmm that's a good info thank you, i''ll get back to you

Elliot Garbus

unread,
Feb 10, 2021, 10:50:04 PM2/10/21
to kivy-...@googlegroups.com
Look at the most recent code I sent - I was able to put an MDList in the Expansion panel. 

Sent from my iPhone

John Zuriel

unread,
Feb 10, 2021, 11:31:04 PM2/10/21
to Kivy users support
I don't know what's happening but after putting the code and running it, it just close like normal like when you close the window, it doesn't give any traceback or any error

Elliot Garbus

unread,
Feb 10, 2021, 11:42:03 PM2/10/21
to kivy-...@googlegroups.com
Did you get all the code?  The run() call?

Sent from my iPhone

On Feb 10, 2021, at 9:31 PM, John Zuriel <zuriel...@gmail.com> wrote:

I don't know what's happening but after putting the code and running it, it just close like normal like when you close the window, it doesn't give any traceback or any error

John Zuriel

unread,
Feb 10, 2021, 11:46:25 PM2/10/21
to Kivy users support
It works now i've accidently put unnecessary code, and is it possible to create a text file with the recipe list dictionary on it then load it into the app? since I will be like putting 10-15 recipes according to the category

Elliot Garbus

unread,
Feb 11, 2021, 8:48:50 AM2/11/21
to kivy-...@googlegroups.com

Yes you can start with a text file of recipes and use that to load into the app.

Some things to consider:  You could define a simple format that you use for each recipe that includes the category, title, ingredients… and write a program to format all of the recipes in the desired data structure.  Alternatively you could create an editor app that lets you load and edit a JSON file that has all of this data.

 

I would recommend combining the Categories with the recipes in a single data structure as in the example below, I included some code to show how you can parse this:

 

card_file = [{'Category': 'Chicken',
             
'Recipes': [{'title': 'Chicken Adobo', 'shopping list': ['Fish', 'parchment paper', 'tomatoes']},
                          {
'title': 'Chicken Noodle Soup', 'shopping list': ['ground beef', 'cheese', 'buns']},
                          ]
              },
             {
'Category': 'Pork',
             
'Recipes': [{'title': 'Pork Adobo', 'shopping list': ['Bacon', 'spices', 'tomatoes']},
                          {
'title': 'Pork Burger', 'shopping list': ['ground pork', 'cheese', 'buns']},
                          ]
              }]

print('The Card file is a list of catagories each with a list of recipes:')
for cat in card_file:
   
print(f'Card_file entry: {cat}')

print('\nAccess the Categories')
for cat in card_file:
   
print(cat['Category'])

print('\nRecipes per Catagory:')
for cat in card_file:
   
print(f'\nCategory: {cat["Category"]}')
   
for r in cat['Recipes']:
       
print(r)

print('\n Full details')
print('\nRecipes per Category:')
for cat in card_file:
   
print(f'\nCategory: {cat["Category"]}')
   
for r in cat['Recipes']:
       
print(f'Recipe: {r["title"]}')
       
for i, item in enumerate(r['shopping list']):
           
print(f'{i + 1}.\t {item}')
       
print()

 

 

From: John Zuriel
Sent: Wednesday, February 10, 2021 9:46 PM
To: Kivy users support
Subject: Re: [kivy-users] Re: How to load data to list using JSON

 

It works now i've accidently put unnecessary code, and is it possible to create a text file with the recipe list dictionary on it then load it into the app? since I will be like putting 10-15 recipes according to the category

now after putting this code to on_start since I'm trying to put the title to OneLineListItem widget.

John Zuriel

unread,
Feb 11, 2021, 10:27:09 AM2/11/21
to Kivy users support
Yes you can start with a text file of recipes and use that to load into the app.
I tried to make a recipe text file and put the dictionary you made
I can't seem to make it run with these code of yours, this is from my menuscreen that you edited too last time. it loads the files that saves when exiting the app, I tried this too but I don't know how to make it work, i keep getting errors and errors

    def on_start(self):  # Event handler that triggers when the application has started running
        # Loads the json file created after closing the app to
        p = Path('recipelist.txt')
        if p.exists():
            with open(p) as f:
                items = json.load(f)
                for item in items:
                    self.add_item(item)

Some things to consider:  You could define a simple format that you use for each recipe that includes the category, title, ingredients… and write a program to format all of the recipes in the desired data structure.  Alternatively you could create an editor app that lets you load and edit a JSON file that has all of this data.
Yes i've thought about that too, since the category is in another dictionary

I would recommend combining the Categories with the recipes in a single data structure as in the example below, I included some code to show how you can parse this:
Ok I will, I also added a pork recipes dictionary, its kinda same the one you given above
here is it:
1111.PNG
then added this on on_start to make it work
            if category == 'Pork':
                for recipe in self.card_file['Pork Recipes']:
                    rw = RecipeLine(text=recipe['title'])
                    self.root.ids.sm.get_screen('menu').ids.rlist.children[0].content.add_widget(rw)

but I really want to make the card_file dictiobary as text file so the code will not be messy.

Elliot Garbus

unread,
Feb 11, 2021, 10:59:02 AM2/11/21
to kivy-...@googlegroups.com

The example:

    def on_start(self):  # Event handler that triggers when the application has started running

        # Loads the json file created after closing the app to

        p = Path('recipelist.txt')

        if p.exists():

            with open(p) as f:

                items = json.load(f)

                for item in items:

                    self.add_item(item)

 

Assumes the stored data is a list. It will not work if the data is stored differently.

 

The nice thing about JSON is that is well defined and there are tools that parse it right into python data structures.  While the combinations of lists and dictionaries are a little complicated, it is quite a common technique.  Web APIs often return data formatted this way.

 

As I mention before, it might be worthwhile to write a simple editor that loads in a recipe file in JSON, and lets you edit/create data.

You could of course create your own format instead, and parse it as you like. 

Another option might be use a commas separated value file (CSV) see: https://docs.python.org/3/library/csv.html

Any spreadsheet can create CSV files, and you could create a simple template to build your recipes.  The disadvantage of this approach is the data would be flat – rather than hierarchical, but you could work around that as well.

 

From: John Zuriel
Sent: Thursday, February 11, 2021 8:27 AM
To: Kivy users support
Subject: Re: [kivy-users] Re: How to load data to list using JSON

 

Yes you can start with a text file of recipes and use that to load into the app.

I tried to make a recipe text file and put the dictionary you made

I can't seem to make it run with these code of yours, this is from my menuscreen that you edited too last time. it loads the files that saves when exiting the app, I tried this too but I don't know how to make it work, i keep getting errors and errors

 

    def on_start(self):  # Event handler that triggers when the application has started running

        # Loads the json file created after closing the app to

        p = Path('recipelist.txt')

        if p.exists():

            with open(p) as f:

                items = json.load(f)

                for item in items:

                    self.add_item(item)

 

Some things to consider:  You could define a simple format that you use for each recipe that includes the category, title, ingredients… and write a program to format all of the recipes in the desired data structure.  Alternatively you could create an editor app that lets you load and edit a JSON file that has all of this data.

Yes i've thought about that too, since the category is in another dictionary

 

I would recommend combining the Categories with the recipes in a single data structure as in the example below, I included some code to show how you can parse this:

Ok I will, I also added a pork recipes dictionary, its kinda same the one you given above

here is it:

1111.PNG

John Zuriel

unread,
Feb 11, 2021, 11:02:57 AM2/11/21
to Kivy users support
So I created a recipe_list.txt with the dictionary you give, now I don't know what's next since the code you give that loads a file with dictionary in it is pretty different to what i'm gonna do right now
1.png
here's the error after moving the card_file dictionary to text
2.png
since the card_file is not in the py.file anymore it gives error, so what to do to make this work again like before.

Elliot Garbus

unread,
Feb 11, 2021, 11:18:26 AM2/11/21
to kivy-...@googlegroups.com

Card_file is a python data structure, not a JSON data structre.

Create a program that writes card file to disk use the JSON module.  Then you will have a text file in JSON format.

In your program you can load that file with the JSON module, and it will be the same python data structure.

 

 

From: John Zuriel
Sent: Thursday, February 11, 2021 9:04 AM
To: Kivy users support
Subject: Re: [kivy-users] Re: How to load data to list using JSON

 

So I created a recipe_list.txt with the dictionary you give, now I don't know what's next since the code you give that loads a file with dictionary in it is pretty different to what i'm gonna do right now

here's the error after moving the card_file dictionary to text

since the card_file is not in the py.file anymore it gives error, so what to do to make this work again like before.

 

On Thursday, February 11, 2021 at 11:27:09 PM UTC+8 John Zuriel wrote:

Yes you can start with a text file of recipes and use that to load into the app.

I tried to make a recipe text file and put the dictionary you made

I can't seem to make it run with these code of yours, this is from my menuscreen that you edited too last time. it loads the files that saves when exiting the app, I tried this too but I don't know how to make it work, i keep getting errors and errors

 

    def on_start(self):  # Event handler that triggers when the application has started running

        # Loads the json file created after closing the app to

        p = Path('recipelist.txt')

        if p.exists():

            with open(p) as f:

                items = json.load(f)

                for item in items:

                    self.add_item(item)

 

Some things to consider:  You could define a simple format that you use for each recipe that includes the category, title, ingredients… and write a program to format all of the recipes in the desired data structure.  Alternatively you could create an editor app that lets you load and edit a JSON file that has all of this data.

Yes i've thought about that too, since the category is in another dictionary

 

I would recommend combining the Categories with the recipes in a single data structure as in the example below, I included some code to show how you can parse this:

Ok I will, I also added a pork recipes dictionary, its kinda same the one you given above

here is it:

1.png
2.png

John Zuriel

unread,
Feb 11, 2021, 11:24:23 AM2/11/21
to Kivy users support

Assumes the stored data is a list. It will not work if the data is stored differently.

ohhhh I thought it will work, since it work on my menuscreen.

The nice thing about JSON is that is well defined and there are tools that parse it right into python data structures.  While the combinations of lists and dictionaries are a little complicated, it is quite a common technique.  Web APIs often return data formatted this way.

As I mention before, it might be worthwhile to write a simple editor that loads in a recipe file in JSON, and lets you edit/create data.

You could of course create your own format instead, and parse it as you like. 

Thank you for another information, I'm still kinda new to dictionaries but i'm getting the grasp on it, so for now it's best to put the card_file on py file right?

Elliot Garbus

unread,
Feb 11, 2021, 11:57:07 AM2/11/21
to kivy-...@googlegroups.com

Of course it is fine to keep things in python for now.

 

 

From: John Zuriel
Sent: Thursday, February 11, 2021 9:25 AM
To: Kivy users support
Subject: Re: [kivy-users] Re: How to load data to list using JSON

 

Assumes the stored data is a list. It will not work if the data is stored differently.

ohhhh I thought it will work, since it work on my menuscreen.

The nice thing about JSON is that is well defined and there are tools that parse it right into python data structures.  While the combinations of lists and dictionaries are a little complicated, it is quite a common technique.  Web APIs often return data formatted this way.

As I mention before, it might be worthwhile to write a simple editor that loads in a recipe file in JSON, and lets you edit/create data.

You could of course create your own format instead, and parse it as you like. 

Thank you for another information, I'm still kinda new to dictionaries but i'm getting the grasp on it, so for now it's best to put the card_file on py file right?

On Friday, February 12, 2021 at 12:02:57 AM UTC+8 John Zuriel wrote:

So I created a recipe_list.txt with the dictionary you give, now I don't know what's next since the code you give that loads a file with dictionary in it is pretty different to what i'm gonna do right now

here's the error after moving the card_file dictionary to text

since the card_file is not in the py.file anymore it gives error, so what to do to make this work again like before.

 

On Thursday, February 11, 2021 at 11:27:09 PM UTC+8 John Zuriel wrote:

Yes you can start with a text file of recipes and use that to load into the app.

I tried to make a recipe text file and put the dictionary you made

I can't seem to make it run with these code of yours, this is from my menuscreen that you edited too last time. it loads the files that saves when exiting the app, I tried this too but I don't know how to make it work, i keep getting errors and errors

 

    def on_start(self):  # Event handler that triggers when the application has started running

        # Loads the json file created after closing the app to

        p = Path('recipelist.txt')

        if p.exists():

            with open(p) as f:

                items = json.load(f)

                for item in items:

                    self.add_item(item)

 

Some things to consider:  You could define a simple format that you use for each recipe that includes the category, title, ingredients… and write a program to format all of the recipes in the desired data structure.  Alternatively you could create an editor app that lets you load and edit a JSON file that has all of this data.

Yes i've thought about that too, since the category is in another dictionary

 

I would recommend combining the Categories with the recipes in a single data structure as in the example below, I included some code to show how you can parse this:

Ok I will, I also added a pork recipes dictionary, its kinda same the one you given above

here is it:

John Zuriel

unread,
Feb 11, 2021, 12:05:12 PM2/11/21
to Kivy users support
I have manage to parse and display the category with the updated card file dictionary, now I'm having a problem on the recipes inside it.
Capture.PNG

"Unexpected type(s):(str)Possible type(s):(int)(slice)" this is the warning on line 60, i tried deleting it, the warning is gone, but nothing is showing on the list

Elliot Garbus

unread,
Feb 11, 2021, 12:28:30 PM2/11/21
to kivy-...@googlegroups.com

Look at how the code is parsed the in standalone example:

 

card_file = [{'Category': 'Chicken',
             
'Recipes': [{'title': 'Chicken Adobo', 'shopping list': ['Fish', 'parchment paper', 'tomatoes']},
                          {
'title': 'Chicken Noodle Soup', 'shopping list': ['ground beef', 'cheese', 'buns']},
                          ]
              },
             {
'Category': 'Pork',
             
'Recipes': [{'title': 'Pork Adobo', 'shopping list': ['Bacon', 'spices', 'tomatoes']},
                          {
'title': 'Pork Burger', 'shopping list': ['ground pork', 'cheese', 'buns']},
                          ]
              }]

print('\nFull details')
print('\nRecipes per Category:')
for cat in card_file:
   
print(f'\nCategory: {cat["Category"]}')
   
for r in cat['Recipes']:
       
print(f'Recipe: {r["title"]}')
       
for i, item in enumerate(r['shopping list']):
           
print(f'{i + 1}.\t {item}')
       
print()

 

 

From: John Zuriel
Sent: Thursday, February 11, 2021 10:05 AM
To: Kivy users support
Subject: Re: [kivy-users] Re: How to load data to list using JSON

 

I have manage to parse and display the category with the updated card file dictionary, now I'm having a problem on the recipes inside it.


"Unexpected type(s):(str)Possible type(s):(int)(slice)" this is the warning on line 60, i tried deleting it, the warning is gone, but nothing is showing on the list

On Friday, February 12, 2021 at 12:24:23 AM UTC+8 John Zuriel wrote:

Assumes the stored data is a list. It will not work if the data is stored differently.

ohhhh I thought it will work, since it work on my menuscreen.

The nice thing about JSON is that is well defined and there are tools that parse it right into python data structures.  While the combinations of lists and dictionaries are a little complicated, it is quite a common technique.  Web APIs often return data formatted this way.

As I mention before, it might be worthwhile to write a simple editor that loads in a recipe file in JSON, and lets you edit/create data.

You could of course create your own format instead, and parse it as you like. 

Thank you for another information, I'm still kinda new to dictionaries but i'm getting the grasp on it, so for now it's best to put the card_file on py file right?

On Friday, February 12, 2021 at 12:02:57 AM UTC+8 John Zuriel wrote:

So I created a recipe_list.txt with the dictionary you give, now I don't know what's next since the code you give that loads a file with dictionary in it is pretty different to what i'm gonna do right now

here's the error after moving the card_file dictionary to text

since the card_file is not in the py.file anymore it gives error, so what to do to make this work again like before.

 

On Thursday, February 11, 2021 at 11:27:09 PM UTC+8 John Zuriel wrote:

Yes you can start with a text file of recipes and use that to load into the app.

I tried to make a recipe text file and put the dictionary you made

I can't seem to make it run with these code of yours, this is from my menuscreen that you edited too last time. it loads the files that saves when exiting the app, I tried this too but I don't know how to make it work, i keep getting errors and errors

 

    def on_start(self):  # Event handler that triggers when the application has started running

        # Loads the json file created after closing the app to

        p = Path('recipelist.txt')

        if p.exists():

            with open(p) as f:

                items = json.load(f)

                for item in items:

                    self.add_item(item)

 

Some things to consider:  You could define a simple format that you use for each recipe that includes the category, title, ingredients… and write a program to format all of the recipes in the desired data structure.  Alternatively you could create an editor app that lets you load and edit a JSON file that has all of this data.

Yes i've thought about that too, since the category is in another dictionary

 

I would recommend combining the Categories with the recipes in a single data structure as in the example below, I included some code to show how you can parse this:

Ok I will, I also added a pork recipes dictionary, its kinda same the one you given above

here is it:

Capture.PNG

John Zuriel

unread,
Feb 11, 2021, 12:54:55 PM2/11/21
to Kivy users support
It works now, the only problem now is when clicking a recipe it shows all the ingredients instead of only the one that's been clicked
Capture.PNG
and is it possible to show the only ingredients without the numbers?

Elliot Garbus

unread,
Feb 11, 2021, 1:16:55 PM2/11/21
to kivy-...@googlegroups.com
        for i, item in enumerate(r['shopping list']):
           
print(f'{i + 1}.\t {item}')
Remove I and enumerate, and  use item 

Sent from my iPad

On Feb 11, 2021, at 10:55 AM, John Zuriel <zuriel...@gmail.com> wrote:

It works now, the only problem now is when clicking a recipe it shows all the ingredients instead of only the one that's been clicked

John Zuriel

unread,
Feb 11, 2021, 1:44:23 PM2/11/21
to Kivy users support
Got that already thanks, how bout when clicking a recipe it shows all the ingredients instead of only the one that's been clickedCapture.PNG

Elliot Garbus

unread,
Feb 11, 2021, 5:29:03 PM2/11/21
to kivy-...@googlegroups.com

I’m not sure I understand your question…

Assuming you want to show a list of ingredients on a Dialog, you would need to add custom content to the Dialog, Create a ScrollView with an MDList and add a list item for each ingredient.  This is similar to how the list of recipes is added as widgets to the list under the categories.

 

From: John Zuriel
Sent: Thursday, February 11, 2021 11:44 AM
To: Kivy users support
Subject: Re: [kivy-users] Re: How to load data to list using JSON

 

Got that already thanks, how bout when clicking a recipe it shows all the ingredients instead of only the one that's been clicked

Capture.PNG

John Zuriel

unread,
Feb 11, 2021, 9:04:08 PM2/11/21
to Kivy users support
I’m not sure I understand your question…
this is what I'm saying, when you click the recipe, all of the shopping list is printing instead of only their own shopping list
Capture.PNG

Assuming you want to show a list of ingredients on a Dialog, you would need to add custom content to the Dialog, Create a ScrollView with an MDList and add a list item for each ingredient.  This is similar to how the list of recipes is added as widgets to the list under the categories.
yeaaaah, that's what I'm gonna do thanks again, so I really need to solve the last problem, please see the photo

Elliot Garbus

unread,
Feb 11, 2021, 9:37:12 PM2/11/21
to kivy-...@googlegroups.com
Share your code, or the code your calling when the recipe is pressed. 

Sent from my iPhone

On Feb 11, 2021, at 7:04 PM, John Zuriel <zuriel...@gmail.com> wrote:

I’m not sure I understand your question…
this is what I'm saying, when you click the recipe, all of the shopping list is printing instead of only their own shopping list

John Zuriel

unread,
Feb 11, 2021, 9:42:41 PM2/11/21
to Kivy users support
Here it is:
in py:
    def showinfo(self, widget):
        close_button = MDFlatButton(text="Done", on_release=self.close_dialog)
        self.dialog = MDDialog(size_hint=(0.8, 0.8), text="Ingredients:", auto_dismiss=True, buttons=[close_button])
        self.dialog.open()

        for category in self.card_file:
            for recipe in category['Recipes']:
                for item in (recipe['shopping list']):
                    print(f'{item}')

in kv:
<RecipeLine>:
    adaptive_height: True
    OneLineListItem:
        text: root.text
        on_release: app.showinfo(None)



Elliot Garbus

unread,
Feb 12, 2021, 7:36:50 AM2/12/21
to kivy-...@googlegroups.com

You want something more like this:

card_file = [{'Category': 'Chicken',
             
'Recipes': [{'title': 'Chicken Adobo', 'shopping list': ['Fish', 'parchment paper', 'tomatoes']},
                          {
'title': 'Chicken Noodle Soup', 'shopping list': ['ground beef', 'cheese', 'buns']},
                          ]
              },
             {
'Category': 'Pork',
             
'Recipes': [{'title': 'Pork Adobo', 'shopping list': ['Bacon', 'spices', 'tomatoes']},
                          {
'title': 'Pork Burger', 'shopping list': ['ground pork', 'cheese', 'buns']},
                          ]
              }]

def print_shopping_list(cat, recipe):
   
for c in card_file:
       
if c['Category'] == cat:
           
for r in c['Recipes']:
               
if r['title'] == recipe:
                   
print(r['shopping list'])

print_shopping_list(
'Pork', 'Pork Burger')

At the risk of being more confusing.  This data structure was put together to save and restore the state of widgets.  You could create a different data structure for more efficient look ups.  This is not likely to ever be an issue in the scope of this application. 

 

From: John Zuriel
Sent: Thursday, February 11, 2021 7:42 PM
To: Kivy users support
Subject: Re: [kivy-users] Re: How to load data to list using JSON

 

Here it is:

On Friday, February 12, 2021 at 2:16:55 AM UTC+8 ElliotG wrote:

John Zuriel

unread,
Feb 12, 2021, 8:53:23 AM2/12/21
to Kivy users support
card_file = [{'Category''Chicken',
              'Recipes': [{'title''Chicken Adobo''shopping list': ['Fish''parchment paper''tomatoes']},
                          {'title''Chicken Noodle Soup''shopping list': ['ground beef''cheese''buns']},
                          ]
              },
             {'Category''Pork',
              'Recipes': [{'title''Pork Adobo''shopping list': ['Bacon''spices''tomatoes']},
                          {'title''Pork Burger''shopping list': ['ground pork''cheese''buns']},
                          ]
              }]

this structure is what I'm currently using right now,

as for this, i'm gonna try to apply it on my code

def print_shopping_list(cat, recipe):
    for c in card_file:
        if c['Category'] == cat:
            for r in c['Recipes']:
                if r['title'] == recipe:
                    print(r['shopping list'])

print_shopping_list('Pork''Pork Burger') but this how can I apply it to the list when I click since its fixed value here?

Elliot Garbus

unread,
Feb 12, 2021, 9:12:15 AM2/12/21
to kivy-...@googlegroups.com

When you click on the item in the list the text (self.text) is the recipe title.

You can access the widget tree to get the category that the RecipeLine is under.

 

Alternatively  create a new attribute and save the category in the RecipeLine when it is created.  That way you can use it to easily look up the ingredients. 

 

<RecipeLine>:
    adaptive_height: True
    OneLineListItem:
       
text: root.
text
       
on_release: app.showinfo(root.parent.parent.panel_cls.text, self.text)
    MDIconButton:
        icon:
'plus'

John Zuriel

unread,
Feb 12, 2021, 9:15:41 AM2/12/21
to Kivy users support
So here's the method when clicking the list a dialog box will show

    def showinfo(self, widget):
        close_button = MDFlatButton(text="Done", on_release=self.close_dialog)
        self.dialog = MDDialog(size_hint=(0.8, 0.8), text="Ingredients:", content=AnotherContent(), auto_dismiss=True,
                               buttons=[close_button])
        self.dialog.open()

class AnotherContent(MDList):
    pass

and for the custom content what will I put on kv, the AnotherContent? or create another like the <RecipeLine> you make on kv that use in py file?
here it is:

            for recipe in category['Recipes']:
                rw = RecipeLine(text=recipe['title'])
                self.root.ids.sm.get_screen('menu').ids.rlist.children[0].content.add_widget(rw)

<RecipeLine>: #Do I need to create something like this and put the MDList and scrollview?
    adaptive_height: True
    OneLineListItem:
        text: root.text
        on_release: app.showinfo(None)

John Zuriel

unread,
Feb 12, 2021, 9:26:44 AM2/12/21
to Kivy users support
Alternatively  create a new attribute and save the category in the RecipeLine when it is created.  That way you can use it to easily look up the ingredients. 

<RecipeLine>:
    adaptive_height: True
    OneLineListItem:
        text: root.
text
        on_release: app.showinfo(root.parent.parent.panel_cls.text, self.text)
    MDIconButton:
        icon:'plus'

I'm getting a bit confused here, and also I remove the + button beside the list, I have an idea that its better to put an add button instead inside the dialog box for me to add the ingredients to the list

Elliot Garbus

unread,
Feb 12, 2021, 9:26:58 AM2/12/21
to kivy-...@googlegroups.com

I suspect our emails crossed…

    def showinfo(self, category, recipe):

        close_button = MDFlatButton(text="Done", on_release=self.close_dialog)

        # instance the content…

        ing = IngContent(items=ingredient_list(category, recipe))    # ingredient_list returns a list of the ingredients..

        self.dialog = MDDialog(size_hint=(0.8, 0.8), text="Ingredients:", content=ing, auto_dismiss=True,

                               buttons=[close_button])

        self.dialog.open()

 

Create IngContent with a Listproperty(), items.  And display the items as you like.(ScrollView and MDList would work).

John Zuriel

unread,
Feb 12, 2021, 10:02:55 AM2/12/21
to Kivy users support
It seems not working on me, I'm getting a "TypeError: showinfo() missing 1 required positional argument: 'recipe'"
here's the code:

py:
from kivy.lang import Builder
from kivymd.app import MDApp
from kivymd.uix.button import MDFlatButton
from kivymd.uix.dialog import MDDialog
from kivy.uix.screenmanager import Screen
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.expansionpanel import MDExpansionPanel, MDExpansionPanelTwoLine
from kivymd.uix.list import MDList
from kivy.properties import StringProperty, ListProperty
from kivy.core.window import Window

Window.size = (300, 500)


class MenuScreen(Screen):
    pass


class Content(MDList):
    pass


class AnotherContent(MDList):
    pass


class RecipeLine(MDBoxLayout):
    text = StringProperty()


class IngContent:
    items = ListProperty


class GroceryApp(MDApp):

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.list_items = []
        self.dialog = None

        self.card_file = [{'Category': 'Chicken',
                           'Recipes': [
                               {'title': 'Chicken Adobo', 'shopping list': ['Fish', 'parchment paper', 'tomatoes']},
                               {'title': 'Chicken Noodle Soup', 'shopping list': ['ground beef', 'cheese', 'buns']}
                           ]
                           },

                          {'Category': 'Pork',
                           'Recipes': [
                               {'title': 'Pork Adobo', 'shopping list': ['Bacon', 'spices', 'tomatoes']},
                               {'title': 'Pork Burger', 'shopping list': ['ground pork', 'cheese', 'buns']}
                           ]
                           }]

    def build(self):
        self.theme_cls.primary_palette = "Pink"
        self.theme_cls.theme_style = "Dark"
        return Builder.load_file('main.kv')

    def on_start(self):
        for category in self.card_file:
            panel = MDExpansionPanel(icon="recipe.png", content=Content(),
                                     panel_cls=MDExpansionPanelTwoLine(text=category['Category'],
                                                                       secondary_text="Tap to view recipes"))
            self.root.ids.sm.get_screen('menu').ids.rlist.add_widget(panel)

            for recipe in category['Recipes']:
                rw = RecipeLine(text=recipe['title'])
                self.root.ids.sm.get_screen('menu').ids.rlist.children[0].content.add_widget(rw)

    def showinfo(self, category, recipe):
        close_button = MDFlatButton(text="Done", on_release=self.close_dialog)
        add_button = MDFlatButton(text="Add to list", on_release=self.close_dialog)

        for c in self.card_file:
            if c['Category'] == category:
                for r in c['Recipes']:
                    if r['title'] == recipe:
                        print(r['shopping list'])

        ing = IngContent(items=ingredient_list(category, recipe))  # I'm also getting unresolved reference on ingredient_list
        self.dialog = MDDialog(size_hint=(0.8, 0.8), text="Ingredients:", content=ing, auto_dismiss=True,
                               buttons=[close_button, add_button])
        self.dialog.open()

    def close_dialog(self, obj):  # Method that close the dialog box
        self.dialog.dismiss()


GroceryApp().run()

kv:
Screen:
    ScreenManager:
        id: sm
        MenuScreen:
            id: ms
            name: "menu"

<RecipeLine>:
    adaptive_height: True
    OneLineListItem:
        text: root.text
        on_release: app.showinfo(None)

<IngContent>:
    ScrollView:
        MDList:
            id: ilist

<MenuScreen>:
    BoxLayout:
        orientation: 'vertical'

        MDBottomNavigation:
            MDBottomNavigationItem:
                name: 'screen 2'
                text: 'Recipe'
                icon: 'food'

                ScrollView:
                    MDList:
                        id: rlist

Elliot Garbus

unread,
Feb 12, 2021, 10:07:24 AM2/12/21
to kivy-...@googlegroups.com

In your kv code:

<RecipeLine>:

    adaptive_height: True

    OneLineListItem:

        text: root.text

        # on_release: app.showinfo(None)

        on_release: app.showinfo(root.parent.parent.panel_cls.text, self.text)

John Zuriel

unread,
Feb 12, 2021, 10:15:13 AM2/12/21
to Kivy users support
ohhhh, it gives me unresolved reference "ingredient_list" error now

    def showinfo(self, category, recipe):
        close_button = MDFlatButton(text="Done", on_release=self.close_dialog)
        add_button = MDFlatButton(text="Add to list", on_release=self.close_dialog)

        for c in self.card_file:
            if c['Category'] == category:
                for r in c['Recipes']:
                    if r['title'] == recipe:
                        print(r['shopping list'])

        ing = IngContent(items=ingredient_list(category, recipe))
        self.dialog = MDDialog(size_hint=(0.8, 0.8), text="Ingredients:", content=ing, auto_dismiss=True,
                               buttons=[close_button, add_button])
        self.dialog.open()

Elliot Garbus

unread,
Feb 12, 2021, 10:25:31 AM2/12/21
to kivy-...@googlegroups.com
You need to write the method ingredients_list()
That is passed The category in the recipe title and returns the ingredients list


Sent from my iPhone

On Feb 12, 2021, at 8:16 AM, John Zuriel <zuriel...@gmail.com> wrote:

ohhhh, it gives me unresolved reference "ingredient_list" error now

John Zuriel

unread,
Feb 12, 2021, 10:44:51 AM2/12/21
to Kivy users support
I think I'm doing it wrong, if I add self on ingredients_list it gives me "Unresolved attribute reference 'ingredient_list' for class 'GroceryApp'" and unexpected argument is showing too
Capture.PNG
    def showinfo(self, category, recipe):
        close_button = MDFlatButton(text="Done", on_release=self.close_dialog)
        add_button = MDFlatButton(text="Add to list", on_release=self.close_dialog)

        for c in self.card_file:
            if c['Category'] == category:
                for r in c['Recipes']:
                    if r['title'] == recipe:
                        print(r['shopping list'])

        ing = IngContent(items=self.ingredient_list(category, recipe))
        self.dialog = MDDialog(size_hint=(0.8, 0.8), text="Ingredients:", content=ing, auto_dismiss=True,
                               buttons=[close_button, add_button])
        self.dialog.open()

    def ingredients_list(self, category, recipe):
        pass
Message has been deleted

John Zuriel

unread,
Feb 12, 2021, 2:27:22 PM2/12/21
to Kivy users support
so I misspelled there, now I must create a method like this right? but still it gives an Unresolved reference 'ingredient_list'
py:
    def ingredient_list(category, recipe):
        pass

    def showinfo(self, category, recipe):
        close_button = MDFlatButton(text="Done", on_release=self.close_dialog)
        add_button = MDFlatButton(text="Add to list", on_release=self.close_dialog)

        for c in self.card_file:
            if c['Category'] == category:
                for r in c['Recipes']:
                    if r['title'] == recipe:
                        print(r['shopping list'])

        ing = IngContent(items=ingredient_list(category, recipe)) # and in here an Unexpected argument error
        self.dialog = MDDialog(size_hint=(0.8, 0.8), text="Ingredients:", content=ing, auto_dismiss=True,
                               buttons=[close_button, add_button])
        self.dialog.open()'
kv:
<IngContent>:
    ScrollView:
        MDList:
            id: ilist

Capture.PNG
Message has been deleted
Message has been deleted
Message has been deleted
Message has been deleted
Message has been deleted

Elliot Garbus

unread,
Feb 13, 2021, 2:09:22 PM2/13/21
to kivy-...@googlegroups.com

Here is a version that puts the ingredients in a dialog box.  This includes creating the button in on_start from the updated dictionary.

 

From: John Zuriel
Sent: Friday, February 12, 2021 12:27 PM
To: Kivy users support
Subject: Re: [kivy-users] Re: How to load data to list using JSON

 

so I misspelled there, now I must create a method like this right? but still it gives an Unresolved reference 'ingredient_list'

py:

    def ingredient_list(category, recipe):

        pass

 

    def showinfo(self, category, recipe):

        close_button = MDFlatButton(text="Done", on_release=self.close_dialog)

        add_button = MDFlatButton(text="Add to list", on_release=self.close_dialog)

 

        for c in self.card_file:

            if c['Category'] == category:

                for r in c['Recipes']:

                    if r['title'] == recipe:

                        print(r['shopping list'])

 

        ing = IngContent(items=ingredient_list(category, recipe)) # and in here an Unexpected argument error

        self.dialog = MDDialog(size_hint=(0.8, 0.8), text="Ingredients:", content=ing, auto_dismiss=True,

                               buttons=[close_button, add_button])

        self.dialog.open()'

kv:

<IngContent>:

    ScrollView:

        MDList:

            id: ilist

 

On Friday, February 12, 2021 at 11:44:51 PM UTC+8 John Zuriel wrote:

I think I'm doing it wrong, if I add self on ingredients_list it gives me "Unresolved attribute reference 'ingredient_list' for class 'GroceryApp'" and unexpected argument is showing too

main.zip
Capture.PNG
Reply all
Reply to author
Forward
0 new messages