I am creating a newsletter application that requires the user's name and email. However each time I input form data . no change is reflected in the database
models.py
class NewUsers(models.Model):
name = models.CharField(max_length=50)
email = models.EmailField()
date_added = models.DateField(auto_now_add= True)
class Meta:
verbose_name = "NewUser"
verbose_name_plural = "NewUsers"
def __str__(seld):
return self.email
views.py
def newsletter_subscribe(request):
if request.method == 'POST' :
form = NewUserForm(request.POST)
if form.is_valid():
name = form.cleaned_data['name'] #variable to store cleaned data
email = form.cleaned_data['email']
instance = NewUsers(name= name, email = email)
instance.save()
if NewUsers.objects.filter(email = instance.email).exists():
print("Your email is already added to our database")
else:
instance.save()
print("Thank you for subscribing")
else:
form = NewUserForm()#display empty form
context = {'form':form}
template = "index.html"
return render(request ,template ,context )
Here is my template code
template
<form method="post" action="{%url 'subscribe'%}">
{% csrf_token %}
<label for="id_email_field">Name:</label> <input type="text"
name=""
required="" id="">
<label for="id_email_field">E-mail:</label> <input type="email"
name="email_field"
required="" id="id_email_field">
<button id="id_submit" name="submit" value="Subscribe"
type="submit">Subscribe
</button>
</form>
A few things I notice: First, a view must return an HttpResponse object. E.g., I recommend reading up here: https://docs.djangoproject.com/en/2.1/topics/http/views/ and here: https://docs.djangoproject.com/en/2.1/topics/forms/
So, since apparently you didnt get an error thrown at you pointing to this fact, I assume that the request.method never has been equal "POST". Maybe you could try to find out if this is the case? Therefore: could you also provide your template code, please.
Next, your code in the if form.is_valid() is quite contrived. The most natural thing to do here is just calling form.save(). This will create an instance in your db out of the cleaned form-data. In case, you need to do some adjustments, you can extend like this:
instance = form.save(commit=False)
# add some adjustments (instance.foo = bar)
instance.save()
Last, as noted before, you need to return an HttpResponse object which is usually done via
return redirect(url_name, ..)
Edit: since you now added the template code: Try to first let django render the fields for you: https://docs.djangoproject.com/en/2.1/topics/forms/#rendering-fields-manually
and then have a look at the source code of the template. Your name-input-field is missing a name tag and your email-input-field should have name="email" I think. You can django even let the whole form render for you (see docs again...) Without (correct) name tags in the input fields - it will not be possible to send or correctly assign the data inputted by the user.
Related
data cannot be saved in form.I wrote html like
<form action="/app/save" method="POST">
<input id="classname" name="classname">
<input id="score" name="score">
<input id="course" name="course">
<button type="submit">SEND</button>
</form>
in forms.py
from django import forms
from .models import Student
class SaveForm(forms.ModelForm):
class Meta:
model = Student
fields = ("classname", "score", "course")
in views.py
#csrf_exempt
def save(request):
save_form = SaveForm(request.POST or None)
print(save_form.is_valid())
if request.method == "POST" and save_form.is_valid():
item = save_form.save(commit=False)
classname = request.POST.get("classname", "")
score = request.POST.get("score", "")
course = request.POST.get("course", "")
item.classname = classname
item.score = score
item.course = course
item.save()
return render(request, 'index.html')
in models.py
from django.db import models
class Student(models.Model):
classname = models.CharField(max_length=100)
score = models.CharField(max_length=100)
course = models.CharField(max_length=100)
When I run this codes ,put data A in classname& 80 in score&Math in course of html and put SEND button,save method can be called but data cannot be saved.print(save_form.is_valid()) shows False.I really cannot understand why I can't send data.What is wrong in my codes?How should I fix this?
Okay a few things here;
Why is score a charfield? If it's a %, shouldn't it be an int?
Student model doesn't have any foreign keys, so there's really no need to use commit = false in your save.
Creating inputs for each item on your form in html is definitely the long way to do it. The best way to do this in your html is simply to use {{form}}. To do this, you'll need to pass the form as a variable in context in your views.py.
Without being mean, are you very early in to the django beginner tutorial? If so, I would recommend moving forward through that before trying to continue your current project. It'll really help you. Here's what I would suggest as a views.py
def save(request):
if request.method == "POST":
save_form = SaveForm(request.POST)
print(save_form.is_valid())
if(save_form.is_valid()):
save_form.save()
return HttpResponseRedirect('New-destination-URL')
save_form = SaveForm()
context['form'] = save_form
return render(request, context, 'index.html')
and in index.html:
form action="/app/save" method="POST">
{{form}}
</form>
You do it wrong, you have to handle both situations - when you are on page at first time, and time when form is filled with data.
Try to change your views to this :
if request.method == "POST":
save_form = SaveForm(request.POST)
...
else:
save_form = SaveForm()
return render(request, 'index.html', {'save_form': save_form)
and then try to put this in template:
<form action="/app/save" method="POST">
{{ save_form.as_p }}
<button type="submit">SEND</button>
</form>
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 am setting up a simple html page, the page captures the information that the user entered and based on the information that the user entered makes a new page. The problem is that I cant get back the information entered by the user at the backed and I dont understand where I am going wrong.
My views file is setup like this:
def suggestion(request):
if request.method == 'POST':
form = BusinessName(request.POST)
if form.is_valid():
data=form.cleaned_data
context = insert_function_here(data)
return render( request,'mainpage.html', context)
else:
form = BusinessName()
context = {'form':form}
return render( request,'mainpage.html', context)
My forms.py is setup like this:
class BusinessName(forms.Form):
business_name = forms.CharField(widget = forms.HiddenInput(), required = False)
The relevant part of my html is set up like this:
<form id="user_input_form" method="post" action="http://127.0.0.1:8000/textinsighters/suggestion">
Enter Your Business Name : <input type="text" list="browsers" name="browser" id="user_input">
{% csrf_token %}
{{ form }}
<datalist id="browsers">
<option value="Internet Explorer">
<option value="Firefox">
<option value="Chrome">
<option value="Opera">
<option value="Safari">
</datalist>
<button onclick="myFunction()">Submittt</button>
</form>
<script>
function myFunction() {
document.getElementById("id_business_name").value = document.getElementById("user_input").value;
document.getElementById("user_input_form").submit();
}
</script>
I want an auto-completing list so thats why I am creating a form in html. I get the user input, set the value of the Django form field to the value that the user entered and submit it. I should get something back but the variable 'data' in views doesnt contain the user input.
Thanks
You are using a forms.HiddenInput() as the widget and then add the form field yourself. This doesn't work that way. What if you change the field class to TextInput:
class BusinessName(forms.Form):
business_name = forms.CharField(widget = forms.TextInput())
If you're goal is to add custom attributes to the widget, then this can be done by providing an attrs dictionary:
class BusinessName(forms.Form):
business_name = forms.CharField(widget = forms.TextInput(attrs={
'list': 'browser'
}))
Or you could have a look at the django-widget-tweaks package to add attributes in the template.
I am writing simple blog in django and I gotstuck on uploading files.
I want to create template wher user can write post and add multiple files. So firstrly i have created models:
class Post(models.Model):
title= models.CharField(verbose_name=u"post title", max_length=40, blank=False)
body= models.TextField(verbose_name=u"post body", blank=False)
author= models.ForeignKey(User, blank=False)
published= models.DateTimeField(verbose_name=u"data publikacji", blank=True, null=True)
class Add(models.Model):
post=models.ForeignKey(Post)
file=models.FileField(upload_to='adds', verbose_name=u"added files")
and after that i created template which looks like this:
{% block content %}
<div class="col-lg-6 col-md-offset-3">
<form enctype="multipart/form-data" method="post" adction="{% url 'create_post' %}">{% csrf_token %}
{{post_form|crispy}}
<input type="file" name="files" multiple/></br>
<input class="btn btn-success" style="width:100%" type="submit" value="Dodaj post"/>
</form>
</div>
{% endblock %}
after that i wrote simple view which would handle files and post creation:
def create_post(request):
if request.method== 'GET':
post_form=PostForm()
add_form=AddForm()
context={
'post_form': post_form,
}
return render(request, 'create_post.html', context)
else:
post_form=PostForm(request.POST)
if post_form.is_valid():
instance=post_form.save(commit=False)
instance.published=datetime.datetime.now()
instance.author=request.user
instance.save()
# import ipdb
# ipdb.set_trace()
for file in request.FILES.getlist("files"):
add_instance=AddForm()
add_instance.post=instance
add_instance.file=file
if add_instance.is_valid():
add_instance.save()
return redirect(reverse('AllPosts'))
but none of add_instance passes the validation "is_valid". But why?
And the second question is there any way to use Form in template against writing raw input for file? When i use AddForm i can only add one file what is logic.
You problem is that your form is always an unbounded form, which means that it is initialized without data. By data I mean POST or GET data from request or an instance of the model. unbounded form will always fail is_valid() and it doesn't make sense to manually assign anything to a form instance like add_instance = AddForm() then add_instance.post = instance.
django doc explains how to use a form.
You cannot upload multiple files with one single form because each form is a Add model form. You should really use ModelFormSet for your AddForm to add multiple model instances in one submit.
django doc explains how to use ModelFormSet.
By the way, I find the model name Add extremely confusing, consider changing it to Attachment or PostFile or something else.
Edit:
I didn't try it, but if you want one widget for multiple files, you can do this in views:
for upload_file in request.FILES.getlist('files'):
form = AddForm(request.POST, {'file': upload_file})
if form.is_valid():
new_file = form.save(commit=False)
new_file.post = instance
new_file.save()
I have designed an sample registration form and was using it save it to database . I can successfully save an entry to database but the problem is when create an second entry it overrides the first entry
register.html
<form action="/register_process/" method="post">
{% csrf_token %}
<label for="unamefield">Enter Username</label>
<input type="text" name="unamefield">
<label for="unamefield">Enter Password</label>
<input type="password" name="pwdfield">
<input type="submit" value="Register">
</form>
models.py
from django.db import models
class UserRegistration(models.Model):
USER_ID = models.CharField(primary_key=True, max_length=11)
USER_NAME = models.CharField(max_length=50)
PASSWORD = models.CharField(max_length=255, null=False)
class Meta:
db_table = 'USER'
views.py
def register_user(request):
args = {}
args.update(csrf(request))
return render_to_response('register.html', args)
def register_process(request):
if request.method == 'POST':
uname = request.POST.get('unamefield')
pwd = request.POST.get('pwdfield')
obj_userregistration = UserRegistration(USER_NAME=uname, PASSWORD=pwd)
obj_userregistration.save()
return HttpResponseRedirect('<html>Success</html>')
You've made a few errors in defining your model.
First, there is no reason to define your fields IN UPPER CASE. That's very strange.
More importantly, you have defined a USER_ID field as a charfield and set it to be the primary key. But you have not provided any way to actually generate a new value for this field. Unless you have a really good reason, you should not define a manual PK field at all, but let Django add an autoincremented integer field automatically.
But even more importantly than this, you should on no account do what you have done here at all. You are storing your passwords in clear text in the database, opening yourself to all sorts of hacking. Do not ever do this. Django includes a whole authentication framework where this is done properly, and there is absolutely no reason for you to bypass this as you have done. Do not do it.