Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <h1>Prefered Solution</h1> <p>Firstly, I think you should reconsider using a M:M relationship to represent a 1:M relationship. There is going to be a strong likelihood that there are certain situations where a user gets multiple groups, and that may result in bugs in you code at a later stage, that are tricky to trace. </p> <p>As you are already using a UserProfile class, I would put a Foreign key on the user profile model, and that will provide an accurate representation of the data structure that should exist (even if it means logging in and out when testing).</p> <h2>Update</h2> <p>You could do this by changing the model as so:</p> <pre><code>class UserProfile(models.Model): # existing fields here single_group = models.ForeignKey(Group) </code></pre> <p>If you have lots of existing code that uses the existing user groups relationship, this is a less practical solution. However if you really need to force this restriction (one group per user/userprofile), then this would do so.</p> <h1>Solution to your specific problem</h1> <p>If for what ever reason, you don't feel my comments above are appropriate (I don't know the specific situation in which your code exists)...</p> <p>I think the problem that you are experiencing is due to the fact that the select widget returns a single item to the form, whereas a SelectMultiple will return a list of values. As the form expects a list, this is where your problem is. </p> <p>I would suggest subclassing the SelectMultiple widget, so that it actually renders as a select single on the form, but still uses the existing logic to return a list. </p> <p>This is the current render function in the SelectMultiple Widget:</p> <pre><code>class SelectMultiple(Select): def render(self, name, value, attrs=None, choices=()): if value is None: value = [] final_attrs = self.build_attrs(attrs, name=name) output = [u'&lt;select multiple="multiple"%s&gt;' % flatatt(final_attrs)] options = self.render_options(choices, value) if options: output.append(options) output.append('&lt;/select&gt;') return mark_safe(u'\n'.join(output)) </code></pre> <p>if you subclassed and overrode the render method as follows:</p> <pre><code>class CustomSelectSingleAsList(SelectMultiple): def render(self, name, value, attrs=None, choices=()): if value is None: value = [] final_attrs = self.build_attrs(attrs, name=name) output = [u'&lt;select %s&gt;' % flatatt(final_attrs)] # NOTE removed the multiple attribute options = self.render_options(choices, value) if options: output.append(options) output.append('&lt;/select&gt;') return mark_safe(u'\n'.join(output)) </code></pre> <p>This will render a select single, but retrieve a list of items.</p> <p>Then in your form meta, just use your new custom class:</p> <p>widgets = { 'groups': myforms.CustomSelectSingleAsList, 'password': forms.PasswordInput, # 'text': Textarea(attrs = {'rows': 3, 'class': 'span10', 'placeholder': 'Post Content'}), }</p> <h1>Alternative</h1> <p>Alternatively you could override the Select widget to return a list:</p> <pre><code>class SelectSingleAsList(Select): def value_from_datadict(self, data, files, name): if isinstance(data, (MultiValueDict, MergeDict)): return data.getlist(name) # NOTE this returns a list rather than a single value. return data.get(name, None) </code></pre> <p>Let me know if either of these solve your problem.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload