I am new to django and trying to show a form in an html file and I don't see the fields when I get to this particular page on my browser. Anybody has an idea why?
Here is the html file : In which I can see everything but the form showing up
add_device.html
{% extends 'layout/layout1.html' %}
{% block content %}
<form action = "userprofile/" method = "post">
{% csrf_token %}
{{ form }}
<input type = "submit" value = "Submit"/>
</form>
{% endblock %}
forms.py
from django import forms
from models import UserProfile
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = ('deviceNb',)
models.py
from django.db import models
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.OneToOneField(User)
deviceNb = models.CharField(max_length = 100)
User.profile = property(lambda u : UserProfile.objects.get_or_create(user = u)[0])
views.py
def user_profile(request):
if request.method == 'POST':
#we want to populate the form with the original instance of the profile model and insert POST info on top of it
form = UserProfileForm(request.POST, instance=request.user.profile)
if form.is_valid:
form.save()
#to go back to check that the info has changed
return HttpResponseRedirect('/accounts/loggedin')
else:
#this is the preferred way to get a users info, it is stored that way
user = request.user
profile = user.profile
#if we have a user that has already selected info, it will pass in this info
form = UserProfileForm(instance=profile)
args = {}
args.update(csrf(request))
args['form'] = form
print(form)
return render_to_response('profile.html',args)
I am pretty sure my url file is ok, since I get to the right urls, my problem is really the form fields not showing up.
Thank you so much!!
You are not handling GET request in your view. Update code of the view as
def user_profile(request):
if request.method == 'POST':
# your existing code
# .....
else : #when its get request
form = UserProfileForm(instance=request.user.profile)
args = {}
args.update(csrf(request))
args['form'] = form
return render_to_response('profile.html',args)
This is a sample code, it can be improved.
The indentation of your view is incorrect. The else block belongs with the if request.method == 'POST' statement, and handles GET requests.
You also need to fix the indentation at the end of the method, so that you return a response for get and post requests. It's better to use render instead of the obsolete render_to_response. This simplifies your code, because you don't need to call args.update(csrf(request)) anymore.
from django.shortcuts import render
def user_profile(request):
if request.method == 'POST':
#we want to populate the form with the original instance of the profile model and insert POST info on top of it
form = UserProfileForm(request.POST, instance=request.user.profile)
if form.is_valid:
form.save()
#to go back to check that the info has changed
return HttpResponseRedirect('/accounts/loggedin')
else:
#this is the preferred way to get a users info, it is stored that way
user = request.user
profile = user.profile
#if we have a user that has already selected info, it will pass in this info
form = UserProfileForm(instance=profile)
args = {}
args['form'] = form
return render(request, 'profile.html', args)
You should handle GET request, too. Try this in your view:
def user_profile(request):
form = UserProfileForm()
if request.method == 'GET':
# handle GET request here
form = UserProfileForm(instance=request.user.profile)
elif request.method == 'POST':
#we want to populate the form with the original instance of the profile model and insert POST info on top of it
form = UserProfileForm(request.POST, instance=request.user.profile)
if form.is_valid:
form.save()
#to go back to check that the info has changed
return HttpResponseRedirect('/accounts/loggedin')
args = {}
args['form'] = form
return render_to_response('profile.html',args)
And in your profile.html, you can do something like this:
{{ form.as_p }}
Related
I'm trying to get a photo to upload and the form is not seeing the file and in the form.errors, it says 'this field is required'. I've tried using picture = request.FILES['picture'] to no avail and have also tried picture = form.FILES['picture'] as well as picture = request.POST.FILES['picture'] and picture = form.cleaned_data.get('picture') What am I missing? Let me know if you need anymore information
template
{% block content %}
<h1>Create {{post_type.title}} Post</h1>
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{form.as_p}}
<button type='submit'>Submit</button>
</form>
{% endblock %}
forms.py
class PicturePostForm(forms.ModelForm):
class Meta:
model = PicturePost
fields = ('description', 'privacy', 'picture', 'categories')
views.py
#login_required()
def picture_post(request):
"""
Creates new picture post
"""
if request.method == "POST":
form = PicturePostForm(request.POST)
print("is post")
if form.is_valid():
print("is valid") # this never gets printed because of the 'this field is required' error
author = request.user
content = form.cleaned_data['description']
category = form.cleaned_data['categories']
picture = form.cleaned_data['picture']
privacy = form.cleaned_data['privacy']
p_post = PicturePost(author=author, description=content, categories=category, picture=picture,privacy=privacy )
p_post.save()
#redirect to last page
return redirect('home')
else:
l = []
for i in form.errors.keys():
l.append(form.errors[i])
return HttpResponse(l)
else:
post_type = 'picture'
form = PicturePostForm()
return render(request, 'create_post.html', {'form': form, 'post_type': post_type})
The corresponding model field
picture = models.ImageField(upload_to=f'profiles/{User}_gallery', max_length=255)
Fixed it by replacing form = PicturePostForm(request.POST) with form = PicturePostForm(request.POST, request.FILES)
I have tried to complete the code before, please following
views
#login_required()
def picture_post(request):
"""
Creates new picture post
"""
form = PicturePostForm(request.POST or None, request.FILES or None)
if request.method == "POST":
if form.is_valid():
# instance new object p_post (this best practice if using forms.ModelForm)
# commit=False (to save data on ram/memory device without database/hardrive)
p_post = form.save(commit=False)
# assign author attribute from thr current user session
p_post.author = request.user
# commit=True to move/save data from memory to harddrive
p_post.save() # p_post.save(commit=True)
return redirect('home')
else:
l = []
for i in form.errors.keys():
l.append(form.errors[i])
return HttpResponse(l)
post_type = 'picture'
return render(request, 'create_post.html', {'form': form, 'post_type': post_type})
I am unable to see pre-existing form data when updating. The forms work fine, after submitting the database is updated, but in order to submit the user must enter all form data (including data that will not be updated). While reentering, the previous data is not visible. Is there a way to display the current data of the model instance being updated in the form fields?
Forms:
UpdateSomethingForm(forms.ModelForm):
class Meta:
model = Something
fields = ['field1', 'field2', 'field3']
Views:
def update_something(request, object_pk):
form = UpdateSomethingForm()
context_dict = {}
try:
instance = Something.objects.get(pk=object_pk)
context_dict['instance'] = instance
except Something.DoesNotExist:
context_dict['instance'] = None
if request.method == 'POST':
form = UpdateSomethingForm(request.POST, instance=instance)
if form.is_valid():
form.save(commit=True)
return HttpResponseRedirect('/home')
else:
print(form.errors)
context_dict['form'] = form
return render(request, 'form.html', context=context_dict)
Html:
<form role="form" method="post">
{% csrf_token %}
{{ form|bootstrap }}
<div class="form-group">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
You passed the instance argument on POST, but not on GET.
form = UpdateSomethingForm(instance=instance)
in full:
def update_something(request, object_pk):
try:
instance = Something.objects.get(pk=object_pk)
except Something.DoesNotExist:
instance = None
if request.method == 'POST':
form = UpdateSomethingForm(request.POST, instance=instance)
if form.is_valid():
form.save()
return HttpResponseRedirect('/home')
else:
form = UpdateSomethingForm(instance=instance)
context_dict = {'form': form, 'instance': instance}
return render(request, 'form.html', context_dict)
The main problem is that you construct an empty Form, even if the instance can be found. But you make the view rather "chaotic" in the first place.
Probably a more readable view is:
def update_something(request, object_pk):
context_dict = {}
try:
instance = Something.objects.get(pk=object_pk)
except Something.DoesNotExist:
instance = None
context_dict['instance'] = instance
if request.method == 'POST':
form = UpdateSomethingForm(request.POST, instance=instance)
if form.is_valid():
form.save(commit=True)
return redirect('view_name')
else:
form = UpdateSomethingForm(instance=instance)
context_dict['form'] = form
return render(request, 'form.html', context=context_dict)
Here we ensure that the instance variable is always defined, also in the case the except body is "firing".
Furthermore it is probably better to use a redirect(..) and pass the name of the view over an URL, since if you change the URL of that view, this will still work.
Possibly a newbie question, so please bear with me.
I have a Django form that edits a certain instance of a Model. I am using Modelforms. I am able to edit the instance but I am not able to see the content of instance that I want to edit.
I am learning django right now using video tutorials and in the tutorial adding instance=instance to ModelForm instance and then using form.as_p the values were populated in the input box.
In my case when I got to edit url my input fields are blank. However, whatever I write in new blank form gets updated to that object. What could have been wrong here? I am stuck at this point for 4 days so this question is a very desperate one :)
My form class:
from django import forms
from .models import Entry
class EntryForm(forms.ModelForm):
class Meta:
model = Entry
fields = ['name','type', 'date', 'description']
My Model:
from django.db import models
class Entry(models.Model):
name = models.CharField(max_length=200)
type = models.CharField(max_length= 200)
date = models.DateTimeField()
description = models.TextField()
My views look like this :
def update(request,pk):
instance = get_object_or_404(Entry,pk=pk)
if request.method == 'POST':
form = EntryForm(request.POST or None,instance=instance )
if form.is_valid():
instance =form.save(commit=False)
instance.save()
return HttpResponseRedirect('/')
else:
form = EntryForm()
return render(request, "form.html", {"name":instance.name,'instance':instance,'form': form})
Form template :
<form method="POST">
{% csrf_token %}
{{form.as_p}}
<button class="btn btn-success" type='submit'>Submit</button>
</form>
You are not passing the instance for the second case. Update your views.py to this.
def update(request,pk):
instance = get_object_or_404(Entry,pk=pk)
if request.method == 'POST':
form = EntryForm(request.POST or None,instance=instance )
if form.is_valid():
instance =form.save(commit=False)
instance.save()
return HttpResponseRedirect('/')
else:
form = EntryForm(instance=instance)
return render(request, "form.html", {"name":instance.name,'instance':instance,'form': form})
Django 2.0
Python 3.6
I am having trouble with a Django form that is not saving the file that is selected through the form; whenever you select a file to upload, I receive the message "This Field is Required.".
I placed a blank=True and a null=True in the Model FileField to get rid of the same, but whenever I attempt to load the html, I get this error: "The 'copydoc' attirbute has no file associated with it."
I would like for a user to be able to log in, create an entry and upload a file along with said entry. Why doesn't the DB accept the file from the form?
Thank you.
views.py:
from django.shortcuts import render, redirect
from .models import notarizer, CustomUser, notarizerCreateForm
# from .forms import notarizerCreateForm
# Create your views here.
def home(request):
t = 'home.html'
return render(request, t)
def page1(request):
t = 'log1/page1.html'
if request.user.is_authenticated:
logger = notarizer.objects.filter(userziptie=request.user).order_by('-date')
return render(request, t, {'logger': logger})
else:
return redirect(home)
def create_entry(request):
createPath = 'log1/create_entry.html'
if request.method == 'POST':
if request.method == 'FILES':
form = notarizerCreateForm(request.POST, request.FILES)
if form.is_valid():
instance =notarizerCreateForm(
file_field=request.FILES['file']
)
instance.save()
else:
print(form.errors)
else:
form = notarizerCreateForm(request.POST)
if form.is_valid():
form.save()
else:
print(form.errors)
else:
form = notarizerCreateForm()
return render(request, createPath, {'form': form})
create_entry.html:
{% extends "base.html" %}
{% block placeholder1 %}
<div class="form-holder">
<form name="form" enctype="multipart/form-data" method="POST"
action="/create_entry/" >
{% csrf_token %}
{{ form.as_table }}
<input type="submit"/>
</form>
</div>
{% endblock %}
models.py:
from django.db import models
from users.models import CustomUser
from django.forms import ModelForm
# Create your models here.
class notarizer(models.Model):
date = models.DateField(auto_now_add=True)
docName = models.CharField(max_length=25, null=False)
describe = models.TextField(max_length=280)
signee = models.CharField(max_length=25, null=False)
signeeDets = models.TextField(max_length=280)
copydoc = models.FileField(upload_to='users/', blank=True, null=True)
userziptie = models.ForeignKey('users.CustomUser',
on_delete=models.DO_NOTHING, null=True)
def __str__(self):
return "{0}\n{1}\n{2}\n{3}\n{4}\n{5}\n{6}".format(
self.pk,
self.date,
self.docName,
self.describe,
self.signee,
self.signeeDets,
self.userziptie
)
class notarizerCreateForm(ModelForm):
class Meta:
model = notarizer
fields = ['docName','describe','signee','signeeDets', 'copydoc']
There are some things that make the view workflow very weird:
you check request.method, first you check if it is a 'POST' which is a good idea, but then you check if it is 'FILES', there is no HTTP method named FILES, there are only GET, POST, PATCH, PUT, OPTIONS, etc.;
you call form.is_valid() which is again what should happen, but then you create a new Form, and only pass it a single parameter; and
in case of a POST you should not return a rendered page, but redirect to a GET page (for example showing the result). The workflow is typically Post-redirect-get, since if the user refreshes their browser, we do not want to make the same post again.
The workflow should look like:
def create_entry(request):
createPath = 'log1/create_entry.html'
if request.method == 'POST': # good, a post (but no FILES check!)
form = notarizerCreateForm(request.POST, request.FILES)
if form.is_valid():
instance = form.save()
else:
# you probably want to show the errors in that case to the user
print(form.errors)
# redirect to a page, for example the `page1 view
return redirect(page1)
else:
form = notarizerCreateForm()
return render(request, createPath, {'form': form})
I have a model form to display a textbox for the listname and a image for the user to upload. I am wanting the username to be pulled from the current request. When I currently hit submit, I am getting an "NOT NULL constraint failed: pages_newlist.user_id". I did a little experiment and when I include the field for the user to select their username from a list of all the users, it submits the data with no issues. Obviously that would be a huge flaw if I allowed the user to select which account to submit the data to, but my issue is that the form isn't auto populating the username field with the current request. My second issue is, when I do select admin as a user, the list posts fine, but the image url doesn't attach itself to the submission.
View
def control_panel(request, username):
context = RequestContext(request)
if username == request.user.username:
if request.user.is_authenticated():
user = User.objects.get(username=username)
lists = request.user.newlist_set.all()
listitems = request.user.newlistitem_set.all()
form = NewListForm(request.POST or None)
if form.is_valid():
save_it = form.save(commit = False)
save_it.save();
return render_to_response('controlpanel.html', {'form': form, 'lists': lists,'listitems':listitems,}, context)
else:
return render_to_response('login.html', {}, context)
else:
return render_to_response('controlpanel.html', {}, context)
Form
class NewListForm(forms.ModelForm):
class Meta:
fields = ('list_name', 'picture')
model = newlist
Fixing Image Not Posting
Needed to add enctype to template:
<form method = "POST" action = "" enctype="multipart/form-data">
{% csrf_token %}
{{ form }}
</form>
Populating User To Current User
Needed to just assign user for the entry to request.user
form = NewListForm(request.POST, request.FILES)
if form.is_valid():
save_it = form.save(commit = False)
save_it.user = request.user
save_it.save()