如何将ManyToManyField渲染为复选框?

38 投票
3 回答
27723 浏览
提问于 2025-04-15 16:09

我正在制作一个游戏链接网站,用户可以在这里发布他们喜欢的网页游戏链接。 当人们发布游戏时,他们需要检查这个游戏属于哪个类别。 我决定允许每个游戏有多个类别,因为有些游戏可以归入多个类别。 所以我想问的是,如何在我的视图中处理这个问题? 我该如何将这些类别显示为复选框,并且至少要有一个被选中? 另外,如何在管理员界面中也显示这些复选框呢?

这是代码

模型:

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) 

视图:

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),)

表单:

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')

谢谢!

3 个回答

4

这是我在Dropbox的工程经理Chase Seibert那里找到的内容。

来源于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()
46

这是我解决问题的方法(编辑:还有管理员的部分)

表单:

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

(我找不到的部分是查询集的部分..)

视图:

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

这就是保存数据所需的全部代码。

编辑:这里是管理员的解决方案

模型:

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

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

管理员:

from gamesite.games.models import Game, MyModelAdmin

admin.site.register(Game, MyModelAdmin)

看起来有点奇怪,但能正常工作!如果有人找到更“干净”的方法,请分享一下!

谢谢!

51
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')

这样应该能解决你的视图问题,不过我不太确定管理员那边的情况。还在继续查找中... 如果我找到什么,会再更新的。

撰写回答