[Answered ]-Can I bulk upload a CSV to Django with many to one relationship mapping?

2👍

Here’s an example of what you want to do. I have stripped down the original code as it was too large. But this would still give you a good starting point.

In reality, the CSV files uploaded by the client weren’t as simple as I’ve shown in the example. Some lines were blank, some lines contained some other unnecessary info like name of the software that generated the file, name of the store etc. So I had to write some more methods in order to filter out that data. But I haven’t done that below. I’ve kept the example minimal as possible.

from django.db import models
import csv


class Category(models.Model):
    name = models.CharField(max_length=10)


class Product(models.Model):
    category = models.ForeignKey(Category)
    uid = models.CharField(max_length=4)
    name = models.CharField(max_length=10)
    price = models.IntegerField()
    qty = models.IntegerField() # quantity


class CSVFile(models.Model):
    """
    This model allows for uploading a CSV file and then 
    updates data in Category and Product models
    """
    csv_file = models.FileField(upload_to='csvfiles')
    # feel free to add other fields like upload date, etc.

    def save(self, *args, **kwargs):
        """
        This is where you analyze the CSV file and update 
        Category and Product models' data
        """
        super(CSVFile, self).save(*args, **kwargs)
        self.csv_file.open(mode='rb')
        f = csv.reader(self.csv_file)
        for row in f:
            # currently the row is a list of all fields in CSV file
            # change it to a dict for ease
            row_dict = self.row_to_dict(row) # this method is defined below
            # check if product exists in db
            product = self.product_is_in_db(row_dict['uid']) # this method is defined below
            if product:
                # product is in db
                # update fields values
                self.update_product(product, row_dict) # this method is defined below
            else:
                # product is not in db
                # create this product
                self.create_product(row_dict) # this method is defined below

        self.csv_file.close()


    def row_to_dict(self, row):
        """Returns the given row in a dict format"""
        # Here's how the row list looks like:
        # ['category', 'product name', 'product uid' 'price', 'qty']
        return {'category': row[0], 'name': row[1], 
            'uid': row[2], 'price': row[3], 'qty': row[4]
            }

    def product_is_in_db(self, uid):
        """Check the product is in db. 
        If yes, return the product, else return None
        """
        try:
            return Product.objects.get(uid=uid)
        except Product.DoesNotExist:
            return None

    def update_product(self, product, row_dict):
        """Update the given product with new data in row_dict"""
        product.price = row_dict['price']
        product.qty = row_dict['qty']
        product.save()

    def create_product(self, row_dict):
        # First see, if category exists
        # If not, create a new category
        try:
            category = Category.objects.get(row_dict['category'])
        except Category.DoesNotExist:
            category = Category.objects.create(name=row_dict['category'])

        # Now, create the product
        Product.objects.create(
            name=row_dict['name'],
            uid=row_dict['uid'],
            price=row_dict['price'],
            qty=row_dict['qty'],
            category=category,
        )
👤xyres

Leave a comment