简体   繁体   English

CSV无法导入到Django模型

[英]CSV not importing to django models

I'm trying to create a django web app that uses data from CSV's. 我正在尝试创建一个Django Web应用程序,该应用程序使用CSV的数据。 I've created a django model to house the data from these csv's, I've stored all the csv's in STATIC_ROOT. 我创建了一个django模型来容纳来自这些csv的数据,并将所有csv都存储在STATIC_ROOT中。 When I load the page, the called template (datalandingpage.html) loads with no problem. 当我加载页面时,被调用的模板(datalandingpage.html)加载没有问题。 However, when I check django admin, none of the CSVs have been imported. 但是,当我检查django admin时,没有CSV导入。 If I were to guess, I think the shortcoming has something to do with django not being able to find the files (though I'm just guessing, I could very well be wrong since I'm a relatively new developer). 如果我猜的话,我认为缺点与django无法找到文件有关(尽管我只是在猜测,因为我是一个相对较新的开发人员,所以我很可能会错了)。 Below is all the relevant code I've written as an attempt. 以下是我尝试编写的所有相关代码。

Edit: So it looks like my view function may be skipping straight to the render part, which may be why I don't see any errors when it runs. 编辑:所以看来我的视图功能可能会直接跳到渲染部分,这可能就是为什么我在运行时看不到任何错误的原因。 Any ideas as to why this may be the case? 关于为什么可能会这样的任何想法?

settings.py: settings.py:

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static/data')

models.py: models.py:

from __future__ import unicode_literals
from django.db import models
from django.contrib import admin

class Data(models.Model):
     # A bunch of model objects (CharField/IntegerFields mainly)

    class Meta:
        verbose_name_plural = 'Data Sets'

    def __str__(self):
        return self.someobject

views.py: views.py:

from __future__ import unicode_literals
from django.conf import settings
from django.shortcuts import render, render_to_response
from django.template import RequestContext
from .models import Data
import csv
import os

def landing(request):

# Opens all csv files in specified directory
directory = os.path.join(settings.STATIC_ROOT)
for files in os.walk(directory):
    for file in files:
        if file.endswith(".csv"):
            f = open(file, 'r')
            reader = csv.reader(f)

            #Checks the rows/columns and tries to find the specified string that marks the start of data
            for i, row in enumerate(reader):
                target_string = "Some string in the CSV"
                if target_string in row:
                    target_row = i
                    return target_row
                    break

            #Checks the rows/columns and tries to find the specified string that marks the end of data
            for j, row in enumerate(reader):
                end_target_string = "Another string in the CSV"
                if end_target_string in row:
                    end_target_row = j
                    return end_target_row
                    break

            #Begins parsing the csv, but skips until two rows past the target beginning string
            for k, row in enumerate(reader):

                #imports csv data when the row number is between target string and target end string
                if k >= (target_row + 2):
                    row = row.split(',')
                    DataSource = Data.objects.create()
                    DataSource.someobject1 = row[0]
                    DataSource.someobject2 = row[1]
                    DataSource.save()

                # When the parse gets to the row with the end string, it closes the file.
                elif k >= end_target_row:
                    reader.close()
                    break

        # Prints something if the file isn't a csv file
        else:
            print "This isn't a csv file"

return render(request, "Data/datalandingpage.html")

I ended up re-writing the script and it worked. 我最终重新编写了脚本,并且该脚本可以正常工作。 I think my strange looping structure caused the script to not work as intended (or at all, really). 我认为我奇怪的循环结构导致脚本无法按预期运行(或完全无法运行)。 I also used bulk_create instead of having to call save after every row to make the process more efficient. 我还使用了bulk_create,而不必在每一行之后都调用save来使过程更高效。 Here's the version that works: 这是有效的版本:

views.py: views.py:

from __future__ import unicode_literals
from django.conf import settings
from django.shortcuts import render, render_to_response
from django.template import RequestContext
from .models import Data
import os
import csv, sys


def import_data(request):

    # Opens all csv files in specified directory

    directory = os.path.join('Some Target Directory')
    count = 0
    for root, dirs, files in os.walk(directory):
        for filename in files:
            if filename.endswith(".csv"):
                file_path = os.path.join(root, filename)
                with open(file_path) as f:
                     reader = csv.reader(f)

                    #Checks the rows/columns and tries to find the specified string that marks the start of data

                    for i, row in enumerate(reader):
                        target_string = "Some Target String"
                        if target_string in row:

                        #Skips to the next line (where the data starts) when the target string is found

                            true_target_row = next(reader)
                            for row in reader:

                                #Counter tells you which file number is importing. 

                                print "importing file number %d" %(count)

                                #Creates a bunch of objects

                                objects = [
                                    Data(
                                        SomeObject = row [n],
                                        ...
                                        ...
                                )
                                for row in reader if row[0] != "Some Target End String"
                            ]

                            # Does a bulk_create after the file is completed

                            Data.objects.bulk_create(objects)
                            count += 1

            # Prints something if the file isn't a csv file

            else:
                print "This isn't a csv file"

    print "Imported %d files! All done!" %(count)

    return render(request, "Data/DataLandingPage.html")

If I understand correctly, you want to create a list of model from a CSV file. 如果我理解正确,则想从CSV文件创建模型列表。 You might consider using an existing library for this: http://django-import-export.readthedocs.io/en/stable/index.html 您可以考虑为此使用现有的库: http : //django-import-export.readthedocs.io/en/stable/index.html

You have an issue with how you're looping over the directories and opening the files. 您如何遍历目录并打开文件时遇到问题。 os.walk yields for each directory walked a tuple of (root_dir, directories, files) where directories is a tuple of directory names that are found in root_dir and files is a tuple of file names found in root_dir os.walk产量为每个目录走过的元组(root_dir, directories, files)其中directories是被发现在目录名的元组root_dirfiles中找到的文件名的元组root_dir

In your code you have the following: 在您的代码中,您具有以下内容:

for files in os.walk(directory):
    for file in files:
        if file.endswith(".csv"):
            f = open(file, 'r')
            reader = csv.reader(f)

This would not do what you probably think it does and will undoubtedly result in an AttributeError because files in for files in os.walk(...) will always have two tuples in it and tuples do not have a .endswith method. 这不会做你可能认为它无疑会导致AttributeError ,因为filesfor files in os.walk(...)将始终有两个元在它和元组没有.endswith方法。

Furthermore, when you correctly loop over files provided by os.walk -- they are just file names. 此外,当您正确循环os.walk提供的文件时,它们只是文件名。 You have to join the path with the root directory. 您必须将路径与根目录连接。

To fix, you should modify this as follows.... 要解决此问题,您应按以下步骤进行修改。...

for root, dirs, files in os.walk(directory):
    for filename in files:
        if filename.endswith(".csv"):
            file_path = os.path.join(root, filename)
            with open(file_path) as f:
                reader = csv.reader(f)

Notice that this unpacks the tuples yielded by os.walk into root, dirs, files now files is actually a list of file names. 请注意,此解压缩由产生的元组os.walkroot, dirs, files ,现在files实际上是文件名的列表。 Additionally, os.path.join(root, filename) is used to create the full path to the file from the name. 另外, os.path.join(root, filename)用于从名称创建文件的完整路径。

Also note I modified this to use the with open(...) context manager. 还要注意,我将其修改为with open(...)上下文管理器一起使用。 Code under this block executes with the file opened and once the block ends the file will be closed for you. 该块下的代码在打开文件的情况下执行,一旦该块结束,该文件将为您关闭。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM