Django "if request.method == 'POST':" returns False - python

I'm making Django app and I have an issue, I've never had problem with before. As always in form view, I'm checking if request.method == 'POST' but somehow it returns False,
My code looks like that:
def recipe_create_view(request):
context = {}
form = RecipeForm(request.POST or None)
IngredientFormset = formset_factory(IngredientForm)
formset = IngredientFormset(request.POST or None)
context['form'] = form
context['formset'] = formset
if request.method == 'POST':
if form.is_valid():
if formset.is_valid():
form.save()
print("made a recipe")
for form in formset:
child = form.save(commit=False)
child.recipe = parent
child.save()
print("made a Ingredient")
else:
print("formset is not valid")
else:
print("form is not valid")
else:
print("request method is not correct")
return render(request, 'recipes/create_recipe.html', context)
create_recipe.html file:
<form method="POST">
{% csrf_token %}
<label>recipe</label>
<p>{{form}}</p>
<label>ingredients</label>
{% for form in formset %}
<ul>
<label>name</label>
<li>{{ form.name }}</li>
<label>quantity</label>
<li>{{ form.quantity }}</li>
</ul>
{% endfor %}
<div>
<input type="submit" value="submit" class="button-33" role="button">
</div>
</form>
Where is the problem?

It is necessary to return HttpResponseRedirect after dealing with POST data, the tip is not specific to Django, it's a good web practice in general.
Also, try to maintain both GET and POST request separately, so try below view:
def recipe_create_view(request):
context = {}
form="" # for the error of variable refrenced before assignment.
IngredientFormset=""
formset=""
if request.method == 'POST':
form = RecipeForm(request.POST)
IngredientFormset = formset_factory(IngredientForm)
formset = IngredientFormset(request.POST)
if form.is_valid():
if formset.is_valid():
form.save()
print("made a recipe")
for form in formset:
child = form.save(commit=False)
child.recipe = parent
child.save()
print("made a Ingredient")
return redirect('some_success_path_name')
else:
print("formset is not valid")
else:
print("form is not valid")
else: # GET method
print("request method is GET")
form = RecipeForm()
IngredientFormset = formset_factory(IngredientForm)
formset = IngredientFormset()
context['form'] = form
context['formset'] = formset
return render(request, 'recipes/create_recipe.html', context)

add action in your HTML form and POST in small case.
<form action="/your_backend_url_to_view/" method="post">
{% csrf_token %}
<label>recipe</label>
<p>{{form}}</p>
<label>ingredients</label>
{% for form in formset %}
<ul>
<label>name</label>
<li>{{ form.name }}</li>
<label>quantity</label>
<li>{{ form.quantity }}</li>
</ul>
{% endfor %}
<div>
<input type="submit" value="submit" class="button-33" role="button">
</div>
</form>

Related

How to add a comment liking system in Django

I'm attempting to allow a user to like comments of a particular post. However when I attempt to solve this, the expected result doesn't occur.
urls.py:
path('likecomment/<int:pk>/', post_views.likecomment,
name='likecomment'),
views.py:
def likecomment(request, pk):
if request.method == 'POST':
comment = get_object_or_404(Comment, pk=pk)
comment.likes += 1
comment.save()
return redirect('home')
comments.html:
{% for com in comments %}
<br>
<br>
<br>
<b>{{ com.user.username }}</b> &nbsp {{ com.body }}
<br>
<p class="text-muted">{{ com.pub_date_pretty }} &nbsp &nbsp
&nbsp &nbsp &nbsp {{ com.likes }} Likes</p>
<a href="javascript:
{document.getElementById('likecomment').submit()}"> Like </a>
<form id="likecomment" method="post" action="{% url 'likecomment'
com.id %}">
{% csrf_token%}
<input type="hidden">
</form>
<br>
{% endfor %}
Home view:
#login_required(login_url='/login')
def home(request):
posts = Post.objects.all()
return render(request, 'posts/home.html', {'posts': posts})
Render comments:
def comment(request, pk):
form = CommentForm()
comments = Comment.objects.filter(post__pk=pk)
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
comment = Comment()
comment.body = form.cleaned_data['body']
comment.user = request.user
comment.post = Post.objects.get(pk=pk)
comment.save()
return redirect('home')
else:
return render(request, 'posts/comments.html', {'error': 'Please submit valid data'})
else:
return render(request, 'posts/comments.html', {'form': form, 'comments': comments})
Like comments view:
def likecomment(request, pk):
if request.method == 'POST':
comment = get_object_or_404(Comment, pk=pk)
comment.likes += 1
comment.save()
return redirect('home')
The like occurs sometimes, however not for the right comment. The functionality isn't working correctly.
Image 1:
Image 2:
You have multiple HTML form elements with the same id (likecomment). Javascript has no way of knowing which one you meant to submit. Try appending a unique identifier, such as {{ forloop.counter }} to the id value, such as:
<form id="likecomment-{{ forloop.counter }}" ...
and
document.getElementById('likecomment-{{ forloop.counter }}').submit()

Editing view for combined form and inline_formset

I have been trying to create an editing view that allows me manage both parent and child models using an inline formset based in the documentation here
From what I can appreciate the formset doesn't validate. I did try and change it so that instead of validating the entire formset it iterated through each individual form in the formset and validated them individually. This did allow me to add items to the formset but not delete them.
At the moment the code results in "didn't return an HttpResponse object. It returned None instead" value error as the redirect is in the If valid statement and so if that does not result in true there is no other redirect to fall back on.
Models
class Shoppinglist(models.Model):
name = models.CharField(max_length=50)
description = models.TextField(max_length=2000)
created = models.DateField(auto_now_add=True)
created_by = models.ForeignKey(User, related_name='lists', on_delete=models.CASCADE)
last_updated = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
class Item(models.Model):
name = models.CharField(max_length=80, unique=True)
amount = models.IntegerField(default=1)
shoppinglist = models.ForeignKey(Shoppinglist, on_delete=models.CASCADE)
def __str__(self):
return self.name
URL
urlpatterns = [
url(r'^shoppinglists/(?P<pk>\d+)/edit/$', views.shoppinglist_edit, name='shoppinglist_edit'),
]
View
def shoppinglist_edit(request, pk):
try:
shoppinglist = Shoppinglist.objects.get(pk=pk)
except ShoppingList.DoesNotExist:
raise Http404
ItemInlineFormset = inlineformset_factory(Shoppinglist, Item, extra=1, fields=('name', 'amount'))
if request.method == "POST":
form = ShoppinglistForm(request.POST, instance=shoppinglist)
formset = ItemInlineFormset(request.POST, instance=shoppinglist)
if formset.is_valid() and form.is_valid():
form.save()
formset.save()
return redirect('packlist_list', pk=pk)
else:
form = ShoppinglistForm(instance=shoppinglist)
formset = ItemInlineFormset(instance=shoppinglist)
context = {
'shoppinglist' : shoppinglist,
'listform': form,
'formset': formset,
}
return render(request, 'edit_list_with_items.html', context)
Template
{% block content %}
<form method="post">
{% csrf_token %}
<label>List Name</label>
{{ listform.name }}
{% if listform.first_name.errors %}
{% for error in listform.first_name.errors %}
{{ error|escape }}
{% endfor %}
{% endif %}
<label>Description</label>
{{ listform.description }}
{% if listform.description.errors %}
{% for error in listform.description.errors %}
{{ error|escape }}
{% endfor %}
{% endif %}
{{ formset.management_form }}
{% for form in formset %}
<div class="item-formset">
{{ form.amount }}
{% if form.amount.errors %}
{% for error in form.amount.errors %}
{{ error|escape }}
{% endfor %}
{% endif %}
{{ form.name }}
{% if form.name.errors %}
{% for error in form.name.errors %}
{{ error|escape }}
{% endfor %}
{% endif %}
</div>
{% endfor %}
{% if formset.non_form_errors %}
{% for error in formset.non_form_errors %}
{{ error|escape }}
{% endfor %}
{% endif %}
<div class="row spacer">
<button type="submit" class="btn btn-block btn-primary">Create</button>
</div>
</form>
{% endblock %}
{% block extra_js %}
<script>
$('.item-formset').formset({
addText: 'add item',
deleteText: 'remove'
});
</script>
{% endblock %}
Please note I am using this jquery plugin in the template.
https://github.com/elo80ka/django-dynamic-formset
it is probably either your form or formset is invalid, and you dont use else statement to handle that.
so in your views.py:
if request.method == "POST":
form = ShoppinglistForm(request.POST, instance=shoppinglist)
formset = ItemInlineFormset(request.POST, instance=shoppinglist)
if formset.is_valid() and form.is_valid():
form.save()
formset.save()
return redirect('packlist_list', pk=pk)
else:
# either your form or formset is invalid, so this code will render it again.
context = {
'shoppinglist' : shoppinglist,
'listform': form,
'formset': formset,
}
return render(request, 'edit_list_with_items.html', context)
else:
form = ShoppinglistForm(instance=shoppinglist)
formset = ItemInlineFormset(instance=shoppinglist)
context = {
'shoppinglist' : shoppinglist,
'listform': form,
'formset': formset,
}
return render(request, 'edit_list_with_items.html', context)
or you can simplify it with this:
if request.method == "POST":
form = ShoppinglistForm(request.POST, instance=shoppinglist)
formset = ItemInlineFormset(request.POST, instance=shoppinglist)
if formset.is_valid() and form.is_valid():
form.save()
formset.save()
return redirect('packlist_list', pk=pk)
else:
form = ShoppinglistForm(instance=shoppinglist)
formset = ItemInlineFormset(instance=shoppinglist)
# notice the indentation
context = {
'shoppinglist' : shoppinglist,
'listform': form,
'formset': formset,
}
return render(request, 'edit_list_with_items.html', context)
Mentioned error coming because you write this return render(request, 'edit_list_with_items.html', context) inside else block.
instead of this:
else:
form = ShoppinglistForm(instance=shoppinglist)
formset = ItemInlineFormset(instance=shoppinglist)
context = {
'
}
return render(request, 'edit_list_with_items.html', context)
Do this:
else:
form = ShoppinglistForm(instance=shoppinglist)
formset = ItemInlineFormset(instance=shoppinglist)
context = {
}
return render(request, 'edit_list_with_items.html', context)

'ManagementForm data is missing or has been tampered with' error when loading multiple model forms django

views.py
#login_required(login_url='/account/login/')
def TaskCreateView(request,pk,todo_id):
if not request.user.is_authenticated:
return redirect('accounts:index')
else:
instance = get_object_or_404(Level, pk=pk)
qs = instance.todo_set.get(id = todo_id)
todo = Task.objects.filter(todo=qs, student=request.user)
if todo.exists():
messages.warning(request, 'You Already Completed This Task')
return HttpResponseRedirect(instance.get_absolute_url())
form = StudentTaskForm(request.POST or None, request.FILES or None)
if form.is_valid():
form.instance.user = User.objects.get(id=request.user.id)
obj = form.save(commit=False)
obj.student = request.user
obj.todo = qs
obj.level = instance
obj.save()
ImageFormSet = modelformset_factory(Images,
form=ImageForm, extra=3)
formset = ImageFormSet(request.POST, request.FILES,
queryset=Images.objects.none())
if request.method == 'POST':
if formset.is_valid():
for form in formset.cleaned_data:
image = form['image']
photo = Images(post=form, image=image)
photo.save()
return redirect('student:dashboard')
return render(request,'task_form.html',
{'form':form,"qs":qs,'formset':formset})
forms.py
class StudentTaskForm(forms.ModelForm):
title = forms.CharField(widget=forms.TextInput(attrs={'class':
'form-control',' type': "text",'placeholder':'Enter Title'}))
content = forms.CharField(widget=SummernoteWidget())
class Meta:
model = Task
fields = [
'title',
'content',
]
widgets = {
'content': SummernoteWidget(),
}
class ImageForm(forms.ModelForm):
image = forms.ImageField(label='Image')
class Meta:
model = Images
fields = ('image', )
I have two models Task and Images and I'm using two forms for the same.
Im trying to implement multiple image upload for the same. When I try to load the form I'm encountering this error. I have added the {{ formset.management_form }} in the template. The images model has a foreign key to the Task.
template:
<form id="post_form" action="" method="post"
enctype="multipart/form-data">
{% csrf_token %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in form %}
{{ field }} <br />
{% endfor %}
{{ formset.management_form }}
{% for form in formset %}
{{ form }}
{% endfor %}
<div class="panel-body">
<button type="submit" class="btn btn-primary m-t-10">Submit</button>
</div>
</form>
You should only instantiate the formset with request.POST for POST requests.
if request.method == 'POST':
formset = ImageFormSet(request.POST, request.FILES,
queryset=Images.objects.none())
...
else:
# GET request
formset = ImageFormSet(queryset=Images.objects.none())
...

How to Insert multiple data in django to django form?

I want to insert multiple row into my database from form2. Below are my codes
first model.py
class DataPribadiSiswa(models.Model):
SiswaID = models.AutoField(primary_key=True)
WaliKelasID=models.CharField(max_length=5,blank=True,null=True)
second model.py
class RiwayatSekolah(models.Model):
SekolahID=models.AutoField(primary_key=True)
SiswaID_FK=models.ForeignKey(DataPribadiSiswa,blank=True, null=True)
SekolahNama=models.CharField(max_length=50,blank=True,null=True)
SekolahThMasuk=models.CharField(max_length=4,blank=True,null=True)
SekolahThKeluar=models.CharField(max_length=4,blank=True,null=True)
SekolahKet=models.TextField(blank=True,null=True)
views.py
def tambah_siswa(request):
form = datasiswa(request.POST)
form2 = riwayatsekolah(request.POST)
FormSet2 = inlineformset_factory(DataPribadiSiswa, RiwayatSekolah, extra=2, fields=('SekolahID','SiswaID_FK','SekolahNama','SekolahThMasuk','SekolahThKeluar','SekolahKet'))
if request.method == 'POST':
if form.is_valid():
siswa_instance = form.save()
form2 = FormSet2(request.POST, instance=siswa_instance)
if form2.is_valid():
form2.save()
return redirect('index')
else:
formall={}
formall['form'] = datasiswa()
formall['form2'] = riwayatsekolah()
return render(request, 'siswa/tambah_siswa.html', formall)
and this is my template
<form action="" method="post">
{% csrf_token %}
<table >
{{ form2.management_form }}
{{ form2.as_table }}
</table>
</form>
How to insert multiple row from form2 into database? when i run this code, it just insert one row.
To simplify working with related objects you can use Inline formsets
You can implement it this way:
from django.forms import inlineformset_factory
FormSet2 = inlineformset_factory(DataPribadiSiswa, RiwayatSekolah, extra=2)
Now in view try this:
def tambah_siswa(request):
form = datasiswa(request.POST or None)
FormSet2 = inlineformset_factory(DataPribadiSiswa, RiwayatSekolah, extra=2, fields=('SekolahID','SiswaID_FK','SekolahNama','SekolahThMasuk','SekolahThKeluar','SekolahKet'))
if request.method == 'POST':
if form.is_valid():
siswa_instance = form.save()
form2 = FormSet2(request.POST or None, instance=siswa_instance)
if form2.is_valid():
form2.save()
return redirect('index')
form2 = FormSet2(request.POST or None)
formall={}
formall['form'] = form
formall['form2'] = form2
return render(request, 'siswa/tambah_siswa.html', formall)
And in template:
{{ form2.management_form }}
{{ form2.as_table }}
or
{{ form2.management_form }}
{% for frm in form2 %}
{{ frm.as_table }}
{% endfor %}

Take In Input from User and Display the same input on the same page

Hi i am trying to create a post form in django where the user creates a post and the post is displayed back to them on the same page so far i have been unsuccessful. My articles display on the page but the form to post articles doesnt only the submit button shows.
views.py
def articles(request):
args = {}
args.update(csrf(request))
args ['posts'] = post.objects.filter(user = request.user)
args ['full_name'] = User.objects.get(username = request.user.username)
return render_to_response('articles.html', args)
def article(request, post_id=1):
return render(request, 'article.html',
{'post': post.objects.get(id=post_id) })
def create(request):
if request.POST:
form = PostForm(request.POST, request.FILES)
if form.is_valid():
a = form.save(commit=False)
a.user = User.objects.get(username = request.user.username)
a.save()
messages.add_message(request, messages.SUCCESS, "You Article was added")
return HttpResponseRedirect('/posts/all')
else:
form = PostForm()
args = {}
args.update(csrf(request))
args['form'] = form
return render_to_response('articles.html', args)
articles.html
<form action="/posts/create/" method="post" enctype="multipart/form-data">{% csrf_token %}
<ul>
{{form.as_ul}}
</ul>
<input type="submit" name="submit" value="Create Article">
</form>
{% if posts.count > 0 %}
{% for post in posts %}
<div>
<h2>{{full_name}}</h2>
<p>{{ post.body|lower|truncatewords:50 }}</p>
<p>{{post.likes}} people liked this article</a></p>
</div>
{% endfor %}
{% else %}
<p>None to show!</p>
{% endif %}
{% endblock %}
urls.py
from django.conf.urls import patterns, include, url
urlpatterns = patterns('',
url(r'^create/$', 'posts.views.articles'),
url(r'^get/(?P<post_id>\d+)/$', 'posts.views.article'),
url(r'^create/$', 'posts.views.create'),
url(r'^like/(?P<post_id>\d+)/$', 'posts.views.like_article'),
url(r'^article/(?P<post_id>\d+)/$', 'posts.views.add_comment'),
)
First off you aren't passing the form to the template in articles(). You need to have something along the lines of:
args['form'] = YourForm()
In your first view function. Also, in your create view you do this:
a.user = User.objects.get(username = request.user.username)
Which does an unnecessary database lookup of the user again, you can just do this to be clearer and faster:
a.user = request.user

Categories

Resources