4

我有这个模型:

class QuestionInstance(models.Model):
    questionsSet = models.ForeignKey(QuestionsSet)
    question     = models.ForeignKey(Question)
    parent       =  models.ForeignKey('self',null=True,blank=True)
    optional     = models.BooleanField(default=False)

我想创建一个下拉列表,用户可以选择一个 QuestionInstance。它必须用 questionsSet 过滤。

我已经使用这样的模型进行了测试,但它不起作用:

(基于此How do I filter values in a Django form using ModelForm?

class FormQuestionSelect(ModelForm):
    instanceList = forms.ChoiceField(choices=[(questionInstance.id, questionInstance.question) for questionInstance in QuestionInstance.objects.all()])

    class Meta:
        model = QuestionInstance
        fields = ('instanceList', )
        widgets = {
            'instanceList': Select(attrs={'class': 'select'}),
        }

    def __init__(self, questionsSet=None, **kwargs):
        super(FormQuestionSelect, self).__init__(**kwargs)
        if questionsSet:
            #Tested many code here to filter, None of them worked :(
            #Is that possible to create instanceList there ?                        

我不确定使用模型表单是否适合这种目的。

在创建或更新模型实例时,模型表单非常有用。在使用特定表单时,例如在这种情况下,我在模板中使用自定义表单:

看法

questionInstanceList = QuestionInstance.objects.filter(questionsSet=questionsSet)

模板

<select name="questionInstanceSelect">
    {% for instance in questionInstanceList %}
        <option value="{{ instance.id }}">{{ instance.question.text }}</option>
    {% endfor %}
</select>

并以这种方式处理它们:

instanceList = request.POST.get('questionInstanceSelect')

我很确定有一个正确的方法。

4

2 回答 2

1

__init__您可以在表单实例化后在表单或视图中更改 ModelChoiceField的查询集。但这不会解决客户端的问题。当有人更改QuestionSet Question选择框将保持不变

要更新查询集,只需更新表单字段的一个

form.fields['parent'].queryset = (QuestionInstance.objects
                                           .filter(questionsSet=questionsSet))

或者如果你改变形式__init__

self.fields['parent'].queryset = (QuestionInstance.objects
                                           .filter(questionsSet=questionsSet))

但是应该记住,如果questionsSet在客户端父列表上发生更改将保持不变。

你会考虑添加客户端代码更新父母的选择列表

让我解释一下。

你有模特

class QuestionInstance(models.Model):
    questionsSet = models.ForeignKey(QuestionsSet)
    question     = models.ForeignKey(Question)
    parent       =  models.ForeignKey('self',null=True,blank=True)
    optional     = models.BooleanField(default=False)

这里父字段链接到self(相同的模型)。

让我们为此模型使用“模型”形式

class FormQuestionSelect(ModelForm):
    class Meta:
        model = QuestionInstance

ModelForm将为每个具有相同名称的模型字段创建字段,然后在创建后我们更新ModelChoiceField(创建为ForeignKeyqueryset

于 2013-10-25T10:10:32.843 回答
0

如果您希望您的字段是动态的,则需要使用 jQuery 和 ajax 来实现此功能。我已经给出了在 django admin 中使用的代码。如果您想在自定义页面中使用它,您可以稍微调整一下。但两者的概念仍然相同。

question_set_change.js

(function($){   
    $(function(){
        $(document).ready(function() {
            $('#id_questionsSet').bind('change', question_set_change);            
            $('#id_question > option').show();
            if ($('#id_questionsSet').val() != '') {
                var question_set_id = $('#id_questionsSet').val();
                $.ajax({
                "type"      : "GET",
              "url"         : "/product_change/?question_set_id="+question_set_id,
                "dataType"  : "json",
              "cache"       : false,
                "success"   : function(json) {
                    $('#id_question >option').remove();
                    for(var j = 0; j < json.length; j++){
                        $('#id_question').append($('<option></option>').val(json[j][0]).html(json[j][1]));
                    }
                }           
            });
            }
        });
    });  
})(django.jQuery);

// based on the questionsSet, questions will be loaded

var $ = django.jQuery.noConflict();

function question_set_change()
{
    var question_set_id = $('#id_questionsSet').val();
    $.ajax({
    "type"      : "GET",
  "url"         : "/product_change/?question_set_id="+question_set_id,
    "dataType"  : "json",
  "cache"       : false,
    "success"   : function(json) {
        $('#id_question > option').remove();
        for(var j = 0; j < json.length; j++){
            $('#id_question').append($('<option></option>').val(json[j][0]).html(json[j][1]));
        }
    }           
})(jQuery);
}

在 views.py 中包含以下内容:

import simplejson
from django.shortcuts import HttpResponse

from app.models import Question

def question_choices(request): 
    question_list = []
    question_set_id = request.GET.get('question_set_id')
    questions       = Question.objects.filter(question_set = question_set_id)    
    [question_list.append((each_question.pk,each_question.name)) for each_question in questions]
    json = simplejson.dumps(question_list)
    return HttpResponse(json, mimetype='application/javascript')

在 urls.py 中:

from app.views import question_choices

urlpatterns = patterns(
    (r'^question_set_change/', question_choices),
)

在 admin.py 中,您要根据 question_set 加载问题:

class Media:
    js = ['/path/to/question_set_change.js',]
于 2013-10-25T11:54:27.977 回答