• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

question-closed Python + Django + PANDAS - jak przepuscic plik z formularza przez skrypt pandas.

Object Storage Arubacloud
0 głosów
418 wizyt
pytanie zadane 28 sierpnia 2020 w Python przez Ventre90 Obywatel (1,170 p.)
zamknięte 3 września 2020 przez Ventre90

Cześć wszystkim,

Pisze aplikacje web która ma przerobić uploadowany plik .xlsx za pomocą skryptu PANDAS.

Chciałbym aby aplikacja działała tak:

  1. Widok „excle_file” – tu user uploaduje plik .xlsx
def excle_upload(request):
    if request.method =='POST':
        # Czy to w tym miejscu powinna
        # być napisana logika która przepuszcza
        # file przez skrypt pandas
        # i wkłada go do formy w miejsce request.FILE 
        # ???

        form = ExcleForm(request.POST, request.FILES)
        if form.is_valid():
            form.save()
            return redirect('excle_list')
    else:
        form = ExcleForm()

2.Skrypt pandas przerabia plik .xlsx do żądanej postaci (czyli logika + skrypt pandas  chyba musi być także w widoku „excle_file” ??? ) Skrypt zaczyna się tak:

    df = pd.read_excel(os.path.join(path,filename)) # tutaj file przslany przez usera
    df.loc[:,"ODOMETER_FW"] = df.loc[:,"ODOMETER_FW"].fillna(0).astype('int')
    df.dropna(inplace = True)
    df.sort_values(by=['VEHICLE_ID_FW','TRANSACTION_DATE_FW','TRANSACTION_TIME_FW'], ascending=[True,False,False],inplace=True)
    df['ODOMETER_FW'] = df['ODOMETER_FW'].apply(lambda x: 0 if x <1000 else x)
    df.set_index(['VEHICLE_ID_FW'], inplace=True)

3. Widok „excle_list” – ma zawierać już przerobione pliki i daje możliwość ich ściągnięcia

def excle_list(request):
    files = Excel.objects.all()
    return render(request, 'odo_correction/excle_list.html', {'files':files})

Obecnie mam napisane funkcjonalności z pkt 1 i 3 no i oczywiście gotowy skrypt pandas. Aplikacja działa tak, że mogę uploadowac i następnie pobierać dokładnie ten sam plik. (cel to jednak pkt 3). Próbuje dostać się do pliku grzebiąc gdzieś w request.FILES ale mam 2 problemy:

- jak zrobić aby klasa: InMemoryUploadedFile – stała się plikiem excel możliwym do użycia jako DataFrame ?

- jak włożyć przerobiony plik z inputa do zaimplementowanej formy „ExcleForm”

Dodatkowo zamieszczę jeszcze w kolejności: model , forme i formularz uploadu html:

#models.py
class Excel(models.Model):
    country = models.CharField(default= "", max_length = 20)
    file = models.FileField(upload_to ='excel')

    def __str__(self):
        return self.file.name
    
    def delete(self, *args, **kwargs):
        self.file.delete()
        super().delete(*args, **kwargs)

# form.py
class ExcleForm(forms.ModelForm):
    class Meta:
        model = Excel
        fields = ('country','file')
{% extends 'odo_correction/base.html' %}
{% load crispy_forms_tags %}

{% block content %}
    <h2> Upload .xlsx ODO file</h2>
    <form method="post" enctype="multipart/form-data">
        {% csrf_token %}
        {{ form|crispy }}
        <button type="submit" class="btn btn-primary">Upload File</button>
    </form>
{% endblock %}

Jeśli ktoś ma jakieś doświadczenie tego typu problemie, to bardzo proszę o pomoc, gdzie szukać informacji i czym się kierować?

Dziękuje i Pozdrawiam!

komentarz zamknięcia: Temat wyjaśniony

1 odpowiedź

+1 głos
odpowiedź 29 sierpnia 2020 przez Nelson89 Dyskutant (7,720 p.)
wybrane 2 września 2020 przez Ventre90
 
Najlepsza

Cześć,

Skrypt pandas przerabia plik .xlsx do żądanej postaci (czyli logika + skrypt pandas  chyba musi być także w widoku „excle_file” ??? )

Generalnie ta działanie powinno znaleźć się w widoku ale nie musisz tego robić bezpośrednio w kodzie danego widoku - możesz to wrzucić do modułu, dzięki temu przy skomplikowanej, rozbudowanej logice nie zaśmiecisz sobie kodu widoku.

 

- jak zrobić aby klasa: InMemoryUploadedFile – stała się plikiem excel możliwym do użycia jako DataFrame ?

Do tego możesz użyć kodu:

import io
import pandas as pd

...

def excle_upload(request):
    if request.method == 'POST':
        file = request.FILES['fileToUpload'].read()
        excel_file = pd.ExcelFile(io.BytesIO(f))

Plik jest wyciągany z requestu.FILES. Następnie po przez użycie funkcji read() transformujesz  plik z klasy django.core.files.uploadedfile.InMemoryUploadedFile do klasy bytes. Na tym etapie masz plik w postaci binarnej - jakbyś otworzył plik z wykorzystaniem wbudowanej funkcji open i trybem rb. Następnie tworzysz obiekt klasy io.BytesIO, który może być otwarty przez pandas.

- jak włożyć przerobiony plik z inputa do zaimplementowanej formy „ExcleForm

form = ExcleForm(request.POST, request.FILES)
        if form.is_valid():
            # edycja pliku
            request.FILES['nazwa'] = ... # a tutaj podmiana
            # ponowne przypisanie danych z requestu do formy 
            form = ExcleForm(request.POST, request.FILES) 
            form.save()

Mógłbyś spróbować edytować ten plik, następnie utworzyć obiekt klasy django.core.files.uploadedfile.InMemoryUploadedFile i przypisać go do request.FILES. Tego nie próbowałem, a tutaj masz kod tej klasy. Druga opcja, po zapisaniu formy - otwórz uploadowany plik w pandas, edytuj i nadpisz oryginalny plik. W bazie danych masz ścieżkę do pliku, a nie sam plik, więc z tym nie powinno być problemu i jest to łatwiejsze niż pierwsze rozwiązanie.

Pozdrawiam,

Nelson

komentarz 30 sierpnia 2020 przez Ventre90 Obywatel (1,170 p.)

Cześć Nelson

Druga opcja, po zapisaniu formy - otwórz uploadowany plik w pandas, edytuj i nadpisz oryginalny plik. W bazie danych masz ścieżkę do pliku, a nie sam plik, więc z tym nie powinno być problemu

Bardzo dziękuje za pomoc i sugestie. Ten drugi sposób, który sugerujesz faktycznie brzmi lepiej. Czy ta operacja może byc zawarta w tym samym widoku pod linią z zapisem formy ? Czyli wywolanie obiektu modelu z bazy po pk i odwolanie sie do jego url i to powinno zadzialac dla pandas ? Nastepnie moglbym ten plik przypisac ponownie do request.FILES['file'] i ponownie zapisac forme ? Czy to mniej wiecej tak ma wygladac ?

komentarz 1 września 2020 przez Nelson89 Dyskutant (7,720 p.)

Możesz to zrobić od razu w tym samym widoku. Po pk możesz wywołać obiekt, a w obiekcie będziesz mieć ścieżkę do pliku, którą możesz przekazać do pandas. W pandas plik zostanie otwarty, edytowany i zapisany. Jako potwierdzenie, że plik został edytowany przez pandas możesz dodać do modelu atrybut (typ boolaen, domyślna wartość False), który określałby fakt, czy plik został edytowany. Po edycji wartość wynosiłaby True.

W punktach mogłoby to wyglądać tak:

  1. Sprawdzenie czy forma jest poprawna (form.is_valid()) - kolejne kroki dla wartości True,
  2. Zapis formy - czyli zapis danych do bazy danych,
  3. Wyszukanie obiektu, z nowo zapisanymi danymi,
  4. Pobranie ścieżki do pliku z obiektu,
  5. Edycja pliku w pandas,
  6. Zapis pliku,
  7. Edycja atrybutu obiektu z False na True,
  8. Zapis obiektu w bazie danych - po przez użycie metody save().

Pozdrawiam,

Nelson

komentarz 2 września 2020 przez Ventre90 Obywatel (1,170 p.)

@Nelson jeszcze raz wielkie dzięki za stworzenie tej listy, która uporządkowała mi wszystko w głowie. Teraz wszystko "działa jak natura chciała" - jak to mawia klasyk. Excel, który pobieram z aplikacji jest już przerobiony.

Zrobiłem nowy widok gdzie plik jest otwierany i nadpisywany przez pandas, a następnie zapisany jest cały model. Skrypt pandas umieściłem w klasie modelu, co pozwala mi tylko wywoływać funkcje w nadmienionym widoku. Tak jest chyba najczytelniej. Na początku nie miałem pojęcia co zrobić a teraz to tylko 5 linijek kodu. Zostało mi teraz podorabiac trochę ikon, sygnałów, czy popupów z progress barami ale to juz mam nadzieje dam rade sam zrobić ;)

Jeszcze raz dzięki i pozdrawiam!

widok:

def excel_correction(request, pk):
    ex = Excel.objects.get(pk=pk)
    df = ex.odo()
    ex.save_excel(df)
    ex.corrected = True
    ex.save()
    return redirect('excel_list')

form:

<form method="post" action="{% url 'excel_correction' f.pk %}">
       {% csrf_token %}
       <button type="submit" class="btn btn-success btn-sm">Correct</button>
 </form>

 

komentarz 2 września 2020 przez Nelson89 Dyskutant (7,720 p.)
Super powodzenia przy dalszej pracy!

pozdrawiam

Nelson

Podobne pytania

0 głosów
0 odpowiedzi 421 wizyt
pytanie zadane 28 marca 2021 w Python przez PIxEL Nowicjusz (180 p.)
0 głosów
1 odpowiedź 1,218 wizyt
pytanie zadane 22 czerwca 2019 w Python przez 001greg001 Bywalec (2,030 p.)
0 głosów
0 odpowiedzi 926 wizyt
pytanie zadane 27 lutego 2019 w Python przez Dawid89 Obywatel (1,120 p.)

92,573 zapytań

141,423 odpowiedzi

319,648 komentarzy

61,959 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...