如何将CSV数据导入Django模型


76

我有一些CSV数据,我想使用示例CSV数据导入django模型:

1;"02-01-101101";"Worm Gear HRF 50";"Ratio 1 : 10";"input shaft, output shaft, direction A, color dark green";
2;"02-01-101102";"Worm Gear HRF 50";"Ratio 1 : 20";"input shaft, output shaft, direction A, color dark green";
3;"02-01-101103";"Worm Gear HRF 50";"Ratio 1 : 30";"input shaft, output shaft, direction A, color dark green";
4;"02-01-101104";"Worm Gear HRF 50";"Ratio 1 : 40";"input shaft, output shaft, direction A, color dark green";
5;"02-01-101105";"Worm Gear HRF 50";"Ratio 1 : 50";"input shaft, output shaft, direction A, color dark green";

我有一些名为Product的django模型。在产品还有像一些领域namedescriptionprice。我想要这样的东西:

product=Product()
product.name = "Worm Gear HRF 70(02-01-101116)"
product.description = "input shaft, output shaft, direction A, color dark green"
product.price = 100

Answers:


83

您想使用python语言中的csv模块,并且应该使用Django的get_or_create方法

 with open(path) as f:
        reader = csv.reader(f)
        for row in reader:
            _, created = Teacher.objects.get_or_create(
                first_name=row[0],
                last_name=row[1],
                middle_name=row[2],
                )
            # creates a tuple of the new object or
            # current object and a boolean of if it was created

在我的示例中,模型老师具有三个属性first_name,last_name和middle_name。

Django get_or_create方法的文档


谢谢你的回答。只需添加,请确保跳过标题行(如果有的话)。不忽略它可能会导致难以调试的错误,例如:stackoverflow.com/questions/43114679/…–
Anupam

2
除此之外,我是通过管理命令完成的,并且能够使用django manage.py运行导入:python manage.py loadgamecsv CSV_PATH
Rocco

谢谢答案。我尝试在独立的.py脚本中实现它,但随后遇到了这个问题stackoverflow.com/a/58322333/7658051
Tms91,19年

33

如果您想使用一个库,谷歌快速搜索csvdjango显示两个库-django-csvimportdjango-adaptors。让我们读一下他们对自己的评价...

  • django适配器

Django适配器是一种工具,可让您轻松地将CSV / XML文件转换为python对象或Django模型实例。

  • django-importcsv

django-csvimport是一个通用的导入器工具,允许上传CSV文件以填充数据。

第一个要求您编写一个模型以匹配csv文件,第二个要求更多的是命令行导入器,这在您使用它们的方式上有很大的不同,并且每个都适合于不同类型的项目。

那么使用哪一个呢?从长远来看,这取决于哪种方法更适合您的项目。

但是,您也可以通过编写自己的django脚本来导入csv文件来完全避免使用库,这类似于(警告,前面的伪代码):

# open file & create csvreader
import csv, yada yada yada

# import the relevant model
from myproject.models import Foo

#loop:
for line in csv file:
     line = parse line to a list
     # add some custom validation\parsing for some of the fields

     foo = Foo(fieldname1=line[1], fieldname2=line[2] ... etc. )
     try:
         foo.save()
     except:
         # if the're a problem anywhere, you wanna know about it
         print "there was a problem with line", i 

超级容易。地狱,如果是一次性导入,则可以通过django shell进行交互。只需弄清楚您要如何处理项目,需要处理多少个文件,然后-如果您决定使用一个库,请尝试确定哪个库更适合您的需求



2
@ Shog9我现在才注意到这一点。我不明白,为什么?这两个问题根本不相关,这使我的整个回答变成了与OP要求完全不同的荒谬解释。它不应该以其他方式合并吗?
yuvi 2014年

这两个问题都解决了相同的问题,但这在向他人提供榜样方面是一个更好的问题。如果您不介意编辑,我想您的答案在这里会很有用。
Shog9 2014年

@ Shog9好的,我明白你的意思了。我不介意编辑,我会尽力而为。感谢您的回复
yuvi 2014年

13
“使用Google快速搜索csv和django” ...使我进入此页面:-p
Chris Huang-Leaver

8

Python csv库可以进行解析,您的代码可以将其转换为Products()


8

您也可以使用django-adaptors

>>> from adaptor.model import CsvModel
>>> class MyCSvModel(CsvModel):
...     name = CharField()
...     age = IntegerField()
...     length = FloatField()
...
...     class Meta:
...         delimiter = ";"

您声明一个MyCsvModel,它将与以下CSV文件匹配:

安东尼; 27; 1.75

要导入文件或任何可迭代对象,只需执行以下操作:

>>> my_csv_list = MyCsvModel.import_data(data = open("my_csv_file_name.csv"))
>>> first_line = my_csv_list[0]
>>> first_line.age
    27

如果没有显式声明,则数据和列以相同的顺序匹配:

Anthony --> Column 0 --> Field 0 --> name
27      --> Column 1 --> Field 1 --> age
1.75    --> Column 2 --> Field 2 --> length

您知道在Csvmodel内部的Meta类中正确写入update参数的方法吗?我正在尝试执行此操作,但是出现了KeyError。
克里斯蒂安·罗哈斯

7

像这样的东西:

f = open('data.txt', 'r')  
for line in f:  
   line =  line.split(';')  
   product = Product()  
   product.name = line[2] + '(' + line[1] + ')'  
   product.description = line[4]  
   product.price = '' #data is missing from file  
   product.save()  

f.close()  

7

使用Pandas库创建csv数据的数据框。
通过将其包含在csv文件的第一行中或通过使用数据框的columns方法将其包含在代码中来命名字段。
然后创建一个模型实例列表。
最后,使用django方法.bulk_create()将模型实例列表发送到数据库表。

pandas中的read_csv函数非常适合读取csv文件,并为您提供许多参数来跳过行,省略字段等。

import pandas as pd

tmp_data=pd.read_csv('file.csv',sep=';')
#ensure fields are named~ID,Product_ID,Name,Ratio,Description
#concatenate name and Product_id to make a new field a la Dr.Dee's answer
products = [
    Product(
        name = tmp_data.ix[row]['Name'] 
        description = tmp_data.ix[row]['Description'],
        price = tmp_data.ix[row]['price'],
    )
    for row in tmp_data['ID']
]
Product.objects.bulk_create(products)

我使用的是mmrs151的答案,但保存每一行(实例)的速度非常慢,并且所有包含定界字符(甚至是引号内)的字段都无法通过open()-line.split(';')方法进行处理。

熊猫有很多有用的警告,值得了解


6

对于我正在使用的django 1.8,

我发出了一个命令,您可以在将来动态创建对象,因此您只需放置csv的文件路径,相关django应用程序的模型名称和应用程序名称,它将填充相关模型而无需指定字段名称。因此,如果我们以下一个csv为例:

field1,field2,field3
value1,value2,value3
value11,value22,value33

它将为您输入命令的模型名称创建对象[{field1:value1,field2:value2,field3:value3},{field1:value11,field2:value22,field3:value33}]。

命令代码:

from django.core.management.base import BaseCommand
from django.db.models.loading import get_model
import csv


class Command(BaseCommand):
    help = 'Creating model objects according the file path specified'

    def add_arguments(self, parser):
        parser.add_argument('--path', type=str, help="file path")
        parser.add_argument('--model_name', type=str, help="model name")
        parser.add_argument('--app_name', type=str, help="django app name that the model is connected to")

    def handle(self, *args, **options):
        file_path = options['path']
        _model = get_model(options['app_name'], options['model_name'])
        with open(file_path, 'rb') as csv_file:
            reader = csv.reader(csv_file, delimiter=',', quotechar='|')
            header = reader.next()
            for row in reader:
                _object_dict = {key: value for key, value in zip(header, row)}
                _model.objects.create(**_object_dict)

请注意,也许在更高版本中

from django.db.models.loading import get_model

已弃用,需要更改为

from django.apps.apps import get_model

4

您可以使用django-csv-importer软件包。 http://pypi.python.org/pypi/django-csv-importer/0.1.1

它像Django模型一样工作

MyCsvModel(CsvModel):
    field1 = IntegerField()
    field2 = CharField()
    etc

    class Meta:
        delimiter = ";"
        dbModel = Product

而且您只需要:CsvModel.import_from_file(“ my file”)

这将自动创建您的产品。


4
不再支持django-csv-importer,而不再支持django-adaptors
trez 2012年

4

如果您正在使用新版本的Django(> 10),并且不想花时间编写模型定义。您可以使用ogrinspect工具。

这将为模型创建代码定义。

python manage.py ogrinspect [/path/to/thecsv] Product

输出将是类(模型)定义。在这种情况下,该模型称为产品。您需要将此代码复制到您的models.py文件中。

之后,您需要使用以下命令(在外壳中)迁移新的Product表:

python manage.py makemigrations
python manage.py migrate

此处的更多信息:https : //docs.djangoproject.com/en/1.11/ref/contrib/gis/tutorial/

请注意,该示例已针对ESRI Shapefile完成,但对于标准CSV文件也可以很好地工作。

要提取数据(CSV格式),可以使用熊猫。

import pandas as pd
your_dataframe = pd.read_csv(path_to_csv)
# Make a row iterator (this will go row by row)
iter_data = your_dataframe.iterrows()

现在,每行都需要转换为字典,并使用此字典来实例化模型(在这种情况下,为Product())

# python 2.x
map(lambda (i,data) : Product.objects.create(**dict(data)),iter_data

完成,现在检查您的数据库。



2

这是基于Erik先前的回答,但我发现最容易使用pandas读取.csv文件,然后为in数据框中的每一行创建该类的新实例。

用这个例子更新ilocpandas不再使用的最新版本九。我不知道Erik的情况,但是您需要在for循环之外创建列表,否则它不会追加到数组中,而只是覆盖它。

import pandas as pd
df = pd.read_csv('path_to_file', sep='delimiter')
products = []
for i in range(len(df)):
    products.append(
        Product(
        name=df.iloc[i][0]
        description=df.iloc[i][1]
        price=df.iloc[i][2]
        )
    )
Product.objects.bulk_create(products)

这只是将DataFrame分成行数组,然后从该数组中选择零索引以外的每一列。(即名称是第一列,描述是第二列,依此类推)

希望能有所帮助。




1

在models.py中定义类,并在其中定义函数。

class all_products(models.Model):
    def get_all_products():
        items = []
        with open('EXACT FILE PATH OF YOUR CSV FILE','r') as fp:
            # You can also put the relative path of csv file
            # with respect to the manage.py file
            reader1 = csv.reader(fp, delimiter=';')
            for value in reader1:
                items.append(value)
        return items

您可以将第i个元素作为项目[i]访问

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.