BigMonkey89WithaLeg
BigMonkey89WithaLeg

Reputation: 315

Getting certain values to appear in django form

Image displaying issue

The image attached displays my current problem. Math 270 and Math 280 in the picture were created by another user and not Jay, who created Jays course. However the other user is logged in currently, and not Jay. How can I get only the courses created by the logged in user, not Jay, to appear in that drop down menu?

In my views I have the following with attempts to solve the problem:

class CreateQuestion(LoginRequiredMixin, CreateView):
    model = Question
    fields = ["title", "question", 'classe']
    template_name = "attendance_test/add_test.html"

    def form_valid(self, form):
        form.instance.instructor = self.request.user
        return super(CreateQuestion, self).form_valid(form)

    def get_context_data(self, **kwargs):
        context = super(CreateQuestion, self).get_context_data(**kwargs)
        context['classe'] = Classe.objects.filter(professor=self.request.user.id)
        return context

    def get_initial(self):
        return { 'classe': Classe.objects.filter(professor=self.request.user.id) }

My Question model:

class Question(models.Model):
    title = models.CharField(max_length=100)
    question = models.TextField(max_length=500)
    date_pub = models.DateTimeField(auto_now_add=True)
    instructor = models.ForeignKey(Teacher, on_delete=models.CASCADE, default="")
    # this is where all the courses are showing up, I only want those
    # created by the "instructor" to show up, not all instructors
    classe = models.ForeignKey(Classe, on_delete=models.CASCADE, null=True)

    def professor_classes(self):
        return Classe.objects.filter(professor=self.professor)

Teacher Model:

class Teacher(User):  
    isProfessor = models.BooleanField(default=False)
    professor_courses = models.ForeignKey('Classe', on_delete=models.CASCADE, null=True)

This issue would be a problem if there were say as much as 1000 classes, but an instructor only thought 4, it would not make sense to display all 1000 when 996 had nothing to do with them. For the record I asked this question before, I got an answer but I was still not able to solve it.

Upvotes: 1

Views: 49

Answers (2)

Eugene Morozov
Eugene Morozov

Reputation: 15836

There're many ways to solve this problem depending on how you structure your Django application. For example, one way could be:

class QuestionForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        professor = kwargs.pop('professor')
        super(QuestionForm, self).__init__(*args, **kwargs)
        self.fields['classe'].queryset = Classe.objects.filter(professor=professor)

    class Meta:
         model = Question
         fields = ('title', 'question', 'classe')

class CreateQuestionView(LoginRequiredMixin, CreateView):
    form = QuestionForm
    template_name = "attendance_test/add_test.html"

    def get_form_kwargs(self):
        kwargs = super(CreateQuestionView, self).get_form_kwargs()
        kwargs['professor'] = self.request.user
        return kwargs

    def form_valid(self, form):
        form.instance.instructor = self.request.user
        return super(CreateQuestionView, self).form_valid(form)

This filters classes based on the currently logged in user.

Although I think it is incorrect to inherit Teacher model from User. More performant and traditional solution would be to use aggregation in this case:

class Teacher(models.Model):
    user = models.ForeignKey(User)
    # or
    #user = models.OneToOneField(User)

Also, you have problem with your code: initial is an initial selected value for the form field, it's not a range of allowed values. By setting initial you set an initial selected value for the form field.

context is a dict of variables that are passed into your template. So I believe you don't need to define get_context in your view (or at least it doesn't need to pass list of Classes).

Upvotes: 1

Exprator
Exprator

Reputation: 27523

def get_form(self, form_class):
        form = super(CreateQuestion, self).get_form(form_class)
        form.fields['classe']= Classe.objects.filter(professor=self.request.user.id)
        return form

you could try something like this

Upvotes: 1

Related Questions