Поле параметров Django с категориями - PullRequest
1 голос
/ 23 января 2012

В моем 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-профилей, это парсинг форм):

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, в которой будут столбцы name и choice_type, которые у меня уже есть. Проблема в том, что я не знаю, как я могу связать опцию с категорией и сделать так, чтобы пользователь при создании своего профиля выбирал язык программирования или платформу, основываясь на выборе в choice_type.

Я предполагаю, что это будет связано с некоторым JS, но это не такая большая проблема, как код django.

1 Ответ

6 голосов
/ 24 января 2012

Вы захотите сделать эти настоящие модели, чтобы у вас было что-то вроде этого:

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);
});
...