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

#r #shiny #local-storage #user-input

#r #блестящий #локальное хранилище #пользовательский ввод

Вопрос:

Я работаю с пакетом DTedit и хотел бы реализовать две функциональные возможности. Я прилагаю пример кода из github автора пакета. Две вещи, которые я хотел бы реализовать, это:

  • кнопка, которая сохраняет данные после любых новых добавлений или модификаций таблицы в локальный файл. В идеале мы можем добавлять все новые дополнения (или редакции) в существующий CSV-файл. Приложение будет находиться на сервере rstudio, поэтому мы можем добавить этот файл в папку www.

  • Вторая функциональность заключается в том, что приложение должно извлекать данные из csv и показывать их, когда пользователь открывает приложение, вместо отображения пустой таблицы, подобной той, что была в предыдущем коде.

Я перепробовал несколько вариантов и просмотрел несколько руководств в Интернете, но не смог решить эти два вопроса.

 library(shiny)
library(DTedit)

##### Create the Shiny server
server <- function(input, output) {
    mydata <- data.frame(name = character(),
                         email = character(),
                         useR = factor(levels = c('Yes', 'No')),
                         notes = character(),
                         stringsAsFactors = FALSE)

    ##### Callback functions.
    my.insert.callback <- function(data, row) {
        mydata <- rbind(data, mydata)
        return(mydata)
    }

    my.update.callback <- function(data, olddata, row) {
        mydata[row,] <- data[1,]
        return(mydata)
    }

    my.delete.callback <- function(data, row) {
        mydata <- mydata[-row,]
        return(mydata)
    }

    ##### Create the DTedit object
    DTedit::dtedit(input, output,
           name = 'mycontacts',
           thedata = mydata,
           edit.cols = c('name', 'email', 'useR', 'notes'),
           edit.label.cols = c('Name', 'Email Address', 'Are they an R user?', 'Additional notes'),
           input.types = c(notes='textAreaInput'),
           view.cols = c('name', 'email', 'useR'),
           callback.update = my.update.callback,
           callback.insert = my.insert.callback,
           callback.delete = my.delete.callback)
}

##### Create the shiny UI
ui <- fluidPage(
    h3('DTedit Template'),
    uiOutput('mycontacts')
)

##### Start the shiny app
shinyApp(ui = ui, server = server)
  

Комментарии:

1. Я предлагаю вам рассмотреть блестящее постоянное хранилище или блестящие закладки .

2. Я вижу потенциальные проблемы с хранилищем в локальном файле, подобном этому: одновременный доступ; разрешения на доступ (случайное совместное использование / утечка между пользователями); обновите приложение и забудьте перенести исторические CSV. Решение sqlite (включенное в первую ссылку выше) работает лучше, чем отдельные файлы, хотя оно предполагает DBI ориентированный подход к вашим данным. Создание закладок (вторая ссылка) решает большинство этих проблем по своей сути. Для вас это были просто предложения.

3. Я понимаю. Будет ли электронная таблица dropbox / Google лучшим вариантом? Закладка кажется хорошей идеей, но для этого потребуется, чтобы URL-адрес всегда был одним и тем же. Я считаю, что добавление закладок создает новый адрес из того, что я мог прочитать

4. «Лучший» — это чисто субъективно. Я не знаю, как выглядит ваша существующая инфраструктура, ни как выглядит полный вариант использования и пользовательская база. Если он будет использоваться одним человеком несколько раз в течение следующих двух недель и, вероятно, никогда больше, то файлов внутри www/ может быть достаточно. Если он будет использоваться несколькими людьми и / или в течение более длительного периода, то я мог бы склониться к sqlite . Если вы находитесь в распределенной среде, у вас больше пользователей и / или факторами являются долгосрочное обслуживание и показатели, то лучше всего использовать более надежное решение, такое как SQL server, NoSQL (например, redis) сервер и т.д.

5. Я понимаю. Спасибо.

Ответ №1:

Я поддержу предложения, уже высказанные в комментариях, о том, что хранение в базе данных, такой как sqlite (или даже airtable , для которой существуют интерфейсы R, если данные не особенно чувствительны), является лучшим решением.

В этом случае вы можете использовать dtedit обратные вызовы для сохранения данных в базе данных, как показано в dtedit демонстрационном приложении в DTedit репозитории github.

Ответ на конкретный первый пункт для ‘кнопки, которая сохраняет данные после любых новых добавлений или модификаций таблицы в локальный файл. В идеале мы можем добавлять все новые дополнения (или редакции) к существующему файлу CSV’, DT (на котором DTedit основан) имеет функциональность для сохранения текущей таблицы в файл CSV или Excel.

Я не думаю, что это лучшая идея в вашем случае, ваше приложение по-прежнему будет отвечать за «повторную загрузку» этих данных при запуске приложения, и, как говорят другие, только один пользователь может выполнять запись в файл CSV / Excel одновременно. Кроме того, локальное сохранение CSV-файла обычно не выполняется в www/ папке пакета!

Тем не менее, если сохранение CSV-файла является решением быстрого взлома, которое подходит приложению, то его можно изменить, DTedit передав необходимые аргументы в DT , чтобы были доступны кнопки сохранения CSV / Excel. Я и другие внесли изменения DTedit позволяющие передавать аргументы в DT::datatable , измененная версия DTedit доступна на Github. Виньетка, показывающая добавление кнопок «Сохранить», доступна на RPubs и воспроизведена ниже.

 library(DTedit)

server <- function(input, output) {
  
  Grocery_List_Results <- dtedit(
    input, output,
    name = 'Grocery_List',
    thedata = data.frame(
      Buy = c('Tea', 'Biscuits', 'Apples'),
      Quantity = c(7, 2, 5),
      stringsAsFactors = FALSE
    ),
    datatable.call = function(...)
      {DT::datatable(..., extensions = 'Buttons')},
    datatable.options = list(
      dom = 'Bfrtip',
      buttons = c('copy', 'csv', 'pdf', 'excel')
    )
  )
}

ui <- fluidPage(
    h3('Grocery List'),
    uiOutput('Grocery_List')
)

shinyApp(ui = ui, server = server)
  

Изображение таблицы данных с кнопками копирования / сохранения