views.py
def contact_list(request):
importform = ImportExcelForm()
if request.method == 'POST':
importform = ImportExcelForm(request.POST, request.FILES)
if importform.is_valid():
input_excel = request.FILES['input_excel']
book = xlrd.open_workbook(file_contents=input_excel.read())
excel_parser= ExcelParser()
success, log = excel_parser.read_excel(request.FILES['input_excel'] )
return redirect('/member/incident-types/')
else:
importform = ImportExcelForm()
return render(request, 'incident/contact_list.html',
{
'about_menu': True,
'ImportExcelForm':importform,
})
forms.py
class ImportExcelForm(Form):
input_excel = forms.FileField()
user = forms.ModelChoiceField(queryset=Contacts.objects.all())
def save(self):
records = xls.reader(self.cleaned_data["input_excel"])
for line in records:
input_data = Data()
input_data.place = self.cleaned_data["user"]
input_data.name = line[1]
input_data.number = line[2]
input_data.save()
models.py
class Contacts(models.Model):
user = models.ForeignKey(User, null=True)
name = models.CharField('Name', max_length=100)
number = models.IntegerField()
This is to import the xls file,read and write the name and contact number in xls file to database field.I am not getting any error in this but it is not parsing the data in database.
I'm not sure what you're expecting to happen here. Your form save method (assuming it's indented correctly, which it isn't) iterates over the contents of self.cleaned_data["input_excel"], which is a filename, not a file. But in any case, your view does not call the save method at any point. What it does do is use a completely different set of Excel parsing functions, reads them into a pair of local variables, then does nothing at all with the contents of those variables which go out of scope when the function returns.
I suggest you think about exactly what your logic flow should be, write that down, then write the code to match it.
Related
This code return a TypeError as expected str, bytes or os.PathLike object, not InMemoryUploadedFile
I don't know how to pass user data in the form of file and image to my code.py file for making changes to the original.
views.py
def home(request):
new_image = None
file = None
form = ScanForm()
if request.method == 'POST':
form = ScanForm(request.POST, request.FILES)
if form.is_valid():
image = request.FILES['image']
xml_file = request.FILES['xml_file']
new_image = code.create(image, code.search(
xml_file)[0], code.search(xml_file)[1])
form.save()
return render(request, 'app/home.html', {'form': form, 'new_image': new_image})
else:
form = ScanForm()
return render(request, 'app/home.html', {'form': form, 'new_image': new_image})
printing image and xml_file successfully prints out their names
forms.py
class ScanForm(forms.ModelForm):
class Meta:
model = Scan
fields = '__all__'
models.py
class Scan(models.Model):
image = models.ImageField(upload_to='images')
xml_file = models.FileField(upload_to='files')
processed_at = models.DateTimeField(auto_now_add=True)
description = models.CharField(max_length=500, null=True)
class Meta:
ordering = ['-processed_at']
def __str__(self):
return self.description
Here is the code for manipulation of image according to the data in the xml
code.py
def search(path):
new = []
object_names = []
object_values = []
txt = Path(path).read_text()
txt.strip()
names = et.fromstring(txt).findall('object')
for i in names:
object_names.append(i[0].text)
values = et.fromstring(txt).findall('object/bndbox')
for i in values:
for j in i:
object_values.append(int(j.text))
return object_names, object_values
def create(image, object_names, object_values):
img = cv.imread(image)
on = len(object_names)
ov = len(object_values)
for i in list(range(0, ov, on)):
cv.rectangle(img, (object_values[i], object_values[i+1]),
(object_values[i+2], object_values[i+3]), (0, 0, 255), thickness=5)
return img
This code.py works fine if tested by passing data manually using local folder.
Here is the Traceback:
Traceback image
pathlib.Path() handles file paths, not memory objects. request.FILES are the data attached to the POST request. During your handling of a POST request, you can validate this data and decide to save it to the server disk.
If you would like your image processing to read the file from the server disk, you have to save the new model instance first. You can then access the file's path on disk through the name attribute of the model's ImageField, see Using files in models.
If you want to handle the uploaded data before saving it to disk, you can read it as follows:
txt = request.FILES["xml_file"].read()
See UploadedFile.read()
I have a ModelForm that selects one field and excludes the rest, one of which is a ForeignKey that I need to populate manually before saving the form.
I'm in the process of fixing a bug that one of my views has and I'm making use of the request.session object to store information so that the GET and POST method funcions will be in synced by the session in locating the model at hand instead of separately iterating though the database to pin-point what model object the submitted data should be saved for.
I'm making use of the form_object.save(commit=False) funcionality in other places of the same view and it works as I need but for some reason there is a section of the view where it just doesn't populate the extra field before calling the eventual save() method and I get an IntegrityError for that column in the database, even if it is not null=False in my model declaration right now (and I think it'd rather should be..).
So here's my ModelForm:
class PesoFormApertura(ModelForm):
peso_apertura = forms.DecimalField(min_value=0,required=True)
class Meta:
model = Peso
fields = ('peso_apertura',)
here's the Model itself:
class Peso(models.Model):
prodotto = models.ForeignKey(ProdottoPesato,on_delete=models.CASCADE)
peso_apertura = models.DecimalField(max_digits=8,decimal_places=2, blank=False, null=True)
peso_calcolato = models.DecimalField(max_digits=8,decimal_places=2, blank=True, null=True)
peso_chiusura = models.DecimalField(max_digits=8,decimal_places=2, blank=True, null=True)
data = models.DateField(auto_now_add=True, blank = False)
def __str__(self):
return "{} - {} - {}".format(self.prodotto.nome, self.prodotto.get_categoria_display(), self.data)
def save(self, *args, **kwargs):
if self.peso_apertura == 0:
prodotto_associato = ProdottoPesato.objects.get(pk = self.prodotto.pk)
if prodotto_associato.permanente == False:
prodotto_associato.delete()
self.delete()
else:
super().save(*args, **kwargs)
else:
super().save(*args, **kwargs)
class Meta:
ordering = ['prodotto']
and here's the view part where the save() method is failing (where I placed a comment):
if not 'prodotto-da-correggere' in request.session:
for prodotto in tutti_prodotti:
pesi_questo_prodotto_oggi = prodotto.pesi_di_oggi()
for peso in pesi_questo_prodotto_oggi:
if peso.peso_apertura == None:
prodotto_da_elaborare = prodotto
peso_del_giorno = peso
break
if prodotto_da_elaborare:
finito = False
instance_peso = peso_del_giorno
form = PesoFormApertura(request.POST, instance = instance_peso)
if form.is_valid():
form.save(commit=False) # WORKS FINE
form.prodotto = prodotto_da_elaborare
form.save()
else:
form = PesoFormApertura(request.POST)
else: # HERE IS WHERE IT DOESN'T BEHAVE LIKE ABOVE
prodotto_da_elaborare = ProdottoPesato.objects.get(id=request.session['prodotto-da-correggere'])
peso_del_giorno = None
for peso in prodotto_da_elaborare.pesi_di_oggi():
if peso.peso_apertura == None or peso.peso_apertura > 0:
peso_del_giorno = peso
break
form_correzione = PesoFormApertura(request.POST, instance = peso_del_giorno)
if form_correzione.is_valid():
form_correzione.save(commit=False)
form_correzione.prodotto = prodotto_da_elaborare
form_correzione.save() # IT DOESN'T ADD THE INFORMATION TO THE COLUMN WHEN IT SAVES
request.session.flush()
The save() method works alright for the first part of the IF statement and just doesn't work for the rest of the snippet in the ELSE section.
So I'm wondering if the session has something to do with this.
When you call form.save() it returns the instance. You should modify and save that instance.
if form_correzione.is_valid():
peso = form_correzione.save(commit=False)
peso = prodotto_da_elaborare
peso.save()
You should change the other part of the view to use this approach as well. It looks like form.prodotto = prodotto_da_elaborare is having no effect, but you haven't noticed because prodotto is already set so you don't get an integrity error.
I like clarifying that I'm new to Django.
Versions:
Django 1.5
Python 2.7
PostgreSQL 9.3
I have a webapp that uploads a file to AWS S3, this works currently. I would like to name the file the name of the contentid field that gets auto assigned a V4 UUID on upload. I'll try and pick out the relevant information and post it here. I'm not sure where I would gather this information and declare it for the name.
View
def upload_content(request):
if request.method == 'POST':
form = ContentForm(request.POST, request.FILES)
if form.is_valid():
new_content = Content(name=request.POST['name'],accountid=request.user.id,public=False,url=request.POST['name'],uploaddate=datetime.now(),viewcount='0',file = request.FILES['file'])
new_content.save()
return HttpResponseRedirect('/Console/Content/')
Model
class Content(models.Model):
name = models.CharField(max_length=128)
accountid = models.IntegerField(max_length=34)
url = models.CharField(max_length=200)
uploaddate = models.DateTimeField('date published')
viewcount = models.IntegerField(max_length=34)
public = models.BooleanField(max_length=1)
contentid = UUIDField(unique=True,editable=False)
file = models.FileField(upload_to='content')
#classmethod
def get_content_list(cls, account):
cursor = connection.cursor()
cursor.execute('SELECT name, contentid, public, uploaddate, id FROM webapp_content WHERE accountid=%s ORDER BY uploaddate', [account])
ret = cursor.fetchall()
return ret
So I have somewhat of an answer, but I'm still left with an issue
model:
def generate_new_filename(instance, filename):
ext = filename.split('.')[-1]
filename = '{}.{}'.format(uuid.uuid4().hex, ext)
return (filename)
class Content(models.Model):
file = models.FileField(upload_to=generate_new_filename)
view:
still the same as above, how do I write to my sql the newly generated filename on save in place of request.FILES['file']
The outcome:
file get's written the correct variable, url does not
i can't figure out how to save my form data creating a new row, when saving it just rewrites the data using the same 'id' and trhows me an error when there are multiple rows, this is my code:
models.py:
class Submitter(models.Model):
submitter=models.ForeignKey(User)
def __unicode__(self):
return self.submitter.username
class Store(models.Model):
creator=models.ForeignKey(Submitter)
name = models.CharField(_('name'),blank=True,max_length=30)
st = models.CharField(_('Street'),blank=True,max_length=30)
sub_date = models.DateField(_('Visit Date'),)
def __str__(self):
return u'%s-%s-%s'%(self.creator,self.name,self.sub_date)
views.py:
def StoreSave(request):
if request.method == 'POST':
form = StoreForm(request.POST)
if form.is_valid():
submitter, dummy= Creator.objects.get_or_create(creator=request.user)
store, created = Store.objects.get_or_create(
submitter=submitter
)
store.name = form.cleaned_data['name']
store.st = form.cleaned_data['st']
store.visit_date = form.cleaned_data['visit_date']
store.save()
return HttpResponseRedirect('/user/%s/' % request.user.username)
else:
form = StoreForm()
variables = RequestContext(request, {
'form': form
})
return render_to_response('store/create_store.html', variables)
If you want to create a new row, create it. :-) Like
store = Store(submitter=submitter,
name=form.cleaned_data['name'],
st=form.cleaned_data['st'],
store.visit_date=form.cleaned_data['visit_date'])
store.save()
Now you use get_or_create method which tries to find a row with given parameters, so that's why you updating it. And this method throws an error when there are multiple rows, yes, it's its normal behavior.
By the way it's better to place this saving code in form's method (save for example).
P. S. Just noticed you don't have visit_date field in your model, I think you meant sub_date.
Instead of using get_or_create you can simply use create
Store.objects.create(
submitter=submitter,
name=form.cleaned_data['name'],
st=form.cleaned_data['st'],
visit_date=form.cleaned_data['visit_date']
)
More information about the differences can be found Django Model() vs Model.objects.create()
I've tried to import a csv file into a database by tweaking the modelform inside the admin doing this:
models.py:
class Data(models.Model):
place = models.ForeignKey(Places)
time = models.DateTimeField()
data_1 = models.DecimalField(max_digits=3, decimal_places=1)
data_2 = models.DecimalField(max_digits=3, decimal_places=1)
data_3 = models.DecimalField(max_digits=4, decimal_places=1)
Forms.py:
import csv
class DataImport(ModelForm):
file_to_import = forms.FileField()
class Meta:
model = Data
fields = ("file_to_import", "place")
def save(self, commit=False, *args, **kwargs):
form_input = DataImport()
self.place = self.cleaned_data['place']
file_csv = request.FILES['file_to_import']
datafile = open(file_csv, 'rb')
records = csv.reader(datafile)
for line in records:
self.time = line[1]
self.data_1 = line[2]
self.data_2 = line[3]
self.data_3 = line[4]
form_input.save()
datafile.close()
Admin.py:
class DataAdmin(admin.ModelAdmin):
list_display = ("place", "time")
form = DataImport
admin.site.register(Data, DataAdmin)
But i'm stuck trying to import the file i put in "file_to_import" field. Getting AttributeError in forms.py : 'function' object has no attribute 'FILES'.
What i'm doing wrong?
After a long search i found an answer: Create a view inside the admin using a standard form
Form:
class DataInput(forms.Form):
file = forms.FileField()
place = forms.ModelChoiceField(queryset=Place.objects.all())
def save(self):
records = csv.reader(self.cleaned_data["file"])
for line in records:
input_data = Data()
input_data.place = self.cleaned_data["place"]
input_data.time = datetime.strptime(line[1], "%m/%d/%y %H:%M:%S")
input_data.data_1 = line[2]
input_data.data_2 = line[3]
input_data.data_3 = line[4]
input_data.save()
The view:
#staff_member_required
def import(request):
if request.method == "POST":
form = DataInput(request.POST, request.FILES)
if form.is_valid():
form.save()
success = True
context = {"form": form, "success": success}
return render_to_response("imported.html", context,
context_instance=RequestContext(request))
else:
form = DataInput()
context = {"form": form}
return render_to_response("imported.html", context,
context_instance=RequestContext(request))
The rest is part of this post:
http://web.archive.org/web/20100605043304/http://www.beardygeek.com/2010/03/adding-views-to-the-django-admin/
Take a look at django-admin-import, it does more or less exactly what you want -- you can upload a XLS (not a CSV, but that should not matter) and lets you assign columns to model fields. Default values are also supported.
https://pypi.org/project/django-admin-import/
Additionally, it does not take away the possibility to modify individual records by hand because you don't have to replace the default model form used in the administration.
In the save() method, you don't have any access to the request object - you can see that it's not passed in. Normally you would expect to have a NameError there, but I suspect that you've got a function elsewhere in the file called request().
At the point of saving, all the relevant data should be in cleaned_data: so you should be able to do
file_csv = self.cleaned_data['file_to_import']
At that point you'll have another problem, which is when you get to open - you can't do that, as file_to_import is not a file on the server filesystem, it's an in-memory file that has been streamed from the client. You should be able to pass file_csv directly to csv.reader.