2010-07-17 17 views
11

Ich versuche, eine Website in Django einzurichten, die es dem Benutzer ermöglicht, Abfragen an eine Datenbank mit Informationen über ihre Vertreter im Europäischen Parlament zu senden. Ich habe die Daten in einem Komma TXT-Datei mit folgendem Format getrennt:Füllen einer SQLite3-Datenbank aus einer TXT-Datei mit Python

Parliament, Name, Country, Party_Group, National_Party, Position

7, Marta Andreasen, United Kingdom, Europe of freedom and democracy Group, United Kingdom Independence Party, Member

etc....

Ich mag eine SQLite3 Datenbank mit diesen Daten füllen, aber bisher alle Tutorials, die ich nur gefunden habe, zeigen, wie dies zu tun, indem Hand. Da ich 736 Beobachtungen in der Datei habe, möchte ich das nicht wirklich machen.

Ich vermute, das ist eine einfache Sache, aber ich wäre sehr dankbar, wenn mir jemand zeigen könnte, wie man das macht.

Thomas

Antwort

17

So vorausgesetzt, Ihr models.py etwas wie folgt aussieht:

class Representative(models.Model): 
    parliament = models.CharField(max_length=128) 
    name = models.CharField(max_length=128) 
    country = models.CharField(max_length=128) 
    party_group = models.CharField(max_length=128) 
    national_party = models.CharField(max_length=128) 
    position = models.CharField(max_length=128) 

Sie können dann python manage.py shell laufen und führen Sie die folgenden Schritte aus:

import csv 
from your_app.models import Representative 
# If you're using different field names, change this list accordingly. 
# The order must also match the column order in the CSV file. 
fields = ['parliament', 'name', 'country', 'party_group', 'national_party', 'position'] 
for row in csv.reader(open('your_file.csv')): 
    Representative.objects.create(**dict(zip(fields, row))) 

Und du bist fertig.

Addendum (edit)

Per Thomas Wunsch, hier ist eine Erklärung, was **dict(zip(fields,row)) tut:

Also zunächst fields eine Liste der Feldnamen enthält, die wir definiert, und row enthält eine Liste von Werte, die die aktuelle Zeile in der CSV-Datei darstellen.

fields = ['parliament', 'name', 'country', ...] 
row = ['7', 'Marta Andreasen', 'United Kingdom', ...] 

zip() Was tut, ist es zwei Listen in eine Liste von Paaren von Elementen aus beiden Listen kombiniert (wie ein Reißverschluß); d.h. zip(['a','b,'c'], ['A','B','C']) wird [('a','A'), ('b','B'), ('c','C')] zurückgeben. Also in unserem Fall:

>>> zip(fields, row) 
[('parliament', '7'), ('name', 'Marta Andreasen'), ('country', 'United Kingdom'), ...] 

Die dict() Funktion wandelt einfach die Liste von Paaren in einem Wörterbuch.

>>> dict(zip(fields, row)) 
{'parliament': '7', 'name': 'Marta Andreasen', 'country': 'United Kingdom', ...} 

Die ** ist ein Weg, ein Wörterbuch in ein Schlüsselwort-Argument-Liste für eine Funktion der Umwandlung. So ist function(**{'key': 'value'}) das Äquivalent von function(key='value'). So in aus Beispiel create(**dict(zip(field, row))) Aufruf ist das Äquivalent von:

create(parliament='7', name='Marta Andreasen', country='United Kingdom', ...) 

Hoffnung diese Dinge aufklärt.

+3

Wenn Sie diese in Django laden, schauen Sie sich hier unbedingt die Lösung von Aram an. Es nutzt die django ORM-Bits für Sie, so dass Sie sich nicht direkt mit dem Schema herumschlagen müssen. Keine große Sache, wenn Sie mit SQL-Schema vertraut sind, aber ich fand, dass es die Dinge viel einfacher gemacht hat. – heckj

+0

+1; das ist viel einfacher! – bernie

+1

Danke für die Antwort Aram.Ich lerne immer noch Python, also könntest du erklären, was der (** dict (zip (...)) Teil der letzten Zeile tut? –

2

Sie könnten die Daten mit der CSV-Modul lesen. Dann können Sie ein Insert SQL-Anweisung erstellen und verwenden Sie die Methode executemany:

cursor.executemany(sql, rows) 

oder add_all verwenden, wenn Sie sqlalchemy verwenden.

0

So etwas wie die folgenden funktionieren sollte: (nicht getestet)

# Open database (will be created if not exists) 
conn = sqlite3.connect('/path/to/your_file.db') 

c = conn.cursor() 

# Create table 
c.execute('''create table representatives 
(parliament text, name text, country text, party_group text, national_party text, position text)''') 

f = open("thefile.txt") 
for i in f.readlines(): 
    # Insert a row of data 
    c.execute("""insert into representatives 
       values (?,?,?,?,?,?)""", *i.split(", ")) # *i.split(", ") does unpack the list as arguments 

# Save (commit) the changes 
conn.commit() 

# We can also close the cursor if we are done with it 
c.close() 
+0

Hallo Joschua, danke für die Antwort! Allerdings halte ich diesen Fehler, wenn Ihr Beispiel oben mit: > Traceback (jüngste Aufforderung zuletzt): File "/Users/thomasjensen/Documents/sql_test.py", Zeile 13, in c.execute ("" "Einfügen in MEP (Parlament, Name, Land, Party_Group, Home_Party, Position) -Werte (?,?,?,?,?,?)" ", * i.split (", ")) TypeError: function takes höchstens 2 Argumente (162 gegeben) –

+1

Entfernen Sie einfach den führenden Stern aus '* i.split (", ")'. Die Tatsache, dass die Fehlermeldung "162 [Argumente]" lautet, deutet jedoch darauf hin, dass weitere Probleme folgen werden. Ich würde auch dringend empfehlen, eine der anderen Antworten auf dieser Seite zu verwenden, die alle die "csv" -Bibliothek verwenden, anstatt sich auf 'split (", ") zu verlassen, was Ihnen viel Kummer bereiten wird. –

+0

Ok, danke für den Hinweis. –

4

Wie SiggyF sagt und nur etwas anders als Joschua:

Erstellen Sie eine Textdatei mit dem Schema, zB:

 
CREATE TABLE politicians (
    Parliament text, 
    Name text, 
    Country text, 
    Party_Group text, 
    National_Party text, 
    Position text 
); 

erstellen Tabelle:

>>> import csv, sqlite3 
>>> conn = sqlite3.connect('my.db') 
>>> c = conn.cursor() 
>>> with open('myschema.sql') as f:   # read in schema file 
... schema = f.read() 
... 
>>> c.execute(schema)       # create table per schema 
<sqlite3.Cursor object at 0x1392f50> 
>>> conn.commit()        # commit table creation 

Verwenden csv-Modul zu lesen Datei mit einzufügenden Daten:

>>> csv_reader = csv.reader(open('myfile.txt'), skipinitialspace=True) 
>>> csv_reader.next()       # skip the first line in the file 
['Parliament', 'Name', 'Country', ... 

# put all data in a tuple 
# edit: decoding from utf-8 file to unicode 
>>> to_db = tuple([i.decode('utf-8') for i in line] for line in csv_reader) 
>>> to_db          # this will be inserted into table 
[(u'7', u'Marta Andreasen', u'United Kingdom', ... 

Insert Daten:

>>> c.executemany("INSERT INTO politicians VALUES (?,?,?,?,?,?);", to_db) 
<sqlite3.Cursor object at 0x1392f50> 
>>> conn.commit() 

Stellen Sie sicher, dass alles wie erwartet ging:

>>> c.execute('SELECT * FROM politicians').fetchall() 
[(u'7', u'Marta Andreasen', u'United Kingdom', ... 

bearbeiten:
Und da Sie (in Unicode) an Eingang haben decodiert, Sie müssen sicher sein, für die Ausgabe codieren.
Zum Beispiel:

with open('encoded_output.txt', 'w') as f: 
    for row in c.execute('SELECT * FROM politicians').fetchall(): 
    for col in row: 
     f.write(col.encode('utf-8')) 
     f.write('\n') 
+0

Hallo Adam, danke für die aufwendige Antwort! Jeder Schritt funktioniert, außer, wenn ich versuche: c.executemany ("IN Politiker VALUES INSERT (,,,,,);?????", To_db) Dann bekomme ich folgende Fehlermeldung: ProgrammingError : Sie dürfen keine 8-Bit-Bytestrings verwenden, es sei denn, Sie verwenden eine text_factory, die 8-Bit-Bytestrings interpretieren kann (wie text_factory = str). Es wird dringend empfohlen, dass Sie stattdessen Ihre Anwendung nur auf Unicode-Zeichenfolgen umstellen. Ich habe die Textdatei mit einer utf8-Codierung gespeichert, also habe ich keine Ahnung, was hier passiert ... –

+0

@Thomas: Gern geschehen. Ich habe das Beispiel aktualisiert, um die Decodierung von utf-8 zu handhaben, und auch gezeigt, wie man bei der Ausgabe zurück zu utf-8 codiert. Viel Glück für Sie. – bernie

+0

Dank Adam, für einen Anfänger kann dieses ganze Kodierungsgeschäft ziemlich verwirrend sein. –

2

Sie gefragt, was das erstellen (** dict (zip (Felder, Zeile))) Linie tat.

Ich weiß nicht, wie ich direkt auf Ihren Kommentar antworten soll, also werde ich versuchen, es hier zu beantworten.

zip verwendet mehrere Listen als Argumente und gibt eine Liste ihrer entsprechenden Elemente als Tupel zurück.

zip (list1, list2) => [(list1 [0], list2 [0]), (list1 [1], list2 [1]), ....]

dict nimmt eine Liste von 2-Element-Tupeln und gibt ein Wörterbuch zurück, das das erste Element (Schlüssel) jedes Tupels auf sein zweites Element (Wert) abbildet.

create ist eine Funktion, die Schlüsselwortargumente verwendet. Sie können ** some_dictionary verwenden, um dieses Wörterbuch in eine Funktion als Schlüsselwortargumente zu übergeben.

erstellen (** { 'name': 'john', 'Alter': 5}) => create (name = 'John', Alter = 5)

+0

Danke für die Erklärung Steve. –

Verwandte Themen