Reputation: 1292
I am having troubles to carry over previously selected items in a ModelForm in the admin. I want to use the forms.CheckboxSelectMultiple widget since that is the most straightforward UI in this usecase. It works as far that when saving, the values are stored. But when editing the previously saved item, the values previously saved in this field are not reflected in the widget.
UI Example:
After posting (editing that item, returns it blank):
However, when not using the widget but a regular CharField when editing the item it looks like:
So for some reason the values are not represented by the checkbox widget?
Here's my simplified setup, models.py
POST_TYPES = (
('blog', 'Blog'),
('portfolio', 'Portfolio'),
('beeldbank', 'Beeldbank'),
)
class Module(models.Model):
title = models.CharField(max_length=100, verbose_name='title')
entriesFrom = models.CharField(max_length=100)
def __unicode__(self):
return self.title
forms.py:
class ModuleForm(forms.ModelForm):
entriesFrom = forms.MultipleChoiceField(
choices=POST_TYPES,
widget=CheckboxSelectMultiple,
label="Pull content from",
required=False,
show_hidden_initial=True)
class Meta:
model = Module
def __init__(self, *args, **kwargs):
super(ModuleForm, self).__init__(*args, **kwargs)
if kwargs.has_key('instance'):
instance = kwargs['instance']
self.fields['entriesFrom'].initial = instance.entriesFrom
logging.debug(instance.entriesFrom)
admin.py
class ModuleAdmin(admin.ModelAdmin):
form = ModuleForm
So when editing a previously saved item with say 'blog' selected, debugging on init returns me the correct values on self.fields['entriesFrom'] ([u'blog',]), but its not reflected in the checkboxes (nothing is shown as selected) in the admin.
edit
updated the ModuleForm class to pass on initial values, but nothing still gets pre-populated whilst there are a few values in the initial value ("[u'blog']").
Upvotes: 3
Views: 2577
Reputation: 131
I faced this issue, my changes haven't affected on save. I use CharField in model, but in forms.py;
class ModuleForm(forms.ModelForm):
my_field = forms.MultipleChoiceField(
choices=POST_TYPES,
widget=CheckboxSelectMultiple,
required=False,)
def __init__(self, *args, **kwargs):
super(ModuleForm, self).__init__(*args, **kwargs)
if kwargs.get('instance'):
self.initial['my_field'] = eval(self.initial['my_field'])
This form solution worked for me on MultipleChoiceField on Django Admin.
Upvotes: 0
Reputation: 19
you can use this function to remove string mark
from ast import literal_eval
literal_eval(value)
Upvotes: 0
Reputation: 368
Might not be correct, but for my usecase, I did not want to replace the values with integers (as per the accepted answer). This was arrived at by a smidge of trial-and-error, and a lot of stepping through Django internals. Works for me, but YMMV:
from django.forms.widgets import (
CheckboxSelectMultiple as OriginalCheckboxSelectMultiple,
)
class CheckboxSelectMultiple(OriginalCheckboxSelectMultiple):
def optgroups(self, name, value, attrs=None):
# values come back as e.g. `['foo,bar']`, which we don't want when inferring "selected"
return super().optgroups(name, value[0].split(","), attrs)
Upvotes: 2
Reputation: 1292
Solution:
Setting the choices by a integer, instead of a string.
POST_TYPES = (
(1, 'Blog'),
(2, 'Portfolio'),
(3, 'Beeldbank'),
)
Damn, that wasn't worth breaking my skull over.
Upvotes: 3
Reputation: 4286
Maybe I'm not understanding your question completely, but it seems like you could simplify a little. Using ModelForms, I don't think any of your overriding the _init_ in your form is necessary. Try this and see if you get your desired behavior.
models.py
class Module(models.Model): POST_TYPES = ( ('blog', 'Blog'), ('portfolio', 'Portfolio'), ) title = models.CharField(max_length=100, verbose_name='title') entriesFrom = models.CharField(max_length=100, verbose_name='Pull content from', choices=POST_TYPES, blank=True) def __unicode__(self): return self.title
forms.py
class ModuleForm(forms.ModelForm): class Meta: model = Module
admin.py
from django.contrib import admin admin.site.register(models.Module)
If my answer isn't what you're looking for, try clarifying your question and I'll see if I can help you out.
Upvotes: 0