Django 分类选项字段

1 投票
1 回答
5433 浏览
提问于 2025-04-17 10:52

我在我的models.py文件中有以下代码(去掉了一些不相关的字段):

class Choices(models.Model):
    name = models.CharField(max_length=300)
    choice_type = models.CharField(max_length=200)

    def __unicode__(self):
        return self.name

class UserProfile(models.Model):
    user = models.ForeignKey(User, unique=True)
    planguages = models.ManyToManyField(Choices)

还有我的utils.py文件(最初来自django-profiles,用于解析表单):

def get_profile_form():
    profile_mod = get_profile_model()
    class _ProfileForm(forms.ModelForm):
        planguages = forms.ModelMultipleChoiceField(queryset=Choices.objects.all(), required=False, widget=forms.CheckboxSelectMultiple)

        class Meta:
            model = profile_mod
            exclude = ('user',) # User will be filled in by the view.
    return _ProfileForm

现在,我想做的是创建一个名为Choices的表,这个表里会有namechoice_type这两列,这些我已经准备好了。问题是,我不太清楚怎么把一个选项和一个类别关联起来,让用户在创建他们的个人资料时,能够根据choice_type的选择来挑选编程语言或框架。

我想这可能需要用到一些JavaScript,但这并不是像django代码那样复杂的问题。

1 个回答

14

你需要把这些变成实际的模型,这样你就会有像下面这样的东西:

class ProgrammingCategory(models.Model):
    name = models.CharField(max_length=200)

class ProgrammingLanguage(models.Model):
    category = models.ForeignKey(ProgrammingCategory, related_name='languages')
    name = models.CharField(max_length=300)

class UserProfile(models.Model):
    user = models.ForeignKey(User, unique=True)
    planguages = models.ManyToManyField(ProgrammingLanguage)

这样做不仅在维护方面更好(因为编程语言是会变化的:新的语言会出现,旧的语言会消失),而且在查询时也给你更大的灵活性。

接着,你只需要在你的 ModelForm 中添加一个字段,用来表示类别:

class UserProfileForm(forms.ModelForm):
    ...
    category = forms.ModelChoiceField(queryset=ProgrammingCategory.objects.all(), required=False)

然后,在你的表单中,你会看到一个下拉框,里面有完整的类别列表,还有一个下拉框,里面有完整的语言列表。接下来,你只需要一些 AJAX 来帮你进行过滤:

views.py

from django.core import serializers
from django.http import HttpResponse, HttpResponseBadRequest

def ajax_get_languages_for_category(request):
    cat_id = request.GET.get('cat_id')
    if cat_id is not None:
        category = get_object_or_404(ProgrammingCategory, id=cat_id)
        data = serializers.serialize('json', category.languages.all())
        return HttpResponse(data, mimetype='application/json')
    else:
        return HttpResponseBadRequest()

script.js

$(document).ready(function(){
    var $category = $('#id_category');
    function updateLanguageChoices() {
        var selected = $category.val();
        if (selected) {
            $.getJSON('/path/to/ajax/view/', { cat_id: selected }, function (data, jqXHR) {
                var output = [];
                $.each(data, function(i, item){
                    output.append('<option value="'+item.id+'">'+item.name+'</option>');
                });
                $('#id_planguage').html(output.join(''));
            });
        }
    }
    updateLanguageChoices();
    $category.change(updateLanguageChoices);
});

撰写回答