I have two csv files, pricat.csv
which contains objects I need to populate my DB with, and mapping.csv
which specifies how the value in pricat.csv
must be displayed in my DB, for ex: 'NW 17-18'
in pricat.csv
has to be 'Winter Collection 2017/2018'
in my DB. Here the csvs, first row in both are the headers:
ean;supplier;brand;catalog_code;collection;season;article_structure_code;article_number;article_number_2;article_number_3;color_code;size_group_code;size_code;size_name;currency;price_buy_gross;price_buy_net;discount_rate;price_sell;material;target_area
8719245200978;Rupesco BV;Via Vai;;NW 17-18;winter;10;15189-02;15189-02 Aviation Nero;Aviation;1;EU;38;38;EUR;;58.5;;139.95;Aviation;Woman Shoes
8719245200985;Rupesco BV;Via Vai;;NW 17-18;winter;10;15189-02;15189-02 Aviation Nero;Aviation;1;EU;39;39;EUR;;58.5;;139.95;Aviation;Woman Shoes
source;destination;source_type;destination_type
winter;Winter;season;season
summer;Summer;season;season
NW 17-18;Winter Collection 2017/2018;collection;collection
EU;European sizes;size_group_code;size_group
EU|36;European size 36;size_group_code|size_code;size
EU|37;European size 37;size_group_code|size_code;size
EU|38;European size 38;size_group_code|size_code;size
EU|39;European size 39;size_group_code|size_code;size
EU|40;European size 40;size_group_code|size_code;size
EU|41;European size 41;size_group_code|size_code;size
EU|42;European size 42;size_group_code|size_code;size
4;Boot;article_structure_code;article_structure
5;Sneaker;article_structure_code;article_structure
6;Slipper;article_structure_code;article_structure
7;Loafer;article_structure_code;article_structure
8;Mocassin;article_structure_code;article_structure
9;Sandal;article_structure_code;article_structure
10;Pump;article_structure_code;article_structure
1;Nero;color_code;color
2;Marrone;color_code;color
3;Brandy Nero;color_code;color
4;Indaco Nero;color_code;color
5;Fucile;color_code;color
6;Bosco Nero;color_code;color
In my models.py
in Django I have three models: Catalog
--> Article
--> Variation
the attributes of my models are manually named as mapping.csv
specifies, for ex: Variation
will not have a color_code
attribute but color
.
To populate the DB I've created a custom Django command which reads the rows in pricat.csv
and create istances like this:
x = Catalog.objects.get_or_create(brand=info[2], supplier=info[1], catalog_code=info[3],
collection=map_dict[info[4]],
season=map_dict[info[5]], size_group=map_dict[info[11]],
currency=info[14], target_area=info[20])
y = Article.objects.get_or_create(article_structure=map_dict[info[6]],
article_number=info[7], catalog=x[0])
z = Variation.objects.get_or_create(ean=info[0], article=y[0], size_code=info[12], color=map_col[info[10]],
material=info[19], price_buy_gross=info[15], price_buy_net=info[16],
discount_rate=info[17], price_sell=info[18], size=f'{map_dict[info[11]]} {info[12]}')
info
is a list of all the value in a pricat.csv
row and map_dict
and map_col
are two dictionaries I create with two func() from the mapping.csv
:
def mapping(map_file):
with open(map_file, 'r') as f:
f = [l.strip('\n') for l in f]
map_dict = {}
for l in f[1:19]:
info = l.strip().split(';')
source = info[0]
destination = info[1]
source_type = info[2]
destination_type = info[3]
map_dict[source] = destination
map_dict[source_type] = destination_type
return map_dict
def mapping_color(map_file):
with open(map_file, 'r') as f:
f = [l.strip('\n') for l in f]
map_dict = {}
for l in f[19:]:
info = l.strip().split(';')
source = info[0]
destination = info[1]
source_type = info[2]
destination_type = info[3]
map_dict[source] = destination
map_dict[source_type] = destination_type
return map_dict
map_dict = mapping('mapping.csv')
map_col = mapping_color('mapping.csv')
I had to create two dict because a single one would have duplicate keys.
The code works fine and the DB is populated as intended, but I feel the way I did the mapping is bad practice, also both my command and funcs relies on indeces so the values in my csvs have to be in that specific order to work. I would greatly appreciate any suggestion on how to improve my code or accomplish this task, I hope my explanation is clear.
EDIT:
class Catalog(models.Model):
brand = models.CharField(max_length=255)
supplier = models.CharField(max_length=255)
catalog_code = models.CharField(max_length=255, default=1, blank=True)
collection = models.CharField(max_length=255)
season = models.CharField(max_length=255)
size_group = models.CharField(max_length=2)
currency = models.CharField(max_length=3)
target_area = models.CharField(max_length=255)
def __str__(self):
return self.brand
def get_articles(self):
return Article.objects.filter(catalog=self.pk)
class Article(models.Model):
article_structure = models.CharField(max_length=255)
article_number = models.CharField(max_length=255)
catalog = models.ForeignKey(Catalog, on_delete=models.CASCADE)
def __str__(self):
return f'{self.article_number} | {self.article_structure}'
class Variation(models.Model):
ean = models.CharField(max_length=255)
article = models.ForeignKey(Article, on_delete=models.CASCADE)
size_code = models.IntegerField()
size = models.CharField(max_length=255, default=0)
color = models.CharField(max_length=255)
material = models.CharField(max_length=255)
price_buy_gross = models.CharField(max_length=255)
price_buy_net = models.FloatField()
discount_rate = models.CharField(max_length=255, default=0)
price_sell = models.FloatField()
def __str__(self):
return f'Ean: {self.ean}, article: {self.article}'
I've created a new mapping()
def mapping(map_file):
with open(map_file, 'r') as f:
f = [l.strip('\n') for l in f]
map_dict = {}
for l in f[1:]:
info = l.strip().split(';')
source = info[0]
destination = info[1]
source_type = info[2]
child_dict = {source: destination}
map_dict[source_type] = map_dict.get(source_type, {source: destination})
map_dict[source_type].update(child_dict)
return map_dict
It returns a nested dict, I'm trying to finda solution using this single nested dict instead of 2 dicts like before.