Say there's a model:
class Notification(models.Model):
user = models.ForeignKey(User)
board = models.ForeignKey(Board)
post = models.ForeignKey(Post)
name = models.CharField()
class Meta:
unique_together = ('user', 'name', 'post', 'board')
#i know this is funny.. just for purpose of this post
In every post there's a form that you can fill with "name" value.
This way the logged in user gets notification on every post update.
What is the best way to save the "user", "board", "post" data ?
1. Saving in the views directly (CBV):
class NotificationModelForm(forms.ModelForm):
class Meta:
model = Notification
fields = ["name"]
class CreateNotificationView(CreateView):
model = Notification
form_class = NotificationForm
def form_valid(self, form):
data = form.save(commit=False)
data.user = self.request.user
data.board = ...
data.save()
* if you have model validators (unique_together for user... this won't no longer work when submitting the form)
2. Displaying all the fields in the form, with some fields hidden
class NotificationModelForm(forms.ModelForm):
class Meta:
fields = ["user", "board", "post", "name"]
def __init__(self, *args, **kwargs):
super(NotificationModelForm, self).__init__(*args, **kwargs)
for field in ["user", "board", "post"]:
forms.field['field'].widget = forms.HiddenInput()
#I know this can be done other ways too
Now we need to prepopulate fields with initial data for these fields
class CreateNotificationView(CreateView):
model = Notification
form_class = NotificationModelForm
def get_initial(self):
initial = super(CreateNotificationView, self).get_initial()
initial['user'] = self.request.user
initial['board'] = ...
initial['post'] = ....
return initial
If the same field pattern (user, board, post) is used in more forms/views... I can also create a MixinView
class CommonUserFormMixin(object):
def get_form(self, form_class):
form = super(CommonUserFormMixin, self).get_form(form_class)
for field in ['user', 'board', 'post']:
form.fields[field].widget = forms.HiddenInput()
Then:
class NotifcationModelForm(forms.ModelForm):
class Meta:
model = Notification
fields = ["user", "board", "post", "name"]
class CreateNotificationView(CommonUserFormMixin, CreateView):
form_class = NotificationModelForm
model = Notification
* in 2 above scenarios we get model validators working.
3. Sending values to the form directly and overriding the form.save() method
class CreateNotificationView(CreateView):
model = Notification
form_class = NotificationModelForm
def get_form_kwargs(**kwargs):
kwargs = super(CreateNotificationView, self).get_form_kwargs(**kwargs)
kwargs['user'] = self.request.user
kwargs['board'] = ...
kwargs['post'] = ...
return kwargs
class NotificationModelForm(forms.ModelForm):
class Meta:
model = Notification
fields = ["name"]
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user')
self.board = kwargs.pop('board')
super(NotificationModelForm, self).__init__(*args, **kwargs)
def save(*args, **kwargs):
n = super(NotificationModelForm, self).save(commit=False)
n.user = self.user
n.board = self.board
n.save()
return n
I'm sure there are more ways to achive the same result.
What are your thoughts on that ?
When should I 'hide' (by using HiddenInput() widget) ModelForm fields? when should I save them directly
in view?
Does it all depend on needs or maybe there are some "best" standards ?