How to define initial values for ModelForm rightly? - django

I have no idea and I need to ask your advice.
I have simple form:
class CommentForm(ModelForm):
class Meta:
model = Comment
fields = ['text','author','news']
I want to add form in DetailView and hadle this form there:
class NewsDetailView(DetailView):
model = News
template_name = 'news/detail.html'
def get_initial(self):
return {'news': self.get_object(), 'author': self.request.user}
def get_context_data(self, **kwargs):
context = super(NewsDetailView, self).get_context_data(**kwargs)
context['form'] = CommentForm(initial=self.get_initial())
return context
def post(self, request, *args, **kwargs):
'''
comment_form = CommentForm(request.POST)
if comment_form.is_valid():
comment_form.save()
I don't want to show 'author' and news fieds. But if I hide them I can't to get initial values..
UPDATED:
After form validation I need return current form instance in the template through updating page. I attempted the next:
comment_form = CommentForm(request.POST, request=request)
if comment_form.is_valid() and comment_form.validate_user():
comment_form.save()
return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
else:
context = super(NewsDetailView,self).get_context_data(**kwargs)
context['form'] = comment_form
return self.render_to_response(context)
But did not work.

If you don't render your fields using {{ form.author }} and {{ form.news }} the form won't validate. Try using a HiddenInput for each field, You can do that by overriding the __init__ method of your form:
class CommentForm(ModelForm):
def __init__(self, *args, **kwargs):
super(CommentForm, self).__init__(*args, **kwargs)
self.fields['author'].widget = forms.HiddenInput()
self.fields['news'].widget = forms.HiddenInput()
class Meta:
model = Comment
fields = ['text','author','news']

Related

Filtering dropdown queryset based on URL parameter

I am building a CRM where I want each client to have multiple plans, and each plan to have multiple notes. When a user creates a new note, I want them to be able to select a relevant plan from a dropdown of plans belonging to the client. From what I can find, I should be able to get the contact_id from the kwargs, but my errors show nothing in kwargs. I know there should be a way to do this, but I can't seem to find it.
Variable Value
__class__ <class 'lynx.forms.SipNoteForm'>
args ()
kwargs {}
self <SipNoteForm bound=False, valid=Unknown, fields=(sip_plan;note;note_date;fiscal_year;quarter;class_hours;instructor;clients)>
Views.py
#login_required
def add_sip_note(request, contact_id):
form = SipNoteForm()
if request.method == 'POST':
form = SipNoteForm(request.POST)
if form.is_valid():
form = form.save(commit=False)
form.contact_id = contact_id
form.user_id = request.user.id
form.save()
return HttpResponseRedirect(reverse('lynx:client', args=(contact_id,)))
return render(request, 'lynx/add_sip_note.html', {'form': form})
Forms.py
class SipNoteForm(forms.ModelForm):
class Meta:
model = SipNote
exclude = ('created', 'modified', 'user', 'contact')
def __init__(self, *args, **kwargs):
super(SipNoteForm, self).__init__(*args, **kwargs)
self.fields['sip_plan'].queryset = SipPlan.objects.filter(contact_id=kwargs.get("contact_id"))
Urls.py
path('add-sip-note/<int:contact_id>/', views.add_sip_note, name='add_sip_note'),
You are trying to get the kwargs in __init__(self, *args, **kwargs) as
def __init__(self, *args, **kwargs):
contact_id = kwargs.pop('contact_id')
super(SipNoteForm, self).__init__(*args, **kwargs)
self.fields['sip_plan'].queryset = SipPlan.objects.filter(contact_id=contact_id)
But you are not passing contact_id kwargs to the form while posting. you should pass kwargs to the form you are going to get in __init__(self, *args, **kwargs) such as
#login_required
def add_sip_note(request, contact_id):
form = SipNoteForm()
if request.method == 'POST':
form = SipNoteForm(request.POST, contact_id=contact_id)

'ProjectFormFormSet' object has no attribute 'request'

I want to add to my project one feature that only authenticated users can have access their stuff. But when I write queryset it throws an error like ModelNameFormSet object has no request attribute
views.py
class BaseAuthorFormSet(BaseModelFormSet):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.queryset = Project.objects.filter(author_id=self.request.user.pk)
def add_object(request):
ProjectFormSet = modelformset_factory(Project, formset=BaseAuthorFormSet, fields=( 'service_name', 'service_code', 'report_month', 'report_year', 'last_year'), extra=1)
if request.method == "POST":
form = ProjectFormSet(request.POST)
form.author = request.user
if form.is_valid():
form.save()
form = ProjectFormSet()
return render(request, 'app1/home.html',{'form':form})
I have only this code. How can I solve this issue? Thank you beforehand!
If you need the request in the formset, you need to pass it there. Also note that adding the author to the formset won't do anything, you need to add it to the result of each form save.
class BaseAuthorFormSet(BaseModelFormSet):
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request')
super().__init__(*args, **kwargs)
self.queryset = Project.objects.filter(author_id=self.request.user.pk)
def add_object(request):
ProjectFormSet = modelformset_factory(Project, formset=BaseAuthorFormSet, fields=( 'service_name', 'service_code', 'report_month', 'report_year', 'last_year'), extra=1)
if request.method == "POST":
formset = ProjectFormSet(request.POST, request=request)
if formset.is_valid():
for form in formset:
obj=form.save(commit=False)
obj.author = request.user
obj.save()
return redirect('somewhere')
form = ProjectFormSet(request=request)
return render(request, 'app1/home.html',{'form':form})

Django add value to hidden field inline formset

I am using Django 1.11. I am trying to add a value to a hidden field in an inline formset form. I have tried unsuccessfully inserting the hidden field value at various points of def get_context_data and def form_valid. The code I am using is as follows:
views.py
#method_decorator(login_required, name='dispatch')
class DocumentCreate(CreateView):
model = DocumentClient
success_url = reverse_lazy('documents')
form_class = DocumentForm
def get_context_data(self, **kwargs):
data = super(DocumentCreate, self).get_context_data(**kwargs)
if self.request.POST:
data['docform'] = DocumentFormSet(self.request.POST, self.request.FILES)
else:
data['docform'] = DocumentFormSet()
return data
def form_valid(self, form):
context = self.get_context_data()
docform = context['docform']
if docform.is_valid():
self.object = form.save()
docform.instance = self.object
docform.save()
return HttpResponseRedirect('documents')
else:
return self.render_to_response(self.get_context_data(form=form))
forms.py
class DocumentForm(ModelForm):
class Meta:
model = DocumentClient
exclude = ()
widgets = {
'cnum': HiddenInput(),
}
def __init__(self, *args, **kwargs):
super(DocumentForm, self).__init__(*args, **kwargs)
for field in self.fields:
self.fields['cnum'].required = False
class DocumentDetailForm(ModelForm):
class Meta:
model = DocumentDetail
exclude = ()
widgets = {
'document_date': DateInput(),
}
def __init__(self, *args, **kwargs):
super(DocumentDetailForm, self).__init__(*args, **kwargs)
self.fields['document_description'].required = False
DocumentFormSet = inlineformset_factory(DocumentClient, DocumentDetail, form=DocumentDetailForm, extra=10, can_delete=False)
The hidden field 'cnum' is that what I am trying to insert a value for capturing in the model. Is anyone able to provide any guidance on how to acheive this? Any assistance is gratefully appreciated!
In DocumentCreate, have you tried this?
class DocumentCreate(CreateView):
def get_initial(self):
# Get initial value from kwargs (If needed) and save as instance variable.
self.cnum_val = self.kwargs.get('cnum_value')
def form_valid(self, form):
# Insert your desired value to cnum (or you can simply forget get_initial and supply whatever value here)
form.instance.cnum = self.cnum_val
self.object = form.save()
...
self.render_to_response(self.get_context_data(form=form))
form.instance refers to the unsaved model object used by the form
See here also.

Initialize form with request.user in a ModelForm django

I have this ModelForm
class ScheduleForm(forms.ModelForm):
class Meta:
model = Schedule
fields = ['name', 'involved_people',]
def __init__(self, user, *args, **kwargs):
super(ScheduleForm, self).__init__(*args, **kwargs)
self.fields['involved_people'].queryset = Profile.objects.exclude(user=user)
This is my view
def create_schedule(request):
form = ScheduleForm(request.POST or None)
schedules = Schedule.objects.all().order_by('deadline_date')
if form.is_valid():
schedule = form.save(commit=False)
schedule.save()
messages.success(request, "Schedule added successfully!")
return render(request, 'schedule/index.html', {'schedules': schedules})
context = {'form': form}
return render(request, 'schedule/create_schedule.html', context)
How do you pass request.user in the view?
How do you initialize the form with request.user in it?
You have added user to the __init__ method,
def __init__(self, user, *args, **kwargs):
so now you just pass the user as the first argument when you instantiate your form.
form = ScheduleForm(request.user, request.POST or None)

NOT NULL constraint failed when save ModelForm

I am new in Django (1.9)
I have a NOT NULL constraint failed when I save my ModelForm and i don't understand why ...
I propose to the user a form to post a comment and the only field include in the form is "text", i want to set the excluded fields in my view after the validation and before save in database
Models.py :
class Commentaire(models.Model):
text = RichTextField()
pub_date = models.DateTimeField()
author = models.ForeignKey(User)
post = models.ForeignKey(Post)
publish = models.BooleanField()
def __str__(self):
return "/%s/%s" % (self.pub_date,self.author.username)
class Meta:
ordering = ["-pub_date"]
Forms.py :
class CommentaireForm(forms.ModelForm):
class Meta:
model = Commentaire
fields = ['text']
Views.py :
class PostDetail(View):
def get(self, request, *args, **kwargs):
view = PostDisplay.as_view()
return view(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
view = PostComment.as_view()
return view(request, *args, **kwargs)
class PostDisplay(DetailView):
model = Post
def get_context_data(self, **kwargs):
context = super(PostDisplay, self).get_context_data(**kwargs)
context['form'] = CommentaireForm()
return context
class PostComment(SingleObjectMixin, FormView):
template_name = 'blogengine/post_detail.html'
form_class = CommentaireForm
model = Post
def post(self, request, *args, **kwargs):
#if not request.user.is_authenticated():
# return HttpResponseForbidden()
self.object = self.get_object()
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form):
"""
If the form is valid, redirect to the supplied URL
"""
form.save(commit=False)
form.post = self.object
form.author = self.request.user
form.pub_date = datetime.now()
form.publish = True
form.save()
return HttpResponseRedirect(self.get_success_url())
When Django save the form, i have this exception :
NOT NULL constraint failed: blogengine_commentaire.pub_date
The values i set for the excluded fields (author, post, pub_date) in "form_valid" are not taken into account, they seem to stay NULL
Could you explain me why because i am lost ?
Thanks
You need to rewrite form_valid method like that
def form_valid(self, form):
"""
If the form is valid, redirect to the supplied URL
"""
model_instance = form.save(commit=False)
model_instance.post = self.object
model_instance.author = self.request.user
model_instance.pub_date = datetime.now()
model_instance.publish = True
model_instance.save()
return HttpResponseRedirect(self.get_success_url())
Because save(commit=False) will return you an Post instance that you then need to populate and save.