简体   繁体   中英

How can I render a ManyToManyField as checkboxes?

I'm making a game link site, where users can post links to their favorite web game. When people post games they are supposed to check what category the game falls into. I decided to allow many categories for each game since some games can fall into many categories. So the question is, how do I handle this in my view? And how can I show it as Checkboxes, where at least one has to be checked? And how can I show this as checkboxes in the Admin as well?

Here is the code

Models:

class Category(models.Model): 
        category = models.CharField(max_length=200) 
        def __unicode__(self): 
                return self.category 
class Game(models.Model): 
    name = models.CharField(max_length=200) 
    url = models.CharField(max_length=200) 
    poster = models.ForeignKey(User, related_name='game_poster_set') 
    postdate = models.DateTimeField(default=datetime.now) 
    cats = models.ManyToManyField(Category) 
    hits = models.IntegerField(default=0) 
    post = models.BooleanField(default=False) 

Views:

def submit(request): 
        form = GameForm(request.POST or None) 
        if form.is_valid(): 
                game = form.save(commit=False) 
                game.poster = request.user 
                game.save() 
                next = reverse('gamesite.games.views.favorites') 
                return HttpResponseRedirect(next) 
        return render_to_response( 
        'games/submit.html', 
        {'form': form}, 
        context_instance = RequestContext(request),)

Forms:

class GameForm(forms.ModelForm): 
        name = forms.CharField(max_length=15, label='Name') 
        url = forms.URLField(label='URL', initial='http://') 
        class Meta: 
                model = Game 
                fields = ('name','url')

Thanks!

class GameForm(forms.ModelForm): 
        name = forms.CharField(max_length=15, label='Name') 
        url = forms.URLField(label='URL', initial='http://') 
        cats = forms.ModelMultipleChoiceField(
            queryset=Category.objects.all(),
            widget=forms.CheckboxSelectMultiple,
            required=True)

        class Meta: 
                model = Game 
                fields = ('name','url','cats')

that should fix your view, but i'm not sure about the admin. still looking... will edit if i find anything.

Here is how I solved it (Edit: and the admin thing)

Forms:

cats = forms.ModelMultipleChoiceField(widget=forms.CheckboxSelectMultiple, queryset=Category.objects.all())

(It was the queryset part I couldn't find..)

View:

cats = form.cleaned_data['cats']
    game.cats = cats

And that's all the code needed to save the data.

Edit: here is a solution for the admin

Models:

from django.contrib import admin
from django.forms import CheckboxSelectMultiple

class MyModelAdmin(admin.ModelAdmin):
    formfield_overrides = {
        models.ManyToManyField: {'widget': CheckboxSelectMultiple},
    }

Admin:

from gamesite.games.models import Game, MyModelAdmin

admin.site.register(Game, MyModelAdmin)

It's kind of quirky in looks, but works! If someone finds a way to make it more "clean" please post!

Cheers!

Found this on from Chase Seibert, Engineering Manager of Dropbox

Source from Chase Seibert

from django.db import models
from django.forms.models import ModelForm
from django.forms.widgets import CheckboxSelectMultiple

class Company(models.Model):  
    industries = models.ManyToManyField(Industry, blank=True, null=True)

class CompanyForm(ModelForm):

    class Meta:
        model = Company
        fields = ("industries")

    def __init__(self, *args, **kwargs):

        super(CompanyForm, self).__init__(*args, **kwargs)

        self.fields["industries"].widget = CheckboxSelectMultiple()
        self.fields["industries"].queryset = Industry.objects.all()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM