ManytoMany initial values

1,659 views
Skip to first unread message

Giancarlo Razzolini

unread,
Oct 25, 2010, 8:50:31 AM10/25/10
to django...@googlegroups.com
Hi all,

I've been using django for some time now and I must say that it's my
favorite framework. But lately I've run into a problem. Let's say I have
the following models:

class Contact(models.Model):
id = models.AutoField(primary_key=True)
user = models.ForeignKey(User, editable=False)
name = models.CharField(max_length=255, default='', null=True,
blank=True)
groups = models.ManyToManyField('Group', null=True, blank=True)

class Meta:
unique_together = ("user", "name")

def __unicode__(self):
return u'%s' % (self.name)

class Group(models.Model):
id = models.AutoField(primary_key=True)
user = models.ForeignKey(User, editable=False)
name = models.CharField(max_length=255, null=False, blank=False)

class Meta:
unique_together = ("user", "name")

def __unicode__(self):
return u'%s' % (self.name)

I'm using ModelForm to create the forms used to insert new instances
of both these models into my database. But, as the models made clear, I
want to have the contacts and the groups distinct to each user in
django. This part is working. Now, when I'm going to add a new contact,
for example, I want to set the initial value of the field "groups",
which is the ManytoMany field, to be only the groups belonging to that
user. I've searched the mail list and saw that I had to pass a list of
group id's to be the initial value of the field:

group_ids = []
for group in Group.objects.filter(user=request.user):
group_ids.append(group.id)

And then, create the form:

form = ContactForm(request.POST, request.FILES, initial={'groups':
group_ids})

When I do this, the form will render ok, but, instead of only
showing the groups belonging to that user, it will still show all the
groups in the model(belonging to other users too), the only difference
being that, the groups that belong to the request.user, showing already
selected, and the other groups(the ones that shouldn't be showing) not
selected. I don't know if this is possible without having to override
the queryset that the modelform make. Any ideas?

Thanks in advance,

--
Giancarlo Razzolini
http://lock.razzolini.adm.br
Linux User 172199
Red Hat Certified Engineer no:804006389722501
Verify:https://www.redhat.com/certification/rhce/current/
Moleque Sem Conteudo Numero #002
OpenBSD 4.5
Ubuntu 9.04 Jaunty Jackalope
4386 2A6F FFD4 4D5F 5842 6EA0 7ABE BBAB 9C0E 6B85

Jumpfroggy

unread,
Oct 25, 2010, 3:33:56 PM10/25/10
to Django users
Giancarlo,

I've run into this trouble myself. The problem here is the widget
itself. It does exactly what you described:
-Shows all possible values for the ManyToMany field.
-Highlights the "active" or "selected" values. These correspond to
items in that list/array/queryset.

For any more than a couple of values, it's horribly confusing. Even
though I'm used to it, I still find myself assuming that listed values
are selected (especially when you have a few hundred options). It's
just a bad widget for this kind of data.

Take a look at the Admin control panel widgets. Specifically, view a
User in the django control panel and look at the permissions widget.
That's what you want. Something where it shows all available
(unselected) options on one side, all selected options on the other
side, and a way to filter the available options for the ones you
want. Much better than the simple SELECT MULTIPLE="" that is used by
default.

I haven't looked into it, but there may be a way to use that admin
widget for your own forms. This really should be the default widget
anyway.

So bottom line - you need a different widget, maybe one you have to
write yourself. Good luck!

-James

Jumpfroggy

unread,
Oct 25, 2010, 3:36:30 PM10/25/10
to Django users, grazz...@gmail.com
On Mon, Oct 25, 2010 at 2:23 PM, Giancarlo Razzolini
<grazz...@gmail.com> wrote:
> James,
> First of all thank you for the fast response. I'll take a look into the admin forms widgets. I'm already looking for third party applications field types and widgets to see if I find one that does what I want. I was even considering creating views on the underlying database to accomplish this. I think that django should implement on the forms a better way to show granular output. My django application is completely user dependent, and only let a user to view/add/edit/remove information that belongs to him. Only the superuser can deal with all objects. I was using a custom for to accomplish that, but since I'm using a ManyToMany relation, it was a lot of work to validate it myself and save the relationship. I guess I'll have to turn back to it if I can't use the admin form you mentioned. Thank you again.
> My regards,
> Giancarlo Razzolini

No problem. For anything user-facing, I'd recommend not using admin
forms. You might be able to get away with it, but it seems each time
you add some business logic (permissions, validation, etc) it makes it
less and less a fit with the built-in forms.

It's relatively trivial to create your own forms, so it shouldn't be
too hard to ignore the admin pages. It's just annoying to have to do
the work to create templates, logins, etc.

But depending on your requirements, you'll probably find that it's
easier to just create your own forms. You'll still have to figure out
the widget issue, but at least you'll have better control over the
validation.

Larry

unread,
Dec 6, 2010, 12:14:38 PM12/6/10
to Django users
Don't know if you've solved this already, but
This works for me and I think is what you're looking for


views.py
form.fields["groups"].queryset =
Groups.objects.filter(profile=profile)

I only display the groups that are associated with the profile.
My profile is attached to the user via request.user.get_profile()
> for example, I want to set theinitialvalue of the field "groups",
> which is theManytoManyfield, to be only the groups belonging to that
> user. I've searched the mail list and saw that I had to pass a list of
> group id's to be theinitialvalue of the field:
>
>         group_ids = []
>         for group in Group.objects.filter(user=request.user):
>                 group_ids.append(group.id)
>
>     And then, create the form:
>
>     form = ContactForm(request.POST, request.FILES,initial={'groups':
> group_ids})
>
>     When I do this, the form will render ok, but, instead of only
> showing the groups belonging to that user, it will still show all the
> groups in the model(belonging to other users too), the only difference
> being that, the groups that belong to the request.user, showing already
> selected, and the other groups(the ones that shouldn't be showing) not
> selected. I don't know if this is possible without having to override
> the queryset that the modelform make. Any ideas?
>
> Thanks in advance,
>
> --
> Giancarlo Razzolinihttp://lock.razzolini.adm.br
Reply all
Reply to author
Forward
0 new messages