I have a function-based view that does not load the data that was inputted. The view does not throw any error at all. It just presents the form as a blank one.
urls.py
path('edit/<slug>/', editPost, name='edit'),
views.py
#login_required
def editPost(request, slug):
if request.method == 'POST':
post = get_object_or_404(Post, slug=slug)
form = PostForm(request.POST or None, request.FILES or None, instance=post)
if form.is_valid():
post.author = request.user.username
post.updated = True
form.save()
return redirect('dashboard')
else:
form = PostForm(request.POST, request.FILES, instance=post)
return render(request, 'edit_post.html', {'form': form})
template
<form class="dropdown-item" action="{% url 'edit' slug=post.slug %}" method="post">{% csrf_token %}
<input class="btn btn-sm" type="submit" value="Edit">
render form in template, using {{ form.as_p }}
<form class="dropdown-item" action="{% url 'edit' slug=post.slug %}" method="post">
{% csrf_token %}
<!-- render form here -->
{{ form.as_p }}
<input class="btn btn-sm" type="submit" value="Edit">
</form>
or loop through form fields as
<form class="dropdown-item" action="{% url 'edit' slug=post.slug %}" method="post">
{% csrf_token %}
<!-- render form here -->
{% for field in form %}
{{ field.label }}
{{ field }}
{{ field.error }}
{% endfor %}
<input class="btn btn-sm" type="submit" value="Edit">
</form>
#login_required
def editPost(request, slug):
post = get_object_or_404(Post, slug=slug)
if request.method == 'POST':
form = PostForm(request.POST or None, request.FILES or None, instance=post)
if form.is_valid():
post.author = request.user.username
post.updated = True
form.save()
return redirect('dashboard')
else:
form = PostForm(instance=post)
return render(request, 'edit_post.html', {'form': form})
Probably you have to do something like that, there is not any reason to pass request.POST and request.FILES when you don't have POST action in the view. In that way you just have to pass the post object that have all the related info.
And also you have to render your form in the following way:
<form class="dropdown-item" action="{% url 'edit' slug=post.slug %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<!-- render form here -->
{{ form.as_p }}
<input class="btn btn-sm" type="submit" value="Edit">
</form>
Notice that enctype="multipart/form-data" is mandatory 'cause you are dealing with files in your form elsewhere it won't work properly.
Also checkout where you have to put your post = get_object_or_404(Post, slug=slug) line, 'cause in thay way you can pass the object to whatever action that is being performing (POST or GET).
Related
Can you see is there any problem? I don't have any errors, everything is showing but when I upload document, nothing happens, document is not uploaded. Everything seems as it should be, but something I missed, why won't upload document?
my_app/forms.py
class UploadFileForm(forms.Form):
file = forms.FileField()
my_app/hendle_file.py
def handle_uploaded_file(f):
with open('my_app/static/upload/'+f.name, 'wb+') as destination:
for chunk in f.chunks():
destination.write(chunk)
my_app/views.py
from .forms import UploadFileForm
from .handle_file import handle_uploaded_file
def upload_file(request):
form = UploadFileForm()
if request.method == 'POST':
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
print(form.cleaned_data)
handle_uploaded_file(request.FILES['file'])
return HttpResponseRedirect('file uploaded')
else:
form = UploadFileForm()
return render(request, 'my_app/uploadfile.html', {'form': form})
my_app/template/my_app/uploadfile.html
{% extends "my_app/base.html" %}
{% block content %}
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<h1>Upload your document!</h1>
{{ form.as_p }}
<input type="submit" type="button" value="Upload"
</form>
{% endblock content %}
To upload a file within a form the enctype attribute has to be set to multipart/form-data
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<h1>Upload your document!</h1>
{{ form.as_p }}
<input type="submit" type="button" value="Upload"
</form>
I am using two forms in one template. When i submit the 2nd form its calling first form only i'm little bit confusing where i did mistake anyone help me in this.
index.html
<form action="#" method="post">
{% csrf_token %}
<input type="text" name="username" id="username">
<button type="submit"> Submit</button>
</form>
<form action="#" method="post">
{% csrf_token %}
<input type="text" name="review" id="review">
<button type="submit"> Submit</button>
</form>
views.py
def profile(request):
if request.method == 'GET':
# Some operation
return render(request, 'index.html', {})
elif request.method == 'POST':
username = request.POST.get('username')
res = User(username=username)
res.save()
return redirect('/home/')
return redirect('/login/')
def feedback(request):
if request.method == 'POST':
review= request.POST.get('review')
res = Feedback(comment=review)
res.save()
return redirect('/home/')
return redirect('/home/')
urls.py
app_name = 'app'
urlpatterns = [
path('profile/', views.profile, name="profile"),
path('feedback/', views.feedback, name="feedback"),
]
I think the actions should be different to identify which form will make post request to which view:
<form action="{% url 'app:profile' %}" method="post">
{% csrf_token %}
<input type="text" name="username" id="username">
<button type="submit"> Submit</button>
</form>
<form action="{% url 'app:feedback' %}" method="post">
{% csrf_token %}
<input type="text" name="review" id="review">
<button type="submit"> Submit</button>
</form>
Add name attribute in submit.
<form action="#" method="post">
<input type="text" name="username" id="username">
<button type="submit" name="attr_name"> Submit</button>
</form>
And check the name in views.py
def profile(request):
if request.method == 'POST' and 'attr_name' in request.POST:
# Some operation
The form submits but immediately says this field is required... although it was filled out. What am I doing wrong
In my view:
def fileupload(request):
if request.user.is_authenticated and request.user.is_staff:
if request.method == 'POST':
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
handle_uploaded_file(request.FILES.getlist('file_field'))
return HttpResponseRedirect('/fileupload/')
else:
form = UploadFileForm()
return render(request, 'fileupload.j2.html', {'form': form})
return HttpResponseForbidden('<h1>403 Forbidden</h1>')
with this form:
class UploadFileForm(forms.Form):
kit_number = forms.CharField(label="Kit number", max_length=100, required=True, help_text='Required.')
file_field = forms.FileField(label='Upload kit result')
and template:
{% extends "menu.j2.html" %}
{% block content %}
{% if request.user.is_authenticated and request.user.is_staff %}
<h3>File upload</h3><br><br>
<form action="/fileupload/" method="post">
{% csrf_token %}
<div class="form-group">
<table>
{{ form.as_table() }}
</table>
</div>
<input id="button" class="btn" type="submit" value="Sent">
</form>
{% else %}
You are not authorized to see this page
{% endif %}
{% endblock %}
You forgot to set the form enctype.
<form action="/fileupload/" method="post" enctype="multipart/form-data">
My method to redirect a url after login, work well but the code of the template is not very sexy, can I have yours please ?
my function in views.py
def connexion(request):
error = False
n=request.GET.get('n')
if request.method == "POST":
form = ConnexionForm(request.POST)
if form.is_valid():
username = form.cleaned_data["username"]
password = form.cleaned_data["password"]
user = authenticate(username=username, password=password)
if user:
login(request, user)
if request.GET.get('n'):
return redirect(request.GET['n'])
else:
return redirect(accueil)
else:
error = True
else:
form = ConnexionForm()
return render(request, 'blog/connect_user.html', locals())
my template:
<h1>Se connecter</h1>
{% if error %}
<p><strong>Utilisateur inconnu ou mauvais mot de passe.</strong></p>
{% endif %}
{%if n %}
<form method="post" action="{% url 'connexion' %}?n={{ n }}">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Se connecter" />
</form>
{% else %}
<form method="post" action="{% url 'connexion' %}">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Se connecter" />
</form>
{% endif %}
my decorator:
#login_required(redirect_field_name='n')
Why not just:
<input type="hidden" name="n" value="{{ n }}">
And in the view:
n = request.REQUEST.get('n', '')
Using request.REQUEST you can get n from either using POST or GET so you can still link to a URL like /login?n=/foo/bar. You can also do POST/REDIRECT/GET without problems.
I have to insert 2 forms in the same page:
1) Registration form
2) Login form
.
So if I use this in the views.py:
if request.method == 'POST':
form = registrationForm(request.POST)
if form.is_valid():
form.save()
return render_to_response('template.html', {
'form': form,
})
I will get error by submitting one of two forms.
How can I distinguish the 2 forms submitting in the views ?
You can also do like this,
<form method='POST'>
{{form1.as_p}}
<button type="submit" name="btnform1">Save Changes</button>
</form>
<form method='POST'>
{{form2.as_p}}
<button type="submit" name="btnform2">Save Changes</button>
</form>
CODE
if request.method=='POST' and 'btnform1' in request.POST:
do something...
if request.method=='POST' and 'btnform2' in request.POST:
do something...
You can submit two forms on the same page... but the action that each form calls (i.e. the view function that will process each form) should probably be different. That way, you won't have to try and distinguish the forms.
e.g. On your page:
<form id="login_form" action="{% url app.views.login %}" method="post">
...form fields...
</form>
<form id="registration_form" action="{% url app.views.registration %}" method="post">
...form fields...
</form>
And so, in views.py, you'll have a login() view function and a registration() view function that will handle each of those forms.
<form action="Page where u want to post the data" method="post">
<input name="edit" type="submit" value="Edit Client">
<input name="delete" type="submit" value="Delete Client">
</form>
just Give different names to the buttons.
if request.method == "POST" and 'edit' in request.POST:
/ Do /
if request.method == "POST" and 'delete' in request.POST:
/Do /
You can post both forms to same url too:
forms in template are like this:
<form method="post" action="/profile/">
{% for field in firstform %}
<div class="mb10">
<div class="fl desc">{{ field.label_tag }}<br />
<div class="fr">{{ field }}{{ field.errors }}</div>
<div class="clear"></div>
</div>
{% endfor %}
{% for field in secondform %}
<div class="mb10">
<div class="fl desc">{{ field.label_tag }}<br /><</div>
<div class="fr">{{ field }}{{ field.errors }}</div>
<div class="clear"></div>
</div>
{% endfor %}
<a class="submit fr" href="#""><img src="{{ MEDIA_URL }}img/save.png" /></a>
</form>
and just handle them like this in view:
if request.method == 'POST':
firstform = ProfileForm(request.POST, request.FILES, instance=profile)
secondform = UserForm(request.POST, instance=request.user)
and then do stuff with firstform&secondform.
You can have both forms posting to the same URL and have a hidden input with name set to login or registration and sort that out on the server
You can do the Registration and Login POST to different urls so each POST will be handled by corresponding view