This question may also be formulated as: "How to change attributes of a CreateView generated form?"
I am using "CreateView" to generate a view and related form in Django 1.10. The idea is that a regular user (a teacher) can create an instance of the model only as himself/herself but a privileged user can create an instance and assign to any teacher. I would like to use the same view/form for both.
The model:
class Set(models.Model):
name = models.CharField(
max_length=40,
)
matter = models.ForeignKey(
Matter,
on_delete=models.SET_NULL,
null=True,
)
group = models.ForeignKey(
Group,
on_delete=models.SET_NULL,
null=True,
)
teacher = models.ForeignKey(
Teacher,
on_delete=models.PROTECT,
)
Technically, it would consist on populating the form with the current "teacher" logged in and disable the field unless the current user is privileged. I currently do the initial value setting with the following code, but I do not know how to prevent regular users from modifying the "teacher" field.
class SetCreate(LoginRequiredMixin, CreateView):
model = Set
fields = ('name', 'matter', 'group', 'teacher')
def get_initial(self):
return {'teacher': self.request.user.teacher.id}
# code to limit 'teacher' field editing
Another option I tried is to create the instance with the right 'teacher', like:
class SetCreate(LoginRequiredMixin, CreateView):
model = Set
fields = ('name', 'matter', 'group')
def form_valid(self, form):
form.instance.teacher = self.request.user.teacher
return super(SetCreate, self).form_valid(form)
It works nice but I cannot use it to edit the 'teacher' field by a privileged user.
I know there exists the 'Field.disable' attribute to form fields, but I do not know how to change the attributes of 'CreateView' generated forms, if possible.
Another option would be to limit the options in the drop-down list in the form, but I do not know how to do it either.
Any advice including a different point of view is welcome.
Looking at the code, the editing views generate a form within
get_form_class
based on the value of thefields
attribute. That is defined as a class attribute, but the code actually references it viaself.fields
so there is no reason you couldn't override it at instance level. So, you could do this:(The seemingly pointless else block is to ensure we always set an instance variable.)