【问题标题】:CSV not importing to django modelsCSV 未导入 django 模型
【发布时间】:2017-11-14 01:26:46
【问题描述】:

我正在尝试创建一个使用 CSV 数据的 django Web 应用程序。我创建了一个 django 模型来容纳来自这些 csv 的数据,我已经将所有 csv 存储在 STATIC_ROOT 中。当我加载页面时,调用的模板(datalandingpage.html)加载没有问题。但是,当我检查 django admin 时,没有导入任何 CSV。如果我猜测,我认为缺点与 django 无法找到文件有关(虽然我只是猜测,但我很可能是错误的,因为我是一个相对较新的开发人员)。以下是我尝试编写的所有相关代码。

编辑:所以看起来我的视图函数可能会直接跳到渲染部分,这可能是我在运行时看不到任何错误的原因。关于为什么会出现这种情况的任何想法?

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:

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:

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")

【问题讨论】:

  • 在执行视图时是否看到任何错误?返回的状态码是什么?我在那里看到了一些错误,据我所知,这些错误应该会导致一些问题。
  • @sytech 我在执行视图时没有看到任何错误,只有状态码 200。所以我做了一些工作,可能函数只是跳到渲染部分。知道为什么会这样吗?

标签: python django csv django-models


【解决方案1】:

我最终重新编写了脚本并且它成功了。我认为我奇怪的循环结构导致脚本无法按预期工作(或者根本没有,真的)。我还使用了 bulk_create 而不必在每一行之后调用 save 来提高流程效率。这是有效的版本:

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")

【讨论】:

    【解决方案2】:

    如果我理解正确,您想从 CSV 文件创建模型列表。您可以考虑为此使用现有的库:http://django-import-export.readthedocs.io/en/stable/index.html

    【讨论】:

      【解决方案3】:

      您对循环目录和打开文件的方式有疑问。 os.walk 为每个目录生成一个 (root_dir, directories, files) 元组,其中 directories 是在 root_dir 中找到的目录名称元组,files 是在 root_dir 中找到的文件名元组

      在您的代码中,您有以下内容:

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

      这不会像您认为的那样做,毫无疑问会导致AttributeError,因为for files in os.walk(...) 中的files 将始终包含两个元组,而元组没有.endswith 方法。

      此外,当您正确地遍历os.walk 提供的文件时——它们只是文件名。您必须将路径与根目录连接起来。

      要解决这个问题,你应该修改如下......

      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)
      

      请注意,这会将os.walk 产生的元组解包到root, dirs, files 现在files 实际上是一个文件名列表。此外,os.path.join(root, filename) 用于根据名称创建文件的完整路径。

      另请注意,我将其修改为使用 with open(...) 上下文管理器。此块下的代码在文件打开时执行,一旦块结束,文件将为您关闭。

      【讨论】:

      • 感谢您的回复!我按照您的建议进行了更改。然而,因为我在加载视图时没有看到任何错误(同样,模板加载得很好),这让我认为我刚刚跳到渲染部分的函数。知道为什么会这样吗?
      猜你喜欢
      • 2014-04-14
      • 1970-01-01
      • 2021-02-10
      • 2019-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-02
      • 2016-12-21
      • 2012-10-20
      相关资源
      最近更新 更多