How to convert string to key value in python

Question:

I have a Django Application and want to convert a value from a string field which is comma separated to a key vaule pair and add it to a json data block.

class MyClass1(models.Model):
keywords = models.TextField(_('Keywords'), null=True, blank=True)

Example of list:

blue,shirt,s,summer,for women

The JSON data in my code

data = {
       "name": self.name,
       "type": self.type,
       ...
       "keywords": []
       }

I want to split the comma separated string of self.keywords and append it to the keywords field in my json, but as a array like this:

{
"name": keyword,
},

I do the split with the split function, but dont know how to create a key value pair as array and append to keywords.

Expected output:

data = {
       "name": "Name of item",
       "type": "Type of item",
       ...
       "keywords": [
        {
         "name": "blue"
        },
        {
         "name": "shirt"
        },
        ...
       ]
       }
Asked By: sokolata

||

Answers:

You can work with .split():

data = {
    'name': self.name,
    'type': self.type,
    # …
    'keywords': [{'name': n} for n in self.keywords.split(',')],
}

It might however be better to work with a custom field. You can define such field with:

from django.db import models


class ListAsCharField(models.Field):
    def __init__(self, separator=',', *args, **kwargs):
        self.separator = separator
        super().__init__(*args, **kwargs)

    def get_db_prep_value(self, value, connection, prepared=False):
        if isinstance(value, (str, type(None))):
            value = self.separator.join(str(x) for x in value)
        return super().get_db_prep_value(value, connection, prepared)

    def from_db_value(self, value, expression, connection):
        if isinstance(value, str):
            return value.split(self.separator)

    def to_python(self, value):
        if isinstance(value, str):
            value = value.split(self.separator)
        return value

then you can use this in the model to automatically do the wrapping/unwrapping from a list:

class MyClass1(models.Model):
    keywords = ListAsCharField(
        max_length=256, verbose_name=_('Keywords'), null=True, blank=True
    )

Then you can process this with:

data = {
    'name': self.name,
    'type': self.type,
    # …
    'keywords': [{'name': n} for n in self.keywords],
}
Answered By: Willem Van Onsem