I have a form where user just uploads an image,but problem is when I choose an image and press button to submit. It says This field is required.on the page although I have already pointed the image. And that's all it does.I checked if it was actually submitted but no, it was not.What could be the problem ?
Models.py
class pic(models.Model):
username = "anonymous"
picpost = models.ImageField(upload_to='anon_pics')
creation_date = models.DateTimeField(auto_now_add=True)
forms.py
from django import forms
from .models import pic
class PicForm(forms.ModelForm):
class Meta:
model = pic
fields = [
"picpost"
]
view.py
def pic_create(request):
form = PicForm(request.POST or None)
if form.is_valid():
instance = form.save(commit=False)
instance.save()
context = {
"form" : form,
}
return render(request, "create_pic.html", context)
create_pic.html
<body>
<form method='POST' action=''>{% csrf_token %}
{{ form.as_p }}
<input type='submit' value='Upload Picture' />
</form>
</body>
Any help is highly appreciated.Thank you very much!
There are two issues here.
Firstly, your view needs to pass request.FILES as well as request.POST to the form.
Secondly, your form element in the template needs to include enctype="multipart/form-data".
Related
I started to learn Django today, but I am stuck at using forms. I have created two forms: /contact and /blog-new. The form at the Contact page is working fine, but the one at /blog-new is redirecting me to the home page after the submission button is pressed and no information is printed in the terminal nor saved in the database.
Code on Github
I appreciate if someone can explain to me what I did wrong as I cannot figure it out. Thank you!
mysite/blog/forms.py
from django import forms
from .models import BlogPost
class BlogPostModelForm(forms.ModelForm):
class Meta:
model = BlogPost
fields = ['title', 'slug', 'content']
mysite/blog/views.py
from .forms import BlogPostModelForm
def blog_post_create_view(request):
# create objects
# ? use a form
# request.user -> return something
form = BlogPostModelForm(request.POST or None)
if form.is_valid():
print(form.cleaned_data)
form.save()
form = BlogPostModelForm()
template_name = 'form.html'
context = {'form': form}
return render(request, template_name, context)
mysite/blog/models.py
from django.db import models
# Create your models here.
class BlogPost(models.Model):
title = models.TextField()
slug = models.SlugField(unique=True)
content = models.TextField(null=True, blank=True)
mysite/mysite/urls.py
from blog.views import (
blog_post_create_view,
)
urlpatterns = [
..
path('blog-new', blog_post_create_view),
..
]
mysite/templates/form.html
{% extends "base.html" %}
{% block content %}
{% if title %}
<h1>{{ title }}</h1>
{% endif %}
<form method='POST' action='.'> {% csrf_token %}
{{ form.as_p }}
<button type='submit'>Send</button>
</form>
{% endblock %}
You need to point to right url in action attribute of form.
<form action="/blog-new/" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit">
</form>
I think it's not necessary in your case but you could also refactor your view to match the docs.
from django.http import HttpResponseRedirect
from django.shortcuts import render
from .forms import SomeForm
def some_view(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = SomeForm(request.POST)
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
# ...
# redirect to a new URL:
return HttpResponseRedirect('/thanks/')
# if a GET (or any other method) we'll create a blank form
else:
form = SomeForm()
return render(request, 'template_name.html', {'form': form})
You need to point to right url in action attribute of form.
That was not actually the solution but something that helped me to figure out what was wrong.
It is not necessary to point to /blog-new/ as . for action will point to the same page, but I have tried with /blog-new/ as action URL and I was surprised to see that /blog-new/ page doesn't exist.
The bug was in mysite/mysite/urls.py for missing a /:
path('blog-new', blog_post_create_view),
It is funny (and annoying) how a symbol like / missing from your code will mess up everything and make you spend hours trying to find a solution as simple as that.
Thank you for your time spend to have a look over my code and try to help me!
I'm trying to get a simple form working. Oddly, other forms I wrote in this app are working fine, but this one wont show the fields. Can anyone tell me what I'm missing? Here are the files
views.py:
def newnote(request, record_id):
if request.method == 'POST':
form = NoteForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/tracker/all/')
else:
form = NoteForm()
return render(request, 'tracker/noteform.html', {'form': form})
models.py
class Note(models.Model):
record = models.ForeignKey(Record, on_delete=models.CASCADE)
note_text = models.CharField('Notes', max_length=2000)
note_date = models.DateField('Date Entered')
forms.py
class NoteForm(forms.Form):
class Meta:
model = Note
fields = ['note_text',
'note_date'
]
template (noteform.html)
<form action="/tracker/newnote/" method="post">
<div id="fields">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit" />
</div>
</form>
One other note, I have commented out the div id called "fields", to rule out CSS as the issue.
Your form is based on form.Form, which doesn't know anything about models, doesn't expect a Meta class, and expects all its fields to be declared manually - since you have not declared any fields, nothing will show on the template.
It should inherit forms.ModelForm instead.
I want the user to upload the profile picture on the profile page but it is not storing it in the media/documents folder, and yes, I have put enctype="multipart/form-data" in the html form and the method is post. I'm new to django so please provide a simple solution
models.py
class User(models.Model):
first_name=models.CharField(max_length=20)
last_name=models.CharField(max_length=20)
username=models.CharField(max_length=25, primary_key=True)
password=models.CharField(max_length=15)
email_id=models.CharField(max_length=30, default='NULL')
profile_pic=models.ImageField(upload_to='profilepics/%Y/%m/%d/',height_field=200,width_field=200,default='')
forms.py
class ProfilePicForm(forms.ModelForm):
class Meta:
model=User
fields=['username','profile_pic']
views.py
def upload(request):
if request.method == 'POST':
username=request.POST['username']
m=User(username=username)
m.profile_pic=request.FILES['profile_pic']
m.save()
return render(request,'LoginPage/done.html')
else:
pic=ProfilePicForm()
return render(request,'AfterLogin/profile.html')
html file
<form method="POST" enctype="multipart/form-data" action="{% url 'LoginPage:upload' %}">
{% csrf_token %}
<p>Upload your profile photo</p><br>
<input id="id_image" type="file" class="" name="image">
<input type="hidden" name="username" value="{{ username }}">
<input type="submit" value="Submit"/>
</form>
Have a look at this:
Need a minimal Django file upload example
Also, try sharing the error you are getting when trying to upload picture.
I think it would be better for you to use the standard User model created by Django which already has the fields first_name, last_name, username, password and email. Then you create a new model with a OneToOneField with the model user.
If the image uploads and if you get a 404 when going directly to the image url when running the server, then you have forgotten to serve the image, which you have to do when you are in production phase.
urlpatterns = [
...patterns...
]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Something like this should work:
modles.py
from django.contrib.auth.models import User
class UserPicture(models.Model):
user = models.OneToOneField(User, on_delete = models.CASCADE)
picture = models.ImageField(upload_to='...')
forms.py
class ProfilePicForm(forms.ModelForm):
class Meta:
model = UserPicture
fields=['profile_pic']
views.py
def your_view(request):
...
if request.method == 'POST':
form = UserPicture(request.POST, request.FILES)
if form.is_valid():
userprofile = form.save()
userprofile.user = request.user
userprofile.save()
...
You don't have to define own User model since Django has it's own: https://docs.djangoproject.com/en/1.10/ref/contrib/auth/#user-model
And as Jonatan suggested - post error code. If there's none, remove this try ... except: pass.
Django newb here, but I'm learning.
Problem Statement
Input fields not rendering in html template.
Output in Browser
True
| Submit Button |
Relevant Code
forms.py
from django import forms
from django.db import models
class PostNotes(forms.Form):
clientid = models.IntegerField()
notetext = models.CharField(max_length=1000)
-
views.py
def post_form_notes(request):
if request.method == 'GET':
sawit = True
form = PostNotes(initial={'notetext':'This is a sample note'})
else:
sawit = False
pass
return render(request, 'clientadmin/post_form_notes.html', {
'form': form,
'sawit': sawit,
})
-
post_form_notes.html
{{ sawit }}
<form action="" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
Troubleshooting Already Done
I have backed out a fair amount of the code (specifically if I see a
POST) request from the browser. No change.
I have also included a variable to ensure I am seeing the GET request and also the template variables are working. I get output of True.
Simplified the Form Class as much as possible.
I modified the forms.py to use the model I already had for the DB.
forms.py:
from django.forms import ModelForm
from clientadmin.models import notes
class PostNotes(ModelForm):
class Meta:
model = notes
fields = ['notedate', 'notetext']
I also modified the views.py to not set an initial value, so the function uses the following instead of what was asked.
models.py:
def post_form_notes(request):
if request.method == 'GET':
form = PostNotes()
else:
pass
return render(request, 'clientadmin/post_form_notes.html', {
'form': form,
})
Hope this helps someone that was having the same problem I was...
Reference the following URL for further information: https://docs.djangoproject.com/en/1.10/topics/forms/modelforms/
I am working on an app that has a section with with a file upload form for .txt fiels. I would like for the current user that is uploading the file to be added along with the file and the file name. Currently, I can do this successfully in the admin section but I just cant get it to save via the form itself. Any Ideas?
Here are the models:
class UploadedTextFile(models.Model):
file = models.FileField(upload_to="textfiles")
filename = models.CharField(max_length = 50)
username = models.ForeignKey(User, blank=True, null=True)
class UploadedTextFileForm(ModelForm):
class Meta:
model = UploadedTextFile
fields = ['file', 'filename']
Here is my view:
def inputtest(request):
#response for file being submited
if request.method == "POST":
form = UploadedTextFileForm(request.POST)
if form.is_valid():
new_form = form.save(commit=False)
new_form.username = request.user
new_form.save()
return render(request, 'about.html')
inputtest = UploadedTextFileForm()
return render(request, 'failed.html', {'inputtest': inputtest})
else:
inputtest = UploadedTextFileForm()
return render(request, 'inputtest.html', {'inputtest': inputtest})
Here is my html:
{% extends 'base.html' %}
{% block content %}
<form method="post">{% csrf_token %}
{{ inputtest.as_p }}
<input type="submit" value="Submit" />
</form>
{% endblock content %}
Doing it in the view (as you've shown) is the right way to do this. Most likely you're having problems because you've left username as a field on the form, and because the FK model field doesn't have blank=True set the form requires the field to be provided. You should explicitly declare just the subset fields that you want to accept user input for in the form's Meta class.
class UploadedTextFileForm(ModelForm):
class Meta:
model = UploadedTextFile
fields = ['file', 'filename']
I am not sure why you're rendering a different template when the form is not valid, but no matter what you're not providing the form object in the context. This means that you'll never see any errors the form detects, which is probably what's happening with this code - you're not seeing the error that username is not provided.