Обработка и хранение данных / подсказка к 3 задачке

3

Добавить на форму поле для ввода позиции, в которую вставлять очередной элемент списка.

  • Если поле пустое то вставлять в конец файла
  • Если там 0, то в начало
  • если 1 – на вторую позицию
  • и т. д.

Попробуем теперь поработать со списком словариков. Допустим мы делаем программу с помощью которой можно формировать списки студентов. А сами списки чтобы можно было хранить в файле. Как бы мы могли это сделать?

Начнем с кода похожий на тот что был в прошлом задании:

from tkinter import *
import json

# это просто чтобы создавать поля для ввода
def create_entry(x, y, label_text, entry_width):
    label = Label(gui, text=label_text)
    label.place(x=x, y=y)
    gui.update()
    
    entry = Entry(gui)
    entry.place(x=x + label.winfo_width() + 10, y=y, width=entry_width)
    gui.update() # еще раз обновим интерфейс
    
    return entry # вернем метку

class UI():
    def __init__(self, gui):    
        gui.geometry("400x150")
        
        # тут три поля под имя, фамилию, группу
        self.name = create_entry(10, 10, "Имя", 120)
        self.last_name = create_entry(10, 40, "Фамилия", 120)
        self.group = create_entry(10, 70, "Группа", 120)
        
        # кнопочка чтобы в файл сохранять
        self.button = Button(text="Сохранить в файл", command=self.save_to_file)
        self.button.place(x=10, y=100)
    
    # собственно реакция на кнопочку для сохранения в файл
    def save_to_file(self):
        data = {
            "name": self.name.get(), 
            "last_name": self.last_name.get(),
            "group": self.group.get(),            
        }
        
        with open("user.json", "w", encoding="utf8") as f:
            json.dump(data, f, ensure_ascii=False, indent=2)
     

gui = Tk()
UI(gui)
gui.mainloop()

сейчас при попытке сохранить в файла она будет постоянно перезаписывать данные

поэтому надо как-то научится там делать сразу несколько записей.

Идея заключается в том, что мы вместо того чтобы хранить одну запись будем хранить список записей.

Можно для начала попробовать запихать в файлик просто список с одной записью:

class UI():
    def __init__(self, gui):    
        # ...
          
    def save_to_file(self):
        # data это теперь список, внутри которого лежит один словарик: 
        data = [
            {
                "name": self.name.get(), 
                "last_name": self.last_name.get(),
                "group": self.group.get(),            
            }
        ]
        
        with open("user.json", "w", encoding="utf8") as f:
            json.dump(data, f, ensure_ascii=False, indent=2)

теперь если на кнопочку кликнуть, то увидим, что внутри там стал тоже список, только уже с заполненными значениями

попробуем теперь немного реструктурировать код. Ведь по идее когда мы первый раз запустили программу список у нас пустой, а потому по клику мы добавляем в список нового студента. С точки зрения кода — это можно записать так:

class UI():
    def __init__(self, gui):    
        # ...
          
    def save_to_file(self):
        data = [] # создали пустой список
        
        data.append( # добавили в него элемент
            {
                "name": self.name.get(), 
                "last_name": self.last_name.get(),
                "group": self.group.get(),            
            }
        )
        
        # перезаписываем файл
        with open("user.json", "w", encoding="utf8") as f:
            json.dump(data, f, ensure_ascii=False, indent=2)

работать это правда все равно будет так же, потому что наша кнопка при клике

поэтому нам надо сделать так чтобы при клике на кнопку:

пишем код:

class UI():
    def __init__(self, gui):    
        # ...
          
    def save_to_file(self):
        # заружаем список из файла
        with open("user.json", encoding="utf8") as f:
            data = json.load(f) # кладем его в переменную data
        
        # добавляем в этот список данные с формы
        data.append(
            {
                "name": self.name.get(), 
                "last_name": self.last_name.get(),
                "group": self.group.get(),            
            }
        )
        
        # сохраняем обновленный список в файл
        with open("user.json", "w", encoding="utf8") as f:
            json.dump(data, f, ensure_ascii=False, indent=2)

проверяем:

чудеса =О

Кстати у нас получается, что добавление идет всегда в конец файла, можно в принципе сделать чтобы добавление шло в начало списка.

Для этого надо добавлять элемент в список следующим образом:

class UI():
    def __init__(self, gui):    
        # ...
          
    def save_to_file(self):
        with open("user.json", encoding="utf8") as f:
            data = json.load(f)
       
        # использую метод insert, у него первый параметр — это куда вставлять элемент, 
        # если указать 0 то будет вставлять элемент на первую позицию в списке
        # если указать 1 то будет вставлять элемент на вторую позицию и т.д.
        data.insert(0, {
            "name": self.name.get(), 
            "last_name": self.last_name.get(),
            "group": self.group.get(),            
        })
        
        with open("user.json", "w", encoding="utf8") as f:
            json.dump(data, f, ensure_ascii=False, indent=2)