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.
Related
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"'
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()
I wanna parse excel& make dictionary and connect the model(User) which has same user_id of dictionary.
Now dictionary is
dict_data = {'user_id': 1,'nationarity': America, 'dormitory':'A', 'group': 3}
Models in views.py is
user = User(user_id=rows[1],name_id=rows[2],age=rows[3],employee=rows[4])
If I wanna add dictionary's data to model,I should write like
for data in dict_data:
User(**data)
but how should I connect dictionary's user_id& models' one?What should I write it?
Now I wrote like
#coding:utf-8
from django.shortcuts import render
import xlrd
from app.models import User
book3 = xlrd.open_workbook('./data/XXX.xlsx')
sheet3 = book3.sheet_by_index(0)
headers = sheet3.row_values(0)
large_item = None
dicts = {}
for row_index in range(sheet3.nrows):
rows3 = sheet3.row_values(row_index)
large_item = rows3[1] or large_item
# Create dict with headers and row values
row_data = {}
for idx_col, value in enumerate(rows3):
header_value = headers[idx_col]
# Avoid to add empty column. A column in your example
if header_value:
row_data[headers[idx_col]] = value
# Add row_data to your data_dict with
dicts[row_index] = row_data
for data in dicts:
user1 = User.objects.filer(user_id = data['user_id']).exists()
if user1:
user1.__dict__.update(**dicts)
user1.save()
When I run this code,
AttributeError: 'Manager' object has no attribute 'filer'
user1 = User.objects.filer(user_id = data['user_id']).exists()
How should I fix this?
for data in dict_datas:
user = User.object.filter(user_id = data['user_id']).exists()
if user:
user.__dict__.update(**dict_data)
user.save()
dict_data you posted is a dict,you shouldn't iterate it like a list.
I guess your dict_data is a list of dict, so:
for data in dict_datas:
user = User.objects.get(user_id=data['user_id'])
user.name_id = data['**']
...
user.save()
First, fetch the user object with user_id in your xecel&dict, then change the value, and save it.
I wanna parse excel& make dictionary and connect the model(User) which has same user_id of dictionary.
Excel is
user_id is in F1,so I really cannot understand how to make dictionary.
Now views.py is
#coding:utf-8
from django.shortcuts import render
import xlrd
from .models import User
book = xlrd.open_workbook('../data/excel1.xlsx')
sheet = book.sheet_by_index(1)
def build_employee(employee):
if employee == 'leader':
return 'l'
if employee == 'manager':
return 'm'
if employee == 'others':
return 'o'
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()
book2 = xlrd.open_workbook('../data/excel2.xlsx')
sheet2 = book2.sheet_by_index(0)
headers = sheet2.row_values(0)
large_item = None
data_dict = {}
for row_index in range(sheet2.nrows):
rows2 = sheet2.row_values(row_index)
large_item = rows2[1] or large_item
# Create dict with headers and row values
row_data = {}
for idx_col, value in enumerate(rows2):
header_value = headers[idx_col]
# Avoid to add empty column. A column in your example
if header_value:
row_data[headers[idx_col]] = value
# Add row_data to your data_dict with
data_dict[row_index] = row_data
for row_number, row_data in data_dict.items():
user1 = User.objects.filter(user_id = data['user_id']).exists()
if user1:
user1.__dict__.update(**data_dict)
user1.save()
My codes only can catch data in same place(in this case B4~E4),so I cannot understand how to write to achieve my goal.How should I write it?
Ideal dictionary is
{"user_id":1, "name":"Blear","nationality":"America","domitory":"A","group":1}
Your spreadsheet appears to only have one entry? If this is the case, you do not need to iterate over the rows, but instead just extract the locations you need, for example:
import xlrd
book = xlrd.open_workbook('excel1.xlsx')
sheet = book.sheet_by_index(0)
cells = [
('user_id', 0, 5),
('name', 3, 1),
('nationality', 3, 2),
('domitory', 3, 3),
('group', 3, 4)]
user1 = {key:sheet.cell_value(rowy, colx) for key, rowy, colx in cells}
print user1
Giving you:
{'nationality': u'America', 'user_id': 1.0, 'name': u'Blear', 'group': 1.0, 'domitory': u'A'}
This uses a Python dictionary comprehension to build the user1 dictionary based on cells.
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()