Estoy tratando de usar django import-export para permitir que los usuarios importen sus propios datos. Lo he integrado con el administrador, y eso funciona bien, pero tengo problemas para hacer que funcione el lado de importación de usuarios.
Aquí están mis opiniones:
from .models import WordResource
from tablib import Dataset
from .models import Word
from django.contrib import messages
# Word import
def import_words(request):
if request.method == 'POST':
file_format = request.POST['file-format']
word_resource = WordResource()
dataset = Dataset()
new_words = request.FILES['importData']
if file_format == 'CSV':
imported_data = dataset.load(new_words.read().decode('utf-8'),format='csv')
result = word_resource.import_data(dataset, dry_run=True, raise_errors=True)
elif file_format == 'XLSX':
imported_data = dataset.load(new_words.read(),format='xlsx')
result = word_resource.import_data(dataset, dry_run=True, raise_errors=True)
if result.has_errors():
messages.error(request, 'Uh oh! Something went wrong...')
else:
# Import now
word_resource.import_data(dataset, dry_run=False)
messages.success(request, 'Your words were successfully imported')
return render(request, 'vocab/import.html')
Mi WordResource:
from import_export import resources
from import_export.fields import Field
from import_export.widgets import ForeignKeyWidget
class WordResource(resources.ModelResource):
target_word = Field(attribute='target_word', column_name='Russian')
source_word = Field(attribute='source_word', column_name='Meaning')
example_sentence = Field(attribute='example_sentence', column_name='Example sentence')
fluency = Field(attribute='fluency', column_name='Fluency level')
deck_name = Field(attribute='deck_name', column_name='Deck name')
username = Field(attribute='username', column_name='username',widget=ForeignKeyWidget(User, 'username'))
class Meta:
model = Word
fields = ("username", "target_word",'source_word','example_sentence',
'fluency', 'deck_name',)
import_order = fields
skip_unchanged = True
# exclude = ('id',)
import_id_fields = ['username']
Mi modelo de Word:
class Word(models.Model):
target_word = models.CharField('Word in Russian',max_length=25,help_text="The word you want to add, in Russian")
source_word = models.CharField('What does it mean?',max_length=25, help_text="Write down the translation in any language")
add_to_word_list = models.BooleanField('Would you like to create a flashcard?', default=True)
deck_name = models.CharField('Deck name', max_length=25)
example_sentence = models.CharField(max_length=150,blank=True,help_text="It's important to learn words in context!")
## how well you know the word
class Fluency(models.IntegerChoices):
Beginner = 0
Lower_intermediate = 1
Upper_intermediate = 2
Advanced = 3
fluency = models.IntegerField(choices=Fluency.choices, help_text="How well do you know this word?",null=False)
user = models.ForeignKey(User, related_name="words",on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.target_word
def get_absolute_url(self):
return reverse("vocab:detail",
kwargs={"username": self.user.username, "pk": self.pk})
class Meta:
ordering = ["target_word"]
constraints = [
models.UniqueConstraint(fields=['user','target_word', 'source_word'],name='unique_word')]
Y mi plantilla import.html:
{% extends "vocab/vocab_base.html" %}
{% load bootstrap %}
{% block content %}
{% if messages %}
<div class="messages">
{% for message in messages %}
<h3 {% if message.tags %} class=" {{ message.tags }} " {% endif %}> {{ message }} </h3>
{% endfor %}
</div>
{% else %}
<h1> Import your words</h1>
<p>Here you can import your words from a csv or excel file.</p>
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<input type="file" name="importData">
<p>Please select the format of your file</p>
<select name="file-format" class="form-control my-3">
<option selected>Choose format...</option>
<option>CSV</option>
<option>XLSX</option>
</select>
<button class="btn btn-primary" type="submit">Import</button>
</form>
<a href="{% url 'vocab:index' %}">Back</a>
{% endif %}
{% endblock %}
Curiosamente, inicialmente pareció funcionar cuando intenté con un archivo csv, pero no con un archivo xlsx. Luego hice cambios solo en la parte xlsx de mi código. No solo no solucionó el problema, ahora csv tampoco funciona.
Nota: no se debe a la columna de identificación, ya que tengo una columna de identificación en blanco en mis archivos de carga de prueba.
Actualización : me di cuenta de que me faltaba el campo de usuario, que es una clave externa (no nula) en mi modelo de Word. Por lo que añade un ForeignKeyWidget, pero estoy consiguiendo el error siguiente: NOT NULL constraint failed: vocab_word.user_id
. El error persiste incluso si agrego una columna con la identificación de usuario. ¿Cómo puedo arreglar esto?
Mi archivo csv se ve así:
username;Russian;Meaning;Example Sentence;Fluency level;Deck name
testuser;word1;word2;one two three;1;new
Rastreo después de implementar los cambios de Matthew:
Environment:
Request Method: POST
Request URL: http://127.0.0.1:8000/vocab/import/
Django Version: 3.0.3
Python Version: 3.8.2
Installed Applications:
['django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.humanize',
'rest_framework',
'bootstrap4',
'bootstrapform',
'languages',
'django_countries',
'import_export',
'django_tables2',
'django_filters',
'accounts',
'vocab',
'flash',
'api',
'django_cleanup.apps.CleanupConfig']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware']
Traceback (most recent call last):
File "C:\Users\mvren\miniconda3\envs\myRuEnv\lib\site-packages\django\db\backends\utils.py", line 86, in _execute
return self.cursor.execute(sql, params)
File "C:\Users\mvren\miniconda3\envs\myRuEnv\lib\site-packages\django\db\backends\sqlite3\base.py", line 396, in execute
return Database.Cursor.execute(self, query, params)
The above exception (NOT NULL constraint failed: vocab_word.user_id) was the direct cause of the following exception:
File "C:\Users\mvren\miniconda3\envs\myRuEnv\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
response = get_response(request)
File "C:\Users\mvren\miniconda3\envs\myRuEnv\lib\site-packages\django\core\handlers\base.py", line 115, in _get_response
response = self.process_exception_by_middleware(e, request)
File "C:\Users\mvren\miniconda3\envs\myRuEnv\lib\site-packages\django\core\handlers\base.py", line 113, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\mvren\OneDrive\Documents\Coding\Russki\mysite\vocab\views.py", line 115, in import_words
result = word_resource.import_data(dataset, dry_run=True, raise_errors=True)
File "C:\Users\mvren\miniconda3\envs\myRuEnv\lib\site-packages\import_export\resources.py", line 627, in import_data
return self.import_data_inner(dataset, dry_run, raise_errors, using_transactions, collect_failed_rows, **kwargs)
File "C:\Users\mvren\miniconda3\envs\myRuEnv\lib\site-packages\import_export\resources.py", line 673, in import_data_inner
raise row_result.errors[-1].error
File "C:\Users\mvren\miniconda3\envs\myRuEnv\lib\site-packages\import_export\resources.py", line 569, in import_row
self.save_instance(instance, using_transactions, dry_run)
File "C:\Users\mvren\miniconda3\envs\myRuEnv\lib\site-packages\import_export\resources.py", line 352, in save_instance
instance.save()
File "C:\Users\mvren\miniconda3\envs\myRuEnv\lib\site-packages\django\db\models\base.py", line 745, in save
self.save_base(using=using, force_insert=force_insert,
File "C:\Users\mvren\miniconda3\envs\myRuEnv\lib\site-packages\django\db\models\base.py", line 782, in save_base
updated = self._save_table(
File "C:\Users\mvren\miniconda3\envs\myRuEnv\lib\site-packages\django\db\models\base.py", line 887, in _save_table
results = self._do_insert(cls._base_manager, using, fields, returning_fields, raw)
File "C:\Users\mvren\miniconda3\envs\myRuEnv\lib\site-packages\django\db\models\base.py", line 924, in _do_insert
return manager._insert(
File "C:\Users\mvren\miniconda3\envs\myRuEnv\lib\site-packages\django\db\models\manager.py", line 82, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "C:\Users\mvren\miniconda3\envs\myRuEnv\lib\site-packages\django\db\models\query.py", line 1204, in _insert
return query.get_compiler(using=using).execute_sql(returning_fields)
File "C:\Users\mvren\miniconda3\envs\myRuEnv\lib\site-packages\django\db\models\sql\compiler.py", line 1384, in execute_sql
cursor.execute(sql, params)
File "C:\Users\mvren\miniconda3\envs\myRuEnv\lib\site-packages\django\db\backends\utils.py", line 100, in execute
return super().execute(sql, params)
File "C:\Users\mvren\miniconda3\envs\myRuEnv\lib\site-packages\django\db\backends\utils.py", line 68, in execute
return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
File "C:\Users\mvren\miniconda3\envs\myRuEnv\lib\site-packages\django\db\backends\utils.py", line 77, in _execute_with_wrappers
return executor(sql, params, many, context)
File "C:\Users\mvren\miniconda3\envs\myRuEnv\lib\site-packages\django\db\backends\utils.py", line 86, in _execute
return self.cursor.execute(sql, params)
File "C:\Users\mvren\miniconda3\envs\myRuEnv\lib\site-packages\django\db\utils.py", line 90, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "C:\Users\mvren\miniconda3\envs\myRuEnv\lib\site-packages\django\db\backends\utils.py", line 86, in _execute
return self.cursor.execute(sql, params)
File "C:\Users\mvren\miniconda3\envs\myRuEnv\lib\site-packages\django\db\backends\sqlite3\base.py", line 396, in execute
return Database.Cursor.execute(self, query, params)
Exception Type: IntegrityError at /vocab/import/
Exception Value: NOT NULL constraint failed: vocab_word.user_id
Su error es bastante claro: el objeto no se puede crear porque el user_id
campo es nulo en el momento de la creación:
NOT NULL constraint failed: vocab_word.user_id
Su csv contiene:
username;Russian;Meaning;Example Sentence;Fluency level;Deck name
testuser;word1;word2;one two three;1;new
Su Word
modelo también define un campo de usuario:
user = models.ForeignKey(User, related_name="words",on_delete=models.CASCADE)
Esto significa que cuando declaras un Resource
archivo en django-import-export, necesitas especificar cómo username
se puede asignar el csv a cualquier user
instancia existente a través de la relación FK.
Debería usarlo ForeignKeyWidget
para esto, porque maneja la asignación de campos csv a objetos.
column_name
define la columna csv que usamos para buscar referencias de usuariosattribute
define el atributo en el Word
modelo que se va a configurarAdemás, debemos asegurarnos de que las relaciones de usuario se busquen utilizando el campo "correcto". De los documentos :
El campo de búsqueda utiliza de forma predeterminada la clave principal (pk) como criterio de búsqueda, pero se puede personalizar para usar cualquier campo en el modelo relacionado.
Poniéndolo todo junto, nuestra Field
definición se ve así:
userid = fields.Field(column_name='username', attribute='user', widget=widgets.ForeignKeyWidget(User, "username")
Así que creo que la fuente de su error fue que estaban colocando incorrectamente attribute
a username
. Si depuró el código, probablemente encontrará que la User
instancia 'testuser' se ha cargado y asignado Word.username
, lo que simplemente se ignorará y Word.user
será nulo, de ahí el error.
Actualizar
Otro problema para corregir:
La fields
declaración debe hacer referencia a los atributos del modelo que se establecerán a partir de datos csv.
Por lo tanto, el username
campo debería user
, porque este es el atributo del modelo a actualizar.
fields = ("user", "target_word",'source_word','example_sentence', 'fluency', 'deck_name',)
La estrella de HGTV, Christina Hall, revela que le diagnosticaron envenenamiento por mercurio y plomo, probablemente debido a su trabajo como manipuladora de casas.
Recientemente salió a la luz un informe policial que acusa a la estrella de 'Love Is Blind', Brennon, de violencia doméstica. Ahora, Brennon ha respondido a los reclamos.
Conozca cómo Wynonna Judd se dio cuenta de que ahora es la matriarca de la familia mientras organizaba la primera celebración de Acción de Gracias desde que murió su madre, Naomi Judd.
Descubra por qué un destacado experto en lenguaje corporal cree que es fácil trazar "tales paralelismos" entre la princesa Kate Middleton y la princesa Diana.
Los inodoros arrojan columnas de aerosol invisibles con cada descarga. ¿Como sabemos? La prueba fue capturada por láseres de alta potencia.
Air travel is far more than getting from point A to point B safely. How much do you know about the million little details that go into flying on airplanes?
The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!
¿Sigue siendo efectivo ese lote de repelente de insectos que te quedó del verano pasado? Si es así, ¿por cuánto tiempo?
Tapas elásticas de silicona de Tomorrow's Kitchen, paquete de 12 | $14 | Amazonas | Código promocional 20OFFKINJALids son básicamente los calcetines de la cocina; siempre perdiéndose, dejando contenedores huérfanos que nunca podrán volver a cerrarse. Pero, ¿y si sus tapas pudieran estirarse y adaptarse a todos los recipientes, ollas, sartenes e incluso frutas en rodajas grandes que sobran? Nunca más tendrás que preocuparte por perder esa tapa tan específica.
Hemos pirateado algunas ciudades industriales en esta columna, como Los Ángeles y Las Vegas. Ahora es el momento de una ciudad militar-industrial-compleja.
Un minorista está enlatando su sección de tallas grandes. Pero no están tomando la categoría solo en línea o descontinuándola por completo.
Entiendo totalmente, completamente si tienes una relación difícil con los animales de peluche. Son lindos, tienen valor sentimental y es difícil separarse de ellos.
El equipo está a la espera de las medallas que ganó en los Juegos Olímpicos de Invierno de 2022 en Beijing, ya que se está resolviendo un caso de dopaje que involucra a la patinadora artística rusa Kamila Valieva.
Miles de compradores de Amazon recomiendan la funda de almohada de seda Mulberry, y está a la venta en este momento. La funda de almohada de seda viene en varios colores y ayuda a mantener el cabello suave y la piel clara. Compre las fundas de almohada de seda mientras tienen hasta un 46 por ciento de descuento en Amazon
El jueves se presentó una denuncia de delito menor amenazante agravado contra Joe Mixon.
El Departamento de Policía de Lafayette comenzó a investigar a un profesor de la Universidad de Purdue en diciembre después de recibir varias denuncias de un "hombre sospechoso que se acercaba a una mujer".
Al igual que el mundo que nos rodea, el lenguaje siempre está cambiando. Mientras que en eras anteriores los cambios en el idioma ocurrían durante años o incluso décadas, ahora pueden ocurrir en cuestión de días o incluso horas.
Estoy de vuelta por primera vez en seis años. No puedo decirte cuánto tiempo he estado esperando esto.
Cómo mejoramos la accesibilidad de nuestro componente de precio, y cómo nos marcó el camino hacia nuevos saberes para nuestro sistema de diseño. Por Ana Calderon y Laura Sarmiento Leer esta historia en inglés.
“And a river went out of Eden to water the garden, and from thence it was parted and became into four heads” Genesis 2:10. ? The heart is located in the middle of the thoracic cavity, pointing eastward.