Search code examples
djangodjango-modelsbulk-create

Django bulk_create using a list of random fields without a hardcoded query


I am trying to create new instances in my Django model using bulk_create().

My models are:

Class Emotion(models.Model):
    emotion_grp_id = models.AutoField(primary_key=True, ...
    emotion_group = models.CharField(max_length=55, ...

Class EmotionSubGroup(models.Model):
    emotion_sub_grp_id = models.AutoField(primary_key=True, ...
    emotion_grp = models.ForeignKey(EmotionGroup, on_delete=models.CASCADE, ...
    emotion_sub_group = models.CharField(max_length=55, ...

views.py

The relevant portion of the function that I am using looks like this:

def DataUpload (request):
   # ...
   # ...

    df_rawdata = pd.read_csv(csv_file, sep='').   # Dataframe from source (.csv) file

    row_iter = df_rawdata.iterrows()
    data = [
        EmotionSubGroup(
            emotion_grp_id=row['emotion_grp'],
            emotion_sub_group=row['emotion_sub_group'],
            )
        for index, row in row_iter
        ]         

    EmotionSubGroup.objects.bulk_create(data)

Is it possible to create a general data structure instead of hardcoding the field names, for example:

data = `list_of_target_fields = rows_from_external_source`

to be equivalent of what I am using currently and carry out the upload.


Solution

  • Here is a simple function which will update ForeignKey and will return a instance of model

    def set_instance(data, model, foreignkeys=None):
        if foreignkeys:
           # update foreignkey in data dict
           for k, v in foreignkeys.items():
              data[v] = data.pop(k)
        return model(**data)
      
    
    def DataUpload (request):
        # ...
        # ...
    
        df_rawdata = pd.read_csv(csv_file, sep='').   # Dataframe from source (.csv) file
    
        row_iter = df_rawdata.iterrows()
        foreignkey_fields = {'emotion_grp':'emotion_grp_id'}
        data = [
            set_instance(row, EmotionSubGroup, foreignkey_fields)
            for index, row in row_iter
            ]         
    
        EmotionSubGroup.objects.bulk_create(data)
    

    Other approch to make code readable

    def update_foreignkey(data, foreignkeys=None):
        if foreignkeys:
           # update foreignkey in data dict
           for k, v in foreignkeys.items():
             data[v] = data.pop(k)
        return data
      
    
    def DataUpload (request):
        # ...
        # ...
    
        df_rawdata = pd.read_csv(csv_file, sep='').   # Dataframe from source (.csv) file
    
        row_iter = df_rawdata.iterrows()
        foreignkey_fields = {'emotion_grp':'emotion_grp_id'}
        data = [
            EmotionSubGroup(**update_foreignkey(row, foreignkey_fields))
            for index, row in row_iter
            ]         
    
        EmotionSubGroup.objects.bulk_create(data)