gpt4 book ai didi

python - 将 django-import-export 与基于类的 View 一起使用

转载 作者:太空宇宙 更新时间:2023-11-03 12:33:06 26 4
gpt4 key购买 nike

我想将 django-import-export 与基于类的 View 一起使用。

https://django-import-export.readthedocs.org/en/latest/getting_started.html 的文档中我看到一个导出为 csv 的示例

>>> dataset = BookResource().export()
>>> print dataset.csv
id,name,author,author_email,imported,published,price,categories
2,Some book,1,,0,2012-12-05,8.85,1

但是如果我想返回一个 Excel 文件,我应该使用哪个基于类的 View 呢?只是查看

最佳答案

果酱,

基于 https://github.com/bmihelac/django-import-export 的实现并以具有名称和缩写属性的模型“国家/地区”为例:

首先,在国家模型文件的末尾定义资源:

class CountryResource(resources.ModelResource):
class Meta:
model = Country

然后,实现基于类的 View :

class CountryExport(View):

def get(self, *args, **kwargs ):
dataset = CountryResource().export()
response = HttpResponse(dataset.csv, content_type="csv")
response['Content-Disposition'] = 'attachment; filename=filename.csv'
return response


class CountryImport(View):
model = Country
from_encoding = "utf-8"

#: import / export formats
DEFAULT_FORMATS = (
base_formats.CSV,
base_formats.XLS,
base_formats.TSV,
base_formats.ODS,
base_formats.JSON,
base_formats.YAML,
base_formats.HTML,
)
formats = DEFAULT_FORMATS
#: template for import view
import_template_name = 'Country/import.html'
resource_class = None

def get_import_formats(self):
"""
Returns available import formats.
"""
return [f for f in self.formats if f().can_import()]

def get_resource_class(self):
if not self.resource_class:
return modelresource_factory(self.model)
else:
return self.resource_class

def get_import_resource_class(self):
"""
Returns ResourceClass to use for import.
"""
return self.get_resource_class()

def get(self, *args, **kwargs ):
'''
Perform a dry_run of the import to make sure the import will not
result in errors. If there where no error, save the user
uploaded file to a local temp file that will be used by
'process_import' for the actual import.
'''
resource = self.get_import_resource_class()()

context = {}

import_formats = self.get_import_formats()
form = ImportForm(import_formats,
self.request.POST or None,
self.request.FILES or None)

if self.request.POST and form.is_valid():
input_format = import_formats[
int(form.cleaned_data['input_format'])
]()
import_file = form.cleaned_data['import_file']
# first always write the uploaded file to disk as it may be a
# memory file or else based on settings upload handlers
with tempfile.NamedTemporaryFile(delete=False) as uploaded_file:
for chunk in import_file.chunks():
uploaded_file.write(chunk)

# then read the file, using the proper format-specific mode
with open(uploaded_file.name,
input_format.get_read_mode()) as uploaded_import_file:
# warning, big files may exceed memory
data = uploaded_import_file.read()
if not input_format.is_binary() and self.from_encoding:
data = force_text(data, self.from_encoding)
dataset = input_format.create_dataset(data)
result = resource.import_data(dataset, dry_run=True,
raise_errors=False)

context['result'] = result

if not result.has_errors():
context['confirm_form'] = ConfirmImportForm(initial={
'import_file_name': os.path.basename(uploaded_file.name),
'input_format': form.cleaned_data['input_format'],
})

context['form'] = form
context['opts'] = self.model._meta
context['fields'] = [f.column_name for f in resource.get_fields()]

return TemplateResponse(self.request, [self.import_template_name], context)


def post(self, *args, **kwargs ):
'''
Perform a dry_run of the import to make sure the import will not
result in errors. If there where no error, save the user
uploaded file to a local temp file that will be used by
'process_import' for the actual import.
'''
resource = self.get_import_resource_class()()

context = {}

import_formats = self.get_import_formats()
form = ImportForm(import_formats,
self.request.POST or None,
self.request.FILES or None)

if self.request.POST and form.is_valid():
input_format = import_formats[
int(form.cleaned_data['input_format'])
]()
import_file = form.cleaned_data['import_file']
# first always write the uploaded file to disk as it may be a
# memory file or else based on settings upload handlers
with tempfile.NamedTemporaryFile(delete=False) as uploaded_file:
for chunk in import_file.chunks():
uploaded_file.write(chunk)

# then read the file, using the proper format-specific mode
with open(uploaded_file.name,
input_format.get_read_mode()) as uploaded_import_file:
# warning, big files may exceed memory
data = uploaded_import_file.read()
if not input_format.is_binary() and self.from_encoding:
data = force_text(data, self.from_encoding)
dataset = input_format.create_dataset(data)
result = resource.import_data(dataset, dry_run=True,
raise_errors=False)

context['result'] = result

if not result.has_errors():
context['confirm_form'] = ConfirmImportForm(initial={
'import_file_name': os.path.basename(uploaded_file.name),
'input_format': form.cleaned_data['input_format'],
})

context['form'] = form
context['opts'] = self.model._meta
context['fields'] = [f.column_name for f in resource.get_fields()]

return TemplateResponse(self.request, [self.import_template_name], context)

class CountryProcessImport(View):
model = Country
from_encoding = "utf-8"

#: import / export formats
DEFAULT_FORMATS = (
base_formats.CSV,
base_formats.XLS,
base_formats.TSV,
base_formats.ODS,
base_formats.JSON,
base_formats.YAML,
base_formats.HTML,
)
formats = DEFAULT_FORMATS
#: template for import view
import_template_name = 'Country/import.html'
resource_class = None



def get_import_formats(self):
"""
Returns available import formats.
"""
return [f for f in self.formats if f().can_import()]

def get_resource_class(self):
if not self.resource_class:
return modelresource_factory(self.model)
else:
return self.resource_class

def get_import_resource_class(self):
"""
Returns ResourceClass to use for import.
"""
return self.get_resource_class()

def post(self, *args, **kwargs ):
'''
Perform the actual import action (after the user has confirmed he
wishes to import)
'''
opts = self.model._meta
resource = self.get_import_resource_class()()

confirm_form = ConfirmImportForm(self.request.POST)
if confirm_form.is_valid():
import_formats = self.get_import_formats()
input_format = import_formats[
int(confirm_form.cleaned_data['input_format'])
]()
import_file_name = os.path.join(
tempfile.gettempdir(),
confirm_form.cleaned_data['import_file_name']
)
import_file = open(import_file_name, input_format.get_read_mode())
data = import_file.read()
if not input_format.is_binary() and self.from_encoding:
data = force_text(data, self.from_encoding)
dataset = input_format.create_dataset(data)

result = resource.import_data(dataset, dry_run=False,
raise_errors=True)

# Add imported objects to LogEntry
ADDITION = 1
CHANGE = 2
DELETION = 3
logentry_map = {
RowResult.IMPORT_TYPE_NEW: ADDITION,
RowResult.IMPORT_TYPE_UPDATE: CHANGE,
RowResult.IMPORT_TYPE_DELETE: DELETION,
}
content_type_id=ContentType.objects.get_for_model(self.model).pk
'''
for row in result:
LogEntry.objects.log_action(
user_id=request.user.pk,
content_type_id=content_type_id,
object_id=row.object_id,
object_repr=row.object_repr,
action_flag=logentry_map[row.import_type],
change_message="%s through import_export" % row.import_type,
)
'''
success_message = _('Import finished')
messages.success(self.request, success_message)
import_file.close()

url = reverse('%s_list' % (str(opts.app_label).lower()))
return HttpResponseRedirect(url)

模板 import.html 具有以下代码:

<h1>{% trans "Importar" %} {{ opts.app_label }}</h1>

{% if confirm_form %}
<form action="{% url "process_import" %}" method="POST">
{% csrf_token %}
{{ confirm_form.as_p }}
<p>
{% trans "Below is a preview of data to be imported. If you are satisfied with the results, click 'Confirm import'" %}
</p>
<div class="submit-row">
<input type="submit" class="btn" name="confirm" value="{% trans "Confirm import" %}">
</div>
</form>

{% else %}
<form action="{{ form_url }}" method="post" id="{{ opts.module_name }}_form" enctype="multipart/form-data">
{% csrf_token %}

<p>
{% trans "This importer will import the following fields: " %}
{% for f in fields %}
{% if forloop.counter0 %}
,
{% endif %}
<tt>{{ f }}</tt>
{% endfor %}
</p>

<fieldset class="module aligned">
{% for field in form %}
<div class="form-row">
{{ field.errors }}

{{ field.label_tag }}

{{ field }}

{% if field.field.help_text %}
<p class="help">{{ field.field.help_text|safe }}</p>
{% endif %}
</div>
{% endfor %}
</fieldset>

<div class="submit-row">
<input type="submit" class="btn" value="{% trans "Submit" %}">
</div>
</form>
{% endif %}

{% if result %}
{% if result.has_errors %}
<h2>{% trans "Errors" %}</h2>
<ul>
{% for error in result.base_errors %}
<li>{{ error.error }}</li>
{% endfor %}
{% for line, errors in result.row_errors %}
{% for error in errors %}
<li>
{% trans "Line number" %}: {{ line }} - {{ error.error }}
<div class="traceback">{{ error.traceback|linebreaks }}</div>
</li>
{% endfor %}
{% endfor %}
</ul>
{% else %}
<h2>
{% trans "Preview" %}
</h2>
<table>
<thead>
<tr>
<th></th>
{% for field in fields %}
<th>{{ field }}</th>
{% endfor %}
</tr>
</thead>
{% for row in result.rows %}
<tr>
<td>
{% if row.import_type == 'new' %}
{% trans "New" %}
{% elif row.import_type == 'skip' %}
{% trans "Skipped" %}
{% elif row.import_type == 'delete' %}
{% trans "Delete" %}
{% elif row.import_type == 'update' %}
{% trans "Update" %}
{% endif %}
</td>
{% for field in row.diff %}
<td>
{{ field }}
</td>
{% endfor %}
</tr>
{% endfor %}
</table>
{% endif %}
{% endif %}

并且 urls.py 应该包含:

#export
url(r'export/$', login_required(CountryExport.as_view()), name='country_export'),

#import
url(r'import/$', login_required(CountryImport.as_view()), name='country_import'),
url(r'process_import/$', login_required(CountryProcessImport.as_view()), name='process_import'),

关于python - 将 django-import-export 与基于类的 View 一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24008820/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com