views:

229

answers:

2

Hi I am writting a custom widget which I want to return a list as the value. From what I can find to set the value that is returned you create a custom value_from_datadict function. I have done this

def value_from_datadict(self, data, files, name):
    value = data.get(name, None)
    if value:
        # split the sting up so that we have a list of nodes
        tag_list = value.strip(',').split(',')
        retVal = []
        # loop through nodes
        for node in tag_list:
            # node string should be in the form: node_id-uuid
            strVal = str(node).split("-")

            uuid = strVal[-1]
            node_id = strVal[0]

            # create a tuple of node_id and uuid for node
            retVal.append({'id': node_id, 'uuid': uuid})

        if retVal:
            # if retVal is not empty. i.e. we have a list of nodes
            # return this. if it is empty then just return whatever is in data
            return retVal

    return value

I expect this to return a list but when I print out the value it is returned as a string rather than a list. The string itself contains the right text but as i said it is a string and not a list. An example of what is returned could be

[{'id': '1625', 'uuid': None}]

but if I did str[0] it would print out [ instead of {'id': '1625', 'uuid': None}

How can I stop it from converting my list into a string?

Thanks

+1  A: 

Well, it's simple: if you have a CharField, then you will get a string as a result, because CharField uses method to_python, that coerces the result to string. You need to create your own Field for this one and return a list.

OLD

Could you post the result of:

x = value_from_datadict(..)
print type(x)

so we can see, what exactly is returned?

And could you post the whole test case you are using to deliver the example?

gruszczy
see above for code
John
Thanks for the reply. Is there any examples or somewhere you can point me that will show me this as I'm not sure how to do this? Is there not a field set up for a list such as multiplechoicefield which I could use?
John
Here you go: http://stackoverflow.com/questions/1526806/tutorial-about-how-to-write-custom-form-fields-in-django
gruszczy
thanks worked perfectly. All I did was move the code from the value_from_datadict function into the clean function of my new field and it did exactly what I wanted.
John
A: 

widget.py

class AutoTagWidget(widgets.TextInput):
  def render(self, name, value, attrs=None):
    final_attrs = self.build_attrs(attrs, name=name)

    if not self.attrs.has_key('id'):
        final_attrs['id'] = 'id_%s' % name

    jquery = u"""
    <script type="text/javascript">
    $("#%s").tokenInput('%s', {
        hintText: "Enter the topic you wish to tag this resource to",
        noResultsText: "No results",
        prePopulate: %s,
        searchingText: "Searching..."
    });

    $("body").focus();
    </script>
    """ % (final_attrs['id'], reverse('ajax_autocomplete'), value)

    output = super(AutoTagWidget, self).render(name, "", attrs)

    return output + mark_safe(jquery)

  def value_from_datadict(self, data, files, name):
    #return data.get(name, None)
    value = data.get(name, None)
    if value:
        # split the sting up so that we have a list of nodes
        tag_list = value.strip(',').split(',')
        retVal = []
        # loop through nodes
        for node in tag_list:
            # node string should be in the form: node_id-uuid
            strVal = str(node).split("-")

            uuid = strVal[-1]
            node_id = strVal[0]

            # create a tuple of node_id and uuid for node
            retVal.append({'id': node_id, 'uuid': uuid})

        if retVal:
            # if retVal is not empty. i.e. we have a list of nodes
            # return this. if it is empty then just return whatever is in data
            return retVal

    return value

forms.py

class TagResourceForm(forms.Form):
     Tag_Resource_To = forms.CharField(max_length=255, widget=AutoTagWidget,required=False)

view.py

def tag_resource(request, slug):
  if request.method == 'POST':
    form = TagResourceForm(data=request.POST)
    if form.is_valid():
        tag_list = form.cleaned_data['Tag_Resource_To']
  else:
    form = TagResourceForm()

when posting the form tag_list = [{'id': '1625', 'uuid': None}]

but it is a string not a list.

if I do eval(tag_list) then I get it as a list but I'd rather it was just a list and not a string when it is returned

John