Filter ManyToMany field's choices in a Django ModelForm
In my current project, I'm required to build a form in which a certain user group can only create with a certain kind of data. For example:
Here is what the model looks like:
models.py:
from django.db import models
class Student(models.Model):
student_number = models.CharField(max_length = 6, primary_key = True)
student_name = models.CharField(max_length = 20)
def __unicode__(self):
return self.student_name
class Meta:
ordering = ['student_number']
class Teacher(models.Model):
name = models.CharField(max_length=50)
students = models.ManyToManyField(Student)
def __unicode__(self):
return u'%s' % (self.name)
class Meta:
ordering = ['name']
verbose_name = "Teachers"
To be able to generate a form and filter by student_number, I just need to define my __init__ function for the TeacherForm:
forms.py:
from django.forms import ModelForm
from myapps.models import Teacher, Student
class TeacherForm(ModelForm):
def __init__(self, student_set, *args,**kwargs):
super (TeacherForm,self ).__init__(*args,**kwargs)
self.fields['students'].queryset = Student.objects.filter(student_number__in=student_set)
class Meta:
model = Teacher
fields = ['name', 'students']
exclude = []
So, in the view, I first check the user's group to decide which set of students that user can create from, then pass it to the form instance:
views.py:
from django.contrib.auth.models import User, Group
from django.shortcuts import render_to_response, redirect
from django.template import RequestContext
from myapps.models import Teacher, Student
from myapps.forms import TeacherForm
SETA = ['123', '234']
SETB = ['345', '678']
def get_student_set(user):
student_set = []
if Group.objects.get(name='A') in user.groups.all():
student_set += SETA
elif Group.objects.get(name='B') in user.groups.all():
student_set += SETB
return student_set
def add_teacher_view(request):
user = request.user
student_set = get_student_set(user)
teacher = Teacher()
if request.method == 'POST':
teacher_form = TeacherForm(request.POST, request.FILES)
if teacher_form.is_valid():
teacher = teacher_form.save()
return redirect('myapps.views.add_teacher_view')
else:
teacher_form = TeacherForm(instance=teacher, student_set=student_set)
return render_to_response('teacher.html', locals(), context_instance=RequestContext(request))
References:
[0] http://stackoverflow.com/questions/291945/how-do-i-filter-foreignkey-choices-in-a-django-modelform/291968#291968
[1] https://docs.djangoproject.com/en/1.7/topics/db/queries/
- User 1 of group A can only create Teacher objects with a set of students (student_numbers, let say ['123', '234'])
- User 2 of group B can only create Teacher objects with a set of students (student_numbers, ['345', '678'])
Here is what the model looks like:
models.py:
from django.db import models
class Student(models.Model):
student_number = models.CharField(max_length = 6, primary_key = True)
student_name = models.CharField(max_length = 20)
def __unicode__(self):
return self.student_name
class Meta:
ordering = ['student_number']
class Teacher(models.Model):
name = models.CharField(max_length=50)
students = models.ManyToManyField(Student)
def __unicode__(self):
return u'%s' % (self.name)
class Meta:
ordering = ['name']
verbose_name = "Teachers"
To be able to generate a form and filter by student_number, I just need to define my __init__ function for the TeacherForm:
forms.py:
from django.forms import ModelForm
from myapps.models import Teacher, Student
class TeacherForm(ModelForm):
def __init__(self, student_set, *args,**kwargs):
super (TeacherForm,self ).__init__(*args,**kwargs)
self.fields['students'].queryset = Student.objects.filter(student_number__in=student_set)
class Meta:
model = Teacher
fields = ['name', 'students']
exclude = []
So, in the view, I first check the user's group to decide which set of students that user can create from, then pass it to the form instance:
views.py:
from django.contrib.auth.models import User, Group
from django.shortcuts import render_to_response, redirect
from django.template import RequestContext
from myapps.models import Teacher, Student
from myapps.forms import TeacherForm
SETA = ['123', '234']
SETB = ['345', '678']
def get_student_set(user):
student_set = []
if Group.objects.get(name='A') in user.groups.all():
student_set += SETA
elif Group.objects.get(name='B') in user.groups.all():
student_set += SETB
return student_set
def add_teacher_view(request):
user = request.user
student_set = get_student_set(user)
teacher = Teacher()
if request.method == 'POST':
teacher_form = TeacherForm(request.POST, request.FILES)
if teacher_form.is_valid():
teacher = teacher_form.save()
return redirect('myapps.views.add_teacher_view')
else:
teacher_form = TeacherForm(instance=teacher, student_set=student_set)
return render_to_response('teacher.html', locals(), context_instance=RequestContext(request))
References:
[0] http://stackoverflow.com/questions/291945/how-do-i-filter-foreignkey-choices-in-a-django-modelform/291968#291968
[1] https://docs.djangoproject.com/en/1.7/topics/db/queries/
Comments
Post a Comment