I cannot add a file in Django. When I click the "save" button, it does not save the database.
This is my view.py:
def add_product(request):
if request.method == "POST":
form = PostForm(request.POST, request.FILES)
if form.is_valid():
post = form.save(commit=False)
post.userprofile = request.user
post.save()
return redirect('kerajinan.views.add_product', pk=post.pk)
else:
form = PostForm()
return render(request, 'kerajinan/add_product.html', {'form': form})
add_product.html:
{% block content %}
<h1>New Product</h1>
<from method="POST" class="post-form" enctype="multiple/form-data">{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="save btn btn-default">Save</button>
</from>
{% endblock %}
forms.py:
class PostForm(forms.ModelForm):
class Meta:
model = Product
fields = ('category','title', 'price','image', 'description')
and urls.py:
url(r'^add_product/$', views.add_product, name='add_product'),
Can you help me solve my problem?
You need to change your enctype to: enctype="multipart/form-data"
Your current value (multiple/form-data), is not a valid method of encoding.
From the docs:
Note that request.FILES will only contain data if...the <form> that posted the request has the attribute enctype="multipart/form-data". Otherwise, request.FILES will be empty.
Related
I have a problem, the urls form works but I can't see the records in url/admin, can I ask for help, thank you :D
SOF wants me to add more details otherwise it doesn't transfer, I don't know what more I can add, generally temapals and urls work.
class Note(models.Model):
"""..."""
notes = models.CharField(max_length=100, unique=True)
description = models.TextField()
class Meta:
verbose_name = "Note"
verbose_name_plural = "Notes"
def __str__(self):
return self.notes
class NoteView(View):
def get(self, request):
if request.method == 'POST':
textN = Note.objects.all().order_by('notes')
form = NoteAddForm(request.POST)
if form.is_valid():
form.save()
return redirect('Files/menu')
else:
textN = NoteAddForm()
return render(request, 'Files/note.html', {'textN': textN})
class NoteAddForm(forms.ModelForm):
"""New note add form"""
class Meta:
model = Note
fields = '__all__'
{% extends 'Files/base.html' %}
{% block title %}Notatnik{% endblock %}
<h2>Notatnik Dietetyka/ Zalecenia ręczne </h2>
{% block content %}
<form action="/send/" method="post">
{% csrf_token %}
{{ textN }}
<label>
<input type="text" class="btn btn-second btn-lg">
<button>Wyślij formularz</button>
</label>
</form>
<button type="button" class="btn btn-primary btn-lg">Powrót</button>
{% endblock %}
Within your NoteView class in views.py file is where the issue is.
I see you have an if statement checking for if request.method == 'POST' within the class-based view get(). The get() is equivalent to if request.method == 'GET'. Therefore, what you might want to do is to override the post() on the class instead. For example:
class NoteView(View):
template_name = 'Files/note.html'
# Use the get method to pass the form to the template
def get(self, request, *arg, **kwargs):
textN = NoteAddForm()
return render(request, self.template_name, {'textN': textN})
# Use the post method to handle the form submission
def post(self, request, *arg, **kwargs):
# textN = Note.objects.all().order_by('notes') -> Not sure why you have this here...
form = NoteAddForm(request.POST)
if form.is_valid():
form.save()
# if the path is... i.e: path('success/', SucessView.as_view(), name='success')
return redirect('success') # Redirect upon submission
else:
print(form.errors) # To see the field(s) preventing the form from being submitted
# Passing back the form to the template in the name 'textN'
return render(request, self.template_name, {'textN': form})
Ideally, that should fix the issue you're having.
Updates
On the form, what I'd suggest having is...
# Assuming that this view handles both the get and post request
<form method="POST"> # Therefore, removing the action attribute from the form
{% csrf_token %}
{{ textN }}
# You need to set the type as "submit", this will create a submit button to submit the form
<input type="submit" class="btn btn-second btn-lg" value="Submit">
</form>
In my app, I have created a context_proccessors.py to show the form to base.html file.
I am able to show the form in the base.html file. But the problem I am facing is I have no idea how to save that form data from base.html since there is no view for the base.html. Below is my code:
models.py
class Posts(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='user_posts')
post_pic = models.ImageField(upload_to='post_pic', verbose_name="Image")
post_caption = models.TextField(max_length=264, verbose_name="Caption")
created_date = models.DateTimeField(auto_now_add=True)
edited_date = models.DateTimeField(auto_now=True)
def __str__(self):
return f"{self.user.username}"
forms.py
from django import forms
from post_app.models import Posts
class PostForm(forms.ModelForm):
class Meta:
model = Posts
exclude = ('user',)
context_proccessors.py
from post_app.forms import PostForm
def post_form(request):
form = PostForm
return {
'post_form': form,
}
base.html
<form method="POST" enctype="multipart/form-data">
{{ post_form|crispy }}
{% csrf_token %}
<button type="submit" class="btn btn-primary">Post</button>
</form>
I want the form to be displayed on every page so that the user can submit data from anywhere
def PostView(request):
form = PostForm()
if request.method == 'GET':
return render(request, 'base.html', {form:form})
elif request.method == 'POST':
form.save(request.data)
In the views.py of your app you can define this view, and the you have to provide it an url in the urls.py of the root directory. So evere time there is a request on that url, if the method is GET, the form will be rendered on base.html file, if the method is POST, the post will be saved.
By following the answer by N T I have implemented this. So, I had to make a URL pattern for the view and use that URL pattern in the action in the form of base.html.
view.py
#login_required
def postsaveview(request):
form = PostForm()
if request.method == 'POST':
form = PostForm(request.POST, request.FILES)
if form.is_valid():
user_obj = form.save(commit=False)
user_obj.user = request.user
user_obj.slug = str(request.user) + str(uuid.uuid4())
user_obj.save()
return HttpResponseRedirect(reverse('profile_app:profile'))
urls.py
urlpatterns = [
path('post-save/', views.postsaveview, name='post-save'),
]
base.html
<form action="{% url "post-save" %}" method="POST" enctype="multipart/form-data">
{{ post_form|crispy }}
{% csrf_token %}
<button type="submit" class="btn btn-primary">Post</button>
</form>
I cobbled together a delete button and edited my view, it isn't working. Can someone help me fix it?
I've moved some code around and tried some things but I can't get it to work. I need someone to show me what I'm doing wrong.
My view:
def post_edit(request, pk):
post = get_object_or_404(Listing, pk=pk)
if request.method == "POST":
form = ListingForm(request.POST, instance=post)
if form.is_valid():
post = form.save(commit=False)
post.save()
return redirect('post_view', pk=post.pk)
else:
form = ListingForm(instance=post)
if request.POST.get('delete'):
post.delete()
return redirect('listings')
return render(request, 'post_edit.html', {'form': form})
My html:
{% extends 'base.html' %}
{% block title %}Post Edit{% endblock %}
{% block content %}
Hi {{ user.username }}!
<p>logout</p>
<h1>Edit listing:</h1>
<p>The listing will only be viewable to users if "Is Live" is checked.</p>
<form method="POST" enctype="multipart/form-data" class="post-form">{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="save btn btn-default">Save</button>
<p>Click the button below to delete this listing. No second warning is given, once you click delete it will be
removed.</p>
<button type="delete" class="delete btn btn-default">delete</button>
</form>
{% endblock %}
"delete" is not a valid type for an HTML form control. You'l need to change it to "submit" (Since you still want to submit the form).
What you'll want to do is create two buttons with the same name, and different values like this:
<button type="submit" name="submit" value="submit" class="save btn btn-default">Save</button>
<p>Click the button below to delete this listing. No second warning is given, once you click delete it will be
removed.</p>
<button type="submit" name="submit" value="delete" class="delete btn btn-default">delete</button>
Then you can check in your view if the delete button was clicked, like this:
def post_edit(request, pk):
post = get_object_or_404(Listing, pk=pk)
if request.method == "POST":
if request.POST.get('submit') == 'delete':
post.delete()
return redirect('listings')
form = ListingForm(request.POST, instance=post)
if form.is_valid():
post = form.save(commit=False)
post.save()
return redirect('post_view', pk=post.pk)
else:
form = ListingForm(instance=post)
return render(request, 'post_edit.html', {'form': form})
Note that I move the check for the delete button to inside the if request.method == "POST": block, for two reasons:
You'll only want to check the POST values if it's actually a post method.
There is no use editing a post, then deleting it.
Hi i try add comment to my django blog procject and i get OSError: [Errno 22] Invalid argument: "C:\Users\marci\PycharmProjects\08.04\blog\templates\"
so my urls
path('<int:a_id>/addcomment', views.addcomment, name='addcomment'),
views.py
def addcomment(request, a_id):
article = get_object_or_404(Articles,id=a_id)
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.article = article
comment.save()
return HttpResponseRedirect('/article/%s' % a_id)
else:
form = CommentForm()
template = 'addcomment.html'
context = {'form': form}
return render_to_response(request,template,context)
addcomment.html
{% extends 'main.html' %}
{% block article %}
<form action="/article/{{ article.id }}/addcomment/" method="post" class="form-horizontal well">{% csrf_token %}
{{ form.as_p }}
<input type="submit" class="btn btn-inverse" name="submit" value="Dodaj komentarz" />
</form>
{% endblock %}
thx
You should be using render instead of render_to_response. You should also include article in the template context if you use it. Deindent the template and contect lines, so that the view works for invalid post requests.
def addcomment(request, a_id):
article = get_object_or_404(Articles,id=a_id)
if request.method == 'POST':
...
else:
form = CommentForm()
template = 'addcomment.html'
context = {'form': form, 'article': article}
return render(request, template, context)
After user logs in, user is able to submit a form. On click of submit button, data is being stored in DB, but how should I connect this information to the submitting user.
I would need the code as well as the structure of the new db
Kind of starting out in django.
Any help would be appreciated!!!
I have included user as foreign key in the CustomizeRequest model, but now how do i fill in this information?
Exact Scenario: After user log in, once he comes to contactUs.html, he submits a form which tells the number of travellers. This number is being stored in the DB. But now how do I connect each of these numbers to the submitted user?
models.py
class CustomizeRequest(models.Model):
user = models.ForeignKey(User)
travellers = models.CharField(max_length=2)
def __str__(self):
return self.travellers
contactUs.html
<form method="POST" class="form-horizontal">
{% csrf_token %}
<div class="btn-group" data-toggle="buttons">
{% for radio in crform.travellers %}
<label class="btn btn-default {% if radio.choice_label = '1' %}active{% endif %}" for="{{ radio.id_for_label }}">
{{ radio.choice_label }}
{{ radio.tag }}
</label>
{% endfor %}
</div>
<button type="submit" class="btn btn-default btn-block btn-warning">SUBMIT</button>
</form>
views.py
def contactUs(request):
if request.method=="POST":
form = CustomizeRequestForm(request.POST)
form.save()
else:
form = CustomizeRequestForm()
context_dict = {'form': form}
return render(request, 'tour/contactUs.html', context_dict)
Based on catavaran answer (with a check to see if the form is valid):
from django.contrib.auth.decorators import login_required
from django.shortcuts import redirect, render
#login_required
def contactUs(request):
form = CustomizeRequestForm(data=request.POST or None)
if request.method == "POST":
if form.is_valid():
customize_request = form.save(commit=False)
customize_request.user = request.user
customize_request.save()
return redirect('.')
else:
pass # could add a notification here
context_dict = {'form': form}
return render(request, 'tour/contactUs.html', context_dict)
Logged user is available as request.user property. You can get the unsaved model instance using form.save(commit=False) trick, set the user field and then save the instance to database:
from django.contrib.auth.decorators import login_required
from django.shortcuts import redirect, render
#login_required
def contactUs(request):
if request.method == "POST":
form = CustomizeRequestForm(request.POST)
if form.is_valid():
customize_request = form.save(commit=False)
customize_request.user = request.user
customize_request.save()
return redirect('.')
else:
form = CustomizeRequestForm()
context_dict = {'form': form}
return render(request, 'tour/contactUs.html', context_dict)