django template form not saving data - python

I have a template form and trying to save some data. Upon clicking on the submit button the page just refreshes and nothing gets saved to the database. I don't get any errors on anything.
template
<form action="" method="post" id="salesform">
{% csrf_token %}
<input type="name" class="form-control" id="name" placeholder="Name">
<input type="clinic" class="form-control" id="clinic_name" placeholder="Clinic">
<input type="phone" class="form-control" id="phone" placeholder="Phone">
<input type="email" class="form-control" id="email" placeholder="Email">
<button id="sub" type="submit" class="btn btn-default">Submit</button>
</form>
forms.py
class LeadForm(forms.ModelForm):
name = forms.CharField(max_length=250, required= True,widget=forms.TextInput())
clinic_name = forms.CharField(max_length=250, required= True,widget=forms.TextInput())
phone = forms.CharField(max_length=8, required= True,widget=forms.TextInput(attrs={'type':'number'}))
email = forms.CharField(max_length=250, required= False, widget=forms.TextInput())
class Meta:
model = Lead
fields = ("clinic_name","phone")
views.py
def add_doc_info(request):
d = getVariables(request,dictionary={'page_name': "Doctors",
'meta_desc' : "Sign up "})
if request.method == "POST":
SalesForm = LeadForm(request.POST)
if SalesForm.is_valid():
name = SalesForm.cleaned_data['name']
clinic_name = SalesForm.cleaned_data['clinic_name']
phone = SalesForm.cleaned_data['phone']
email = SalesForm.cleaned_data['email']
#Saving to database
lead = Lead(name=name, clinic_name=clinic_name, phone=phone, email=email)
lead.save()
else:
SalesForm = LeadForm()
return render(request, 'm1/add_doc_info.html', d, context_instance=RequestContext(request))
models.py
class Lead(models.Model):
name = models.CharField(max_length=1300)
clinic_name = models.CharField(max_length=1300)
phone = models.IntegerField()
email = models.EmailField(blank = True)
submitted_on = models.DateField(auto_now_add=True)
def __unicode__(self):
return u"%s %s" % (self.clinic_name, self.phone)

Almost certainly the form is not valid, but you're not using it in your template so there is no way for it to display errors, or redisplay itself with partially-filled fields.
The Django documentation is fairly explicit on this, so I don't know why you have done something different. Pass the form into your context:
d['form'] = SalesForm
return render(request, 'm1/add_doc_info.html', d)
and use it in the template:
{{ form.errors }}
<form action="" method="post" id="salesform">
{% csrf_token %}
{{ form.name }}
{{ form.clinic_name }}
{{ form.phone }}
{{ form.email }}
<button id="sub" type="submit" class="btn btn-default">Submit</button>
</form>
(Note also you've unnecessarily defined all the fields explicitly in the form, but also stated you are only using two of them in the meta class; also your is_valid block is mostly unnecessary as you can just call form.save() directly. Again, all this is shown fully in the documentation.)

Related

Django Save image without using Django Forms?

I am trying to save the image without using Django forms in the media folder. The image should save in the media\seller_profile folder and its path has to be entered in a database like seller_profile\abc.png but somehow I am getting only abc.png missing seller_profile.
Models.py
class SellerProfile(models.Model):
email = models.EmailField(max_length=255, unique=True)
first_name = models.CharField(max_length=255, default=None, null=True)
seller_profile_picture = models.ImageField(upload_to='seller_profile', default="seller_profile/empty_profile.png")
def __str__(self):
return self.email
Views.py
def profile(request):
if request.method == "POST":
profile_data = SellerProfile.objects.filter(email = str(request.user)).update(
first_name = request.POST.get("First name"),
seller_profile_picture = request.FILES["seller profile picture"],
)
print("object File --->", request.FILES["seller profile picture"])
return redirect("/seller/profile")
else:
user_data = SellerProfile.objects.filter(email=str(request.user))
if len(user_data) == 0:
SellerProfile.objects.create(email = str(request.user))
data_entered = {"First name": "Value not Provided"}
else:
data_entered = dict()
data_entered["First name"] = user_data[0].first_name
return render(request, "seller/profile.html", {"data_entered":data_entered})
seller/profile.html
{% extends 'general/layout.html'%}
{% block body %}
<div class="container">
<div class="jumbotron">
<form method="post" enctype=multipart/form-data>
{% csrf_token %}
{% for attribute, placeholder in data_entered.items %}
<div class="form-group">
<dt><label for="{{attribute}}">{{attribute}}</label>
<dd><input class="form-control" id="{{attribute}}" name="{{attribute}}"
type="text" placeholder="{{placeholder}}" required>
</dd>
</div>
{% endfor %}
<dt><label for="seller profile picture">Profile Picture</label>
<dd><input class="form-control" id="seller profile picture" name="seller profile picture"
type="file" required>
</dd>
</dt>
<div class="form-group text-center">
<p>
<input class="btn btn-primary " type="submit" value="Update">
</p>
</div>
</form>
</div>
</div>
{% endblock%}
Updating Models.py by referring link. According to this solution update do not call save.
def profile(request):
if request.method == "POST":
print("get ", SellerProfile.objects.get(email = str(request.user)))
print("type get ", type(SellerProfile.objects.get(email = str(request.user))))
profile_data = SellerProfile.objects.get(email = str(request.user))
profile_data.email = str(request.user),
profile_data.first_name = request.POST.get(seller_char_attribute[0]),
profile_data.seller_profile_picture = request.FILES["seller profile picture"],
profile_data.save()
but this gives me error as follow
Virtialenv\lib\site-packages\django\db\models\fields\files.py",line 286, in pre_save
if file and not file._committed:
AttributeError: 'tuple' object has no attribute '_committed'
You've left trailing commas at the end of some of the lines where you're assigning values to the profile_data object. Those commas mean that tuples will be assigned rather than the values you intend:
profile_data.email = str(request.user),
profile_data.first_name = request.POST.get(seller_char_attribute[0]),
profile_data.seller_profile_picture = request.FILES["seller profile picture"],
Removing the trailing commas from the above lines should resolve.
In your profile function def profile(request):
where you are dealing with image
profile_data.seller_profile_picture = request.FILES["seller profile picture"],
Instead of this you have to use request.FILES.get()
An instead of passing the image name in list type ["seller profile picture"]you have to give only image name
So at last your line will look like this
profile_data.seller_profile_picture = request.FILES.get("seller profile picture")

How can I allow users to edit their profiles in Django?

I have a model in models.py like this:
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.DO_NOTHING)
phone_number = models.CharField(max_length=50, default='')
Birthday = models.CharField(max_length=50, default='')
city = models.CharField(max_length=50, default='')
school = models.CharField(max_length=100, default='')
course = models.CharField(max_length=50, default='')
I want to allow my users to make edits, so I made a function like this in my views.py:
if request.method == 'POST':
profil = UserProfile.objects.get(user=request.user)
profil.phone_number = models.CharField(max_length=50, default='')
profil.Birthday = models.CharField(max_length=50, default='')
profil.city = models.CharField(max_length=50, default='')
profil.school = models.CharField(max_length=100, default='')
profil.course = models.CharField(max_length=50, default='')
profil.save()
return redirect('profile')
return render(request, 'edit_profile.html')
My template is:
<form action="." method="post">
{% csrf_token %}
Phone Number:
<input type="text" name="phone_number" value="{{ profil.phone_number }}" /><br />
Birthday:
<input type="text" name="Birthday" value="{{ profil.Birthday }}" /><br />
city:
<input type="text" name="city" value="{{ profil.city }}" /><br />
school:
<input type="text" name="school" value="{{ profil.school }}" /><br />
course:
<input type="text" name="course" value="{{ profil.course }}" /><br />
<input type="submit" value="Save Changes" name="save" />
<input type="reset" value="Cancel" name="cancel" />
<br/>
</form>
I do not know why, but after filling the form I get an error saying page not found. And if I check the existing user profile nothing got updated. Help please.
you have an error
profil = UserProfile.objects.get(user=request.user)
profil.phone_number = models.CharField(max_length=50, default='')
you get an UserProfile object and then instead of saving str into phone_number you try to save an object models.CharField.
use ModelForm to achieve what you need.
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = '__all__'
then in your view you can use:
userprofile_form = UserProfileForm(request.POST if request.POST else None, instance = UserProfile.objects.get(user=request.user))
if request.method == 'POST':
if form.is_valid():
form.save()
return redirect('profile')
return render(request, 'edit_profile.html', context={'userprofile_form': userprofile_form)
and in html use:
<form action="." method="post">
{% csrf_token %}
Phone Number: {{ userprofile_form.phone_number }}
Birthday: {{ userprofile_form.Birthday }}
city: {{ userprofile_form.city }}
school: {{ userprofile_form.school }}
course: {{ userprofile_form.course }}
<input type="submit" value="Save Changes" name="save" />
<input type="reset" value="Cancel" name="cancel" />
<br/>
</form>
or just
<form action="." method="post">
{% csrf_token %}
{{ userprofile_form }}
<input type="submit" value="Save Changes" name="save" />
<input type="reset" value="Cancel" name="cancel" />
<br/>
</form>
if you want to use upload files, don't forget to put your files into form you can do it
UserProfileForm(request.POST, request.FILES, instance = UserProfile.objects.get(user=request.user))
and in html you need to put <form enctype="multipart/form-data" method="post" action="...">
Reproduce these steps, you might need slight modifications:
1. Create a UserEditForm
in forms.py
from .models import UserProfile
from django.forms import ModelForm
class UserEditForm(ModelForm):
class Meta:
model = UserProfile
fields = '__all__' # or ['phone_number', 'Birthday', 'city', 'only_fields_you_want_to_edit']
2. Create a View:
in views.py
from django.shortcuts import render, HttpResponseRedirect, get_object_or_404
from django.urls import reverse
from django.forms.models import model_to_dict
from .models import UserProfile
from .forms import UserEditForm
def userEdit(request, user_id):
user = get_object_or_404(Question, pk=user_id)
if request.method == "GET":
form = UserEditForm(initial=model_to_dict(user))
return render(request, 'yourapp/useredit_form.html', {'form':form)
elif request.method == "POST":
form = UserEditForm(request.POST, instance=user)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('user_profile', kwargs={'uid':user.id}))
else:
return HttpResponseRedirect(reverse('some_fail_loc'))
3. Create template
in yourapp/useredit_form.html
<form method="POST">
{% csrf_token %}
{{form}}
<button type="submit">Submit</button>
</form>
4. Set a URL:
in urls.py
urlpatterns += [
path('edit_user/<int:user_id>/', views.userEdit, name='user_edit'),
]
Now try visiting yourapp.com/edit_user/1. You are good to go. :D

form.is_valid always return false

form.is_valid in views.py always return false. I have used Django forms to create a form and html to implement it.
I will upload this photo to imgur using imgurpython later, but first this should work.
views.py
def upload_view(request):
usr = check_validation(request)
if usr:
if request.method == "GET":
form = PostForm()
return render(request, 'upload.html', {'form': form})
elif request.method == "POST":
form = PostForm(request.POST, request.FILES)
if form.is_valid():
pic = form.cleaned_data.get('image')
title = form.cleaned_data.get('caption')
post = PostForm()
post.user = usr
post.caption = title
post.image = pic
post.save()
return redirect('feed/')
else:
return render(request, 'upload.html', {'error_msg' : "Invalid Inputs"})
else:
return redirect('/login/')
models.py
class Post(models.Model):
user = models.ForeignKey(User)
image = models.FileField(upload_to='user_images')
caption = models.CharField(max_length=240)
image_url = models.CharField(max_length=255)
created_on = models.DateTimeField(auto_now_add=True)
forms.py
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ['user', 'image', 'caption']
template - upload.html
<form method="post" enctype="multipart/form-data" class="loginbox" style="margin-top:200px;">
{% csrf_token %}
<p class="text-16">Upload to aperture.</p>
{{ form }}
<p class="text-16">{{ error_msg }}</p>
<input class="login-btn" type="submit" value="Upload"/>
</form>
Try this,
<form method="post" enctype="multipart/form-data" class="loginbox" style="margin-top:200px;">
{% csrf_token %}
{{ form }}
<input class="login-btn" type="submit" value="Upload"/>
</form>
If this doesn't work, print the request.POST and request.FILES then update the answer with the contents.
Your context has only one variable named form so you have to use that only to make your form work.
<form method="post" enctype="multipart/form-data" class="loginbox" style="margin-top:200px;">
{% csrf_token %}
<p class="text-16">Upload to aperture.</p>
<input type="file" accept="image/*" value="{{ form.image }}" name="image" class="login-btn"/><br/>
<input placeholder="Caption" class="input-default all-curve" rows="3" value="{{ form.caption }}" name="caption" />
<p class="text-16">{{ form.error_msg }}</p>
<input class="login-btn" type="submit" value="Upload"/>
</form>

I have a bound ModelForm that is invalid

I am trying to create a ModelForm that links to an external database, and when you submit the form the external database gets updated. The problem comes when I check the validity of the form, it is invalid.
I have done some researching into this and found the most common problem was that the form is not bound, but when I use print(form.non_field_errors) I get:
<bound method BaseForm.non_field_errors of <EmailForm bound=True, valid=False, fields=(subject;body;name;altsubject;utm_source;utm_content;utm_campaign)>
models.py:
class MarketingEmails(models.Model):
messageid = models.AutoField(db_column='column1', primary_key=True)
subject = models.CharField(db_column='column2', max_length=2000)
body = models.TextField(db_column='column3') #using a text field as there is no maximum length
name = models.CharField(db_column='column4', max_length=25)
altsubject = models.CharField(db_column='column5', max_length=2000)
utm_source = models.CharField(db_column='column6', max_length=25)
utm_content = models.CharField(db_column='column7', max_length=25)
utm_campaign = models.CharField(db_column='column8', max_length=25)
class Meta:
managed = False
db_table = ''
forms.py:
class EmailForm(forms.ModelForm):
class Meta:
model = MarketingEmails
fields = ['messageid','subject','body','name','altsubject','utm_source','utm_content','utm_campaign']
views.py:
def emailinfo(request, pk):
if request.session.has_key('shortname'):
shortname = request.session['shortname']
rows = get_object_or_404(MarketingEmails, pk=pk)
if request.method == 'POST':
form = EmailForm(request.POST)
print(form.errors)
print(form.non_field_errors)
if form.is_valid():
form.save()
print("form is valid")
return redirect('marketingemails:emailinfo', pk = rows.messageid)
return render(request, 'marketingemails/emailinfo.html',{'shortname': shortname, 'rows': rows})
else:
return HttpResponseRedirect(reverse('common:login'))
urls.py:
app_name = 'marketingemails'
urlpatterns = [
url(r'^marketing/emails/(?P<pk>[0-9]+)/$', marketingviews.emailinfo, name='emailinfo'),
]
html:
<form method="POST" class="post-form" action ="">
{% csrf_token %}
<label for="exampleTextarea">Name</label>
<textarea class="form-control" id="exampleTextarea" rows="1">{{ rows.name }}</textarea>
<label for="exampleTextarea">Subject</label>
<textarea class="form-control" id="exampleTextarea" rows="1">{{ rows.subject }}</textarea>
<label for="exampleTextarea">Alternative Subject</label>
<textarea class="form-control" id="exampleTextarea" rows="1">{{ rows.altsubject }}</textarea>
<label for="exampleTextarea">Body</label>
<div class="ibox-content no-padding">
<div class="summernote">
{{ rows.body }}
</div>
</div>
<label for="exampleTextarea">utm_source</label>
<textarea class="form-control" id="exampleTextarea" rows="1">{{ rows.utm_source }}</textarea>
<label for="exampleTextarea">utm_content</label>
<textarea class="form-control" id="exampleTextarea" rows="1">{{ rows.utm_content }}</textarea>
<label for="exampleTextarea">utm_campaign</label>
<textarea class="form-control" id="exampleTextarea" rows="1">{{ rows.utm_campaign }}</textarea>
<button type="submit" class="save btn btn-default">Save</button>
</form>
Your HTML form doesn't name the fields so the form can't get them. You want to use the form for rendering too : https://docs.djangoproject.com/en/1.11/topics/forms/#working-with-form-templates

set a Boolean when submitted in django

I want to set a Boolean field is_rep in a retest model to true when the retest form is submitted.
Now it is just get added up in a retest model.
Because I want to trigger other events when the request is submitted.
My code
models.py
class Retest(models.Model):
semester = models.ForeignKey(Semester)
dept = models.ForeignKey(Departement)
batch = models.ForeignKey(Batch)
date = models.DateField(default=0)
subject = models.ForeignKey(Subject)
name = models.CharField(max_length=50)
admnno = models.CharField(max_length=50)
reason = models.CharField(max_length=50)
proof = models.CharField(max_length=200)
is_hod = models.BooleanField(default=False)
is_principal = models.BooleanField(default=False)
notify = models.BooleanField(default=False)
is_sure = models.BooleanField(default=False)
is_rep = models.BooleanField(default=False)
def get_absolute_url(self):
return reverse( 'retest:retestform')
def __str__(self):
return self.name
urls.py
url(r'^retest/retestform/$',login_required(views.RetestCreate.as_view()), name='retestform')
views.py
class RetestCreate(CreateView):
model = Retest
fields = ['semester', 'dept', 'batch', 'date', 'subject', 'name', 'admnno', 'reason', 'proof', 'is_sure']
template
<form class="form_horizontal" action="" method="post" enctype="multipart/form-data" >
{% csrf_token %}
{% include 'retest/form-template.html' %}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-success">Submit</button>
</div>
</div>
</form>
If you want to set the boolean field to true, when the form is submitted, you just have to handle it in the view.
Submit the form and before saving it into the database just set the is_rep = true.
is_rep is a field which is in the model, but not used in the form.
So, if you want to change that then you have to manually write a view for it. Try to use base view instead of generic views to understand the workflow of the views and forms.
I'd recommend using something like this:
class RetestView(View):
def get(self, request, *args, **kwargs):
..............
return render(request, self.template, {"some_context"}
def post(self, request, *args, **kwargs):
form_data = your_form(request.POST)
if form_data.is_valid():
new_object = form_data.save(commit=False)
new_object.is_rep = True
new_object.save()
return render(request, self.template, {"some...context"})
Hope you got what you were looking for..!
form_template
{% for field in form %}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<span class="text-danger small">{{ field.errors }} </span>
</div>
<label class="control-label col-sm-2">{{ field.label_tag }} </label>
<div class ="col-sm-12">
<div class="form-control">
{{ field }}</div></div>
</div>
{% endfor %}

Categories