2017-01-06 28 views
5

Próbuję wstawić dane w Pandas DataFrame do istniejącego modelu Django, Agency, który używa backendu SQLite. Jednak następujące odpowiedzi na How to write a Pandas Dataframe to Django model i Saving a Pandas DataFrame to a Django Model prowadzą do zastąpienia całej tabeli SQLite i złamania kodu Django. W szczególności jest to automatycznie generowana kolumna klucza Django id, która jest zastępowana przez index, która powoduje błędy podczas renderowania szablonów (no such column: agency.id).Jak napisać pandasową ramkę danych do istniejącego modelu Django?

Oto kod i wynik użycia Pandas to_sql w tabeli SQLite, agency.

W models.py:

class Agency(models.Model): 
    name = models.CharField(max_length=128) 

W myapp/management/commands/populate.py:

class Command(BaseCommand): 

def handle(self, *args, **options): 

    # Open ModelConnection 
    from django.conf import settings 
    database_name = settings.DATABASES['default']['NAME'] 
    database_url = 'sqlite:///{}'.format(database_name) 
    engine = create_engine(database_url, echo=False) 

    # Insert data data 
    agencies = pd.DataFrame({"name": ["Agency 1", "Agency 2", "Agency 3"]}) 
    agencies.to_sql("agency", con=engine, if_exists="replace") 

Wywoływanie 'python manage.py populate' skutecznie dodaje trzech agencji w tabeli:

index name 
0  Agency 1 
1  Agency 2 
2  Agency 3 

Jednak ten sposób nie zmieniło DDL tabeli z:

CREATE TABLE "agency" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "name" varchar(128) NOT NULL) 

do:

CREATE TABLE agency (
    "index" BIGINT, 
    name TEXT 
); 
CREATE INDEX ix_agency_index ON agency ("index") 

Jak mogę dodać DataFrame do modelu zarządzanego przez Django i zachować Django ORM nienaruszone?

Odpowiedz

2

Aby odpowiedzieć na moje własne pytanie, ponieważ obecnie zaimportowałem dane za pomocą Pandas do Django, popełniłem błąd, próbując użyć wbudowanego Pandas Sql Alchemy DB ORM, który modyfikował definicję bazowej tabeli bazy danych. W kontekście powyższego, można po prostu użyć Django ORM podłączyć i wstawić dane:

from myapp.models import Agency 

class Command(BaseCommand): 

    def handle(self, *args, **options): 

     # Process data with Pandas 
     agencies = pd.DataFrame({"name": ["Agency 1", "Agency 2", "Agency 3"]}) 

     # iterate over DataFrame and create your objects 
     for agency in agencies.itertuples: 
      agency = Agency.objects.create(name=agency.name) 

Można jednak często chcesz zaimportować dane za pomocą skryptu zewnętrznego raczej niż przy użyciu polecenia zarządzania, jak wyżej, lub używając powłoki Django. W takim przypadku należy najpierw połączyć się z Django ORM przez wywołanie metody setup:

import os, sys 

import django 
import pandas as pd 

sys.path.append('../..') # add path to project root dir 
os.environ["DJANGO_SETTINGS_MODULE"] = "myproject.settings" 

# for more sophisticated setups, if you need to change connection settings (e.g. when using django-environ): 
#os.environ["DATABASE_URL"] = "postgres://myuser:[email protected]:54324/mydb" 

# Connect to Django ORM 
django.setup() 

# process data 
from myapp.models import Agency 
Agency.objects.create(name='MyAgency') 
  • Tu są eksportowane mój moduł ustawień myproject.settings do DJANGO_SETTINGS_MODULE tak że django.setup() może odebrać ustawienia projektu.

  • W zależności od tego, skąd uruchamiasz skrypt, możesz potrzebować ścieżki do ścieżki systemowej, aby Django mógł znaleźć moduł ustawień. W tym przypadku uruchamiam skrypt dwa katalogi poniżej katalogu głównego mojego projektu.

  • Możesz zmodyfikować dowolne ustawienia przed wywołaniem setup. Jeśli twój skrypt musi łączyć się z DB inaczej niż to skonfigurowane w settings. Na przykład podczas lokalnego uruchamiania skryptu na kontenerze Dockgo/postgres Docker.

Uwaga, powyższy przykład wykorzystał django-environ do określenia ustawień DB.