How can I put data is parsed from excel to model? - python

I parsed excel and get row data in list. It is like
[empty:'', text:’1', text:’1’, text:’40’, text:'']
[empty:'', text:’2’, text:’5’, text:’23’, text:’●’]
[empty:'', text:’3’, text:’9’, text:’52’, text:'']
My excel(data.xlsx) is
so list output is ok.Now I wanna put this list to model(User).
User model in models.py is
class User(models.Model):
user_id = models.CharField(max_length=200)
name_id = models.CharField(max_length=200)
age = models.CharField(max_length=200)
man = models.BooleanField()
The last code of man = models.BooleanField() means man or woman,if ’●’ in excel,it means the user is man and true wanna be put in man variable.
Now views.py is
#coding:utf-8
from django.shortcuts import render
import xlrd
book = xlrd.open_workbook('../data/data.xlsx')
sheet = book.sheet_by_index(1)
for row_index in range(sheet.nrows):
row = sheet.row(row_index)
print(row)
# I had to add codes connect controller & model
I do not know how to send these list data to model and model has these data.Strictly speaking,I wanna write these list data to sqlite3.Is this code
import app.models
for x in row:
User.user_id = row[1]
User.name_id = row[2]
User.age = row[3]
User.man = row[4]
good way to write model?(or is it wrong way?)
Is there other more efficient way to do it?

Assuming you have the whole row and columns thing right, this should work:
for row in rows:
# if the man column is not empty, we assume it's a male:
is_man = row[4] != ""
user = User(user_id=row[1], name_id=row[2], age=row[3], man=is_man)
user.save()

Related

Xlwt Excel Export Foreign Key By Actual Values / Django

I export products in excel format using xlwt.But foreign key fields are exported as id.
How can I export foreign key fields with their actual values?
I want to export brand_id and author fields with their actual values.
Here is my product model :
class Product(models.Model):
id = models.AutoField(primary_key=True)
author = models.ForeignKey(User,on_delete= models.CASCADE, verbose_name='Product Author', null=True)
brand_id = models.ForeignKey(Brand,on_delete=models.CASCADE, verbose_name="Brand Names")
name = models.CharField(max_length=255, verbose_name="Product Name")
barcode = models.CharField(max_length=255, verbose_name="Barcode")
unit = models.CharField(max_length=255,verbose_name="Product Unit")
def __str__(self):
return self.name
Here is my export view:
def export_excel(request):
response = HttpResponse(content_type='application/ms-excel')
response['Content-Disposition'] = "attachment; filename=Products-" + str(datetime.datetime.now().date())+".xls"
wb = xlwt.Workbook(encoding="utf-8")
ws = wb.add_sheet('Products')
row_num = 0
font_style = xlwt.XFStyle()
font_style.font.bold = True
columns = ["Product Id","Product Author","Product Brand","Product Name","Product Barcode","Product Unit"]
for col_num in range(len(columns)):
ws.write(row_num,col_num,columns[col_num],font_style)
font_style = xlwt.XFStyle()
rows = Product.objects.filter(author = request.user).values_list("id","author","brand_id","name","barcode","unit")
for row in rows:
row_num +=1
for col_num in range(len(row)):
ws.write(row_num,col_num,str(row[col_num]), font_style)
wb.save(response)
Thanks for your help. Kind regards
You could use django-import-export to export the data from a model to an excel file. This library also supports other data types in case you need them in the future.
As described in the documentation of django-import-export you can create a resource, which can then be used to both import and export data into a model. Start by creating a resource:
from import_export import resources
from import_export.fields import Field
from .models import Product
class ProductResource(resources.ModelResource):
author = Field() # for field with foreignkeys you need to add them here
brand_id = Field() # for field with foreignkeys you need to add them here
fields = ["id", "author", "brand_id", "name", "barcode", "unit"]
export_order = ["id", "author", "brand_id", "name", "barcode", "unit"]
def dehydrate_author(self, product: Product) -> str:
return f"{product.author.name}" # probably need to adapt the name of the field
def dehydrate_brand_id(self, product: Product) -> str:
return f"{product.brand_id.brand}" # probably need to adapt the name of the field
This is also documented here: django-import-export advanced manipulation
Now you can use this ModelResource to export your data to any supported format, in your case an Excel file. Import your resource you've created earlier all you need to do to return this in your view is the following:
from django.http import HttpResponse
from .resource import ProductRes
#... other code in your view
project_resource = ProjectResource()
dataset = project_resource.export()
response = HttpResponse(dataset.xlsx, ontent_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
response["Content-Disposition"] = 'attachment; filename="projects_export.xlsx"'

Django query filter by another dataset

I have 2 User models:
User: Default user model:
Account: Custom User model, which is an extension of the defualt user model, as I wanted to add a custom field to it called 'Status'.
The problem is that I wanted to filter the data based on the current User, so id usually do something like:
Account.objects.filter(usernmae = User).values_list('status', flat=True)
The problem is that the Account dataset doesnt have the username but they both have the same ID.
I was thinking of doing something like this:
Status = Account.objects.filter(user_id=User.objects.filter(username = user).values_list('id', flat=True)).values_list('status', flat=True)
But then i get the following error:
I imagine there is a way better way of doing it, if yall could help me out.
Views.py:
def upload_audits(request):
form = audits_form(request.POST or None, request.FILES or None)
if form.is_valid():
form.save()
form = audits_form()
obj = Csv_Audit.objects.get(activated=True)
with open(obj.file_name.path,'r') as f:
#to clear model contents before applying new data
auditsModel.objects.all().delete()
reader = csv.reader(f)
for i,row in enumerate(reader):
if i==0:
pass
else:
user = row[1] # gets data from CSV Table and returns username
Status = Account.objects.filter(user_id = request.user).values_list('status')
auditsModel.objects.create(
qs_login = user,
Status = Status,
)
obj.activated = True
obj.save()
return render(request,"backend/uploads.html",{'form':form})
Accounts.py(Model)
class Account(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
status = models.CharField(('Status'), max_length=200, default='',choices = [('Bau','Bau'),('Week 1','Week 1')])
def __str__(self):
return self.user.username
1 Answer:mahdi rahimi
I tried your method with the following code:
Status = Account.objects.filter(user__username = user).values_list('status', flat=True)
Which resulted in the following error:
And then I thought of doing this:
Status = Account.objects.filter(user = user).values_list('status', flat=True)
But i got this error:
Which actually returns the usernmae but it seems to be asking for an int?
based on my experience, you can simply join the two tables, and get what you want. roughly, it translates to this:
result = Account.objects.filter(user__username = user).values_list('status', flat=True)
or you can do two queries if you are comfortable with that.
found_user_id = User.objects.filter(username = user).values_list('id', flat = True)
result = Account.objects.filter(user_id = found_user_id).values_list('status', flat=True)
hope that helped.

Getting TypeError: byte indices must be integers or slices, not str

I have a model table by the name of Branches which is to be filed automatically from the CSV file hosted online. But, I keep getting the error
How I can resolve this?
Thanks
from django.db import models
class Branches(models.Model):
ifsc = models.CharField(max_length=1009)
bank_id = models.IntegerField()
branch = models.CharField(max_length=1009)
address = models.CharField(max_length=1500)
city = models.CharField(max_length=1999)
district = models.CharField(max_length=1999)
state = models.CharField(max_length=1000)
bank_name = models.CharField(max_length=1000)
def __str__(self):
return self.branch
from urllib.request import urlopen, Request
from io import StringIO
import csv
for row in urlopen('https://raw.githubusercontent.com/snarayanank2/indian_banks/dc7ac64137ecf24bfc564f3d6151331215cf4783/bank_branches.csv'):
Branches.objects.create(ifsc=row['ifsc'], bank_id=row['bank_id'], branch=row['branch'], address=row['address'], city=row['city'], district=row['district'], state=row['state'], bank_name=row['bank_name'])
Expanding on Daniel Nudelmans comment, this is how you would use split with your current code:
for row in urlopen('https://raw.githubusercontent.com/snarayanank2/...'):
row = row.split(",")
# row is now a list containing all the values from the row
Branches.objects.create(ifsc=row[0], bank_id=row[1], branch=row[2], address=row[3], city=row[4], district=row[5], state=row[6], bank_name=row[7])
Keep in mind if the CSV has headers (like "ifsc", "bank_id", etc. as the first row), in the first iteration of the for loop, row will be the names of the headers.

Add additional fields after phone number lookup in the database in Django

I am building an app that look for each phone number in the database. If there is any duplicate, I want to grab the first phone number found as the main record for that phone number, then for the duplicate information(name, location), get each one of those fields, and add it to the main record phone number fields (name, location), separated by a semi colon.
The outcome would look like this after checking the duplicate information of the main phone number record found:
Name Location Phone number
Helene,Sandra New Yok, Boston 000-000
Please find my model below:
class Document(models.Model):
name = models.CharField(null=True, max_length=254, blank=True)
location = models.CharField(null=True, max_length=254, blank=True)
phone_number = models.CharField(null=True, max_length=254, blank=True)
I am a bit lost on to achieve the above. Any help would be much appreciated.
Below is what I have tried so far:(not working)
from django.shortcuts import render
from .models import Document
def index(request):
search_number = list(Document.objects.order_by('-created').values("phone_number").distinct().order_by()) # Dictionary list of all numbers sorted by creation data without duplicate
for x in search_number:
try:
look_up = Document.objects.values("phone_number")
list_in_dba = look_up.phone_number
x in list_in_dba['phone_number']
print("Yes")
except:
print("No")
return render(request, 'snippets/index.html')
I would start with something like this.
## this will get you all document records that have a duplicate phone-number
## and also group them by phone-number.
duplicate_phone_numbers = Document.objects.values('phone_number').\
annotate(total_items=Count('phone_number')).order_by('-total_items').filter(total_items__gt=1)
for entry in duplicate_phone_numbers:
records = Document.objects.filter(phone_number=entry.get('phone_number')
## unsure whether you want to just output the info here or
## update the actual record
all_names = ''
all_locations = ''
for x in records:
all_names += x.name + ";"
all_locations += x.location + ";"
print all_names, all_locations, entry.get('phone_number')
# to update the actual record
record = records[0]
record.name = all_names
record.location = all_locations
record.save()

Only last excel data is put in model

I wanna parse excel and put data in the model(User). However now,only last excel data is put in model and the number of the data is 4.4 is the number of all excel rows like
Now db.sqlite3 is
|10|Karen|||
|10|Karen|||
|10|Karen|||
|10|Karen|||
My ideal db.sqlite3 is
1|1|Blear|40|false|l
2|5|Tom|23|true|o
3|9|Rose|52|false|m
|10|Karen|||
all data wanna be put in there.
Why does such result happen?
views.py is
#coding:utf-8
from django.shortcuts import render
import xlrd
from .models import User
book = xlrd.open_workbook('../data/data.xlsx')
sheet = book.sheet_by_index(1)
for row_index in range(sheet.nrows):
rows = sheet.row_values(row_index)
print(rows)
def build_employee(employee):
if employee == 'leader':
return 'l'
if employee == 'manager':
return 'm'
if employee == 'others':
return 'o'
for row in rows:
is_man = rows[4] != ""
emp = build_employee(rows[5])
user = User(user_id=rows[1], name_id=rows[2], name=rows[3],
age=rows[4],man=is_man,employee=emp)
user.save()
When i print out rows in print(rows) ,result is
Blear
Tom
Rose
Karen
so I think rows has all data in excel.
models.py is
class User(models.Model):
user_id = models.CharField(max_length=200)
name_id = models.CharField(max_length=200)
name = models.CharField(max_length=200)
age = models.CharField(max_length=200)
man = models.BooleanField()
TYPE_CHOICES = (
('m', 'manager'),
('l', 'leader'),
('o', 'others'),
)
employee =models.CharField(max_length=1, choices=TYPE_CHOICES)
How can i fix this?
At the end of this block rows has only the values of last row(The row withKaren).
for row_index in range(sheet.nrows):
rows = sheet.row_values(row_index)
print(rows)
Now after the above when you do the below you are iterating over values in the last row. Also remember you are not using row inside the for block which is a single cell value iterating over['',10,'Karen','','','']
for row in rows:
is_man = rows[4] != ""
emp = build_employee(rows[5])
user = User(user_id=rows[1], name_id=rows[2], name=rows[3],
age=rows[4],man=is_man,employee=emp)
user.save()
You should correct the above block as below..
for row_index in range(sheet.nrows):
rows = sheet.row_values(row_index)
is_man = rows[4] != ""
emp = build_employee(rows[5])
user = User(user_id=rows[1], name_id=rows[2], name=rows[3],
age=rows[4],man=is_man,employee=emp)
user.save()
Please note that I've not taken due care about the header row. Please do so at your end if need be.

Categories

Resources