I want to change the following HTML form:
#transaction.atomic
def Register(request):
if request.method == "POST":
fname = request.POST['first_name']
lname = request.POST['last_name']
mobile = request.POST['mobile']
"""This section replaces multiple characters with blank value
so that the mobile number has nothing except numeric values
"""
rep = ['+', '-', ' ', '.']
for i in rep:
mobile = mobile.replace(i, '')
company = request.POST['company']
email = request.POST['email']
u = User.objects.create_user(mobile, email, '1234', first_name=fname, last_name=lname)
u.save()
p = UserProfile.objects.create(user=u, company=company, mobile=mobile)
p.save()
return HttpResponse("Registration complete! Please head over to the <a href='/login/'>login page</a> to start using your SMS panel.")
return render(request, "message/register.html", {})
Into a Django form mainly because I need to learn how to use them, also I need all the fields to be filled up before the registration completes, I don't want any optional fields. The following is what I've come up with from the documentation.
views.py
#transaction.atomic
def Register(request):
if request.method == "POST":
form = RegisterForm(request.POST)
if form.is_valid():
# I guess this is where I need help. Thanks.
else:
form = RegisterForm()
return render(request, "message/register.html", {'form': form})
register.html
<form method="post" action="">
{% csrf_token %}
{{ form }}
<input type="submit" value="Register"/>
</form>
You can create a form RegisterForm and add the process of cleaning of mobile to clean_mobile function in forms.py. Then in your views.py, you can access all the form data using form.cleaned_data dictionary.
You can do something like below:
forms.py
from django import forms
class RegisterForm(forms.Form):
first_name = forms.CharField(max_length=100)
last_name = forms.CharField(max_length=100)
mobile = forms.CharField()
company = forms.CharField(max_length=100)
email = forms.EmailField()
def clean_mobile(self):
mobile = self.cleaned_data['mobile']
rep = ['+', '-', ' ', '.']
for i in rep:
mobile = mobile.replace(i, '')
return mobile
views.py
#transaction.atomic
def Register(request):
if request.method == "POST":
form = RegisterForm(request.POST)
if form.is_valid():
u = User.objects.create_user(form.cleaned_data['mobile'], form.cleaned_data['email'], '1234', first_name=form.cleaned_data['first_name'], last_name=form.cleaned_data['last_name'])
u.save()
p = UserProfile.objects.create(user=u, company=form.cleaned_data['company'], mobile=form.cleaned_data['mobile'])
p.save()
return HttpResponse("Registration complete! Please head over to the <a href='/login/'>login page</a> to start using your SMS panel.")
else:
form = RegisterForm()
return render(request, "message/register.html", {'form': form})
after if form.is_valid() == True django creates a cleaned_data method with which you can call for the cleaned form data into your view.
You might want something like this:
def Register(request):
if request.method == "POST":
form = RegisterForm(request.POST)
if form.is_valid():
fname = form.cleaned_data.get('first_name')
lname = form.cleaned_data.get('last_name')
https://docs.djangoproject.com/en/1.8/ref/forms/api/#django.forms.Form.is_valid
also what does your Form object look like in forms.py?
Related
I have created a forum website in Django where users can post Questions/Answers and edit them.
After editing the reply I want to redirect the user to the currently edited post page. like if user
edit reply which has been posted on the question with id 4 (which url is (http://127.0.0.1:8000/discussion/4)) then after edited it should redirect to the same URL. After editing, and deleting the reply I am redirecting the user to the forum homepage but I want to redirect to the /discussion/{post_id} URL(which is URL of the particular post on which reply being edited and deleted)
urls.py
app_name = "dashboard"
urlpatterns = [
path('', views.index, name="index"),
path('user_home', views.user_home, name="user_home"),
path('admin_home', views.admin_home, name="admin_home"),
path("forum", views.forum, name="forum"),
path("discussion/<int:myid>", views.discussion, name="discussion"),
path("showallusers", views.show_all_users, name="showallusers"),
path('delete_user/<int:pk>', views.delete_user, name="delete_user"),
path('delete_post/<int:pk>', views.delete_post, name="delete_post"),
path('delete_reply/<int:pk>', views.delete_reply, name="delete_reply"),
path('upload_notes', views.upload_notes, name='upload_notes'),
path('view_mynotes', views.view_mynotes, name='view_mynotes'),
path('delete_mynotes/<int:pk>/', views.delete_mynotes, `name='delete_mynotes'), `
path('pending_notes', views.pending_notes, name='pending_notes'),
path('assign_status/<int:pk>', views.assign_status, name='assign_status'),
path('accepted_notes', views.accepted_notes, name='accepted_notes'),
path('rejected_notes', views.rejected_notes, name='rejected_notes'),
path('all_notes', views.all_notes, name='all_notes'),
path('delete_notes/<int:pk>', views.delete_notes, name='delete_notes'),
path('delete-records/', views.delete_notes, name='delete_notes'),
path('view_allnotes', views.view_allnotes, name='view_allnotes'),
path('notessharing', views.notessharing, name='notessharing'),
path('edit_post/<int:pk>/', views.edit_post, name='edit_post'),
path('edit_reply/<int:pk>/', views.edit_reply, name='edit_reply'),
]
delete_reply code
def delete_reply(request, pk=None):
reply = Replie.objects.filter(id=pk)
reply.delete()
return redirect('/forum')
After deleting a reply from a post I want to redirect to the same post.
models.py
class Post(models.Model):
user1 = models.ForeignKey(User, on_delete=models.CASCADE, default=1)
post_id = models.AutoField
post_content = models.TextField(max_length=5000,verbose_name="")
timestamp= models.DateTimeField(default=now)
image = models.ImageField(upload_to="images",default="")
def __str__(self):
return f'{self.user1} Post'
class Replie(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, default=1)
reply_id = models.AutoField
reply_content = models.TextField(max_length=5000,verbose_name="")
post = models.ForeignKey(Post, on_delete=models.CASCADE, default='')
timestamp= models.DateTimeField(default=now)
image = models.ImageField(upload_to="images",default="")
def __str__(self):
return f'{self.user1} Post'
views.py
def forum(request):
user = request.user
profile = Profile.objects.all()
if request.method=="POST":
form=PostContent(request.POST)
if form.is_valid():
user = request.user
image = request.user.profile.image
content = request.POST.get('post_content','')
post = Post(user1=user, post_content=content, image=image)
post.save()
messages.success(request, f'Your Question has been posted successfully!!')
return redirect('/forum')
else:
form=PostContent()
posts = Post.objects.filter().order_by('-timestamp')
form= PostContent()
context={
'posts':posts,
'form':form
}
return render(request, "forum.html",context)
def discussion(request, myid):
post = Post.objects.filter(id=myid).first()
replies = Replie.objects.filter(post=post)
if request.method=="POST":
form=ReplyContent(request.POST)
if form.is_valid():
user = request.user
image = request.user.profile.image
desc = request.POST.get('reply_content','')
post_id =request.POST.get('post_id','')
reply = Replie(user = user, reply_content = desc, post=post, image=image)
reply.save()
messages.success(request, f'Your Reply has been posted successfully!!')
return redirect(f'/discussion/{post_id}')
else:
form=ReplyContent()
form= ReplyContent()
return render(request, "discussion.html", {'post':post, 'replies':replies,'form':form})
def edit_reply(request, pk):
reply = Replie.objects.get(id=pk)
if request.method == 'POST':
form = UpdateReplyForm(request.POST, instance=reply)
if form.is_valid():
form.save()
messages.success(request,"Reply updated successfully!")
return redirect('/forum')
else:
form = UpdateReplyForm(instance=reply)
context = {
'form': form
}
return render(request, 'edit_reply.html', context)
edit_post view
def edit_post(request, pk):
post = Post.objects.get(id=pk)
if request.method == 'POST':
form = UpdatePostForm(request.POST, instance=post)
if form.is_valid():
form.save()
messages.success(request, "Post updated successfully!")
return redirect('/forum')
else:
form = UpdatePostForm(instance=post)
context = {
'form': form
}
return render(request, 'edit_post.html', context)
Currently, after editing the reply, I am redirecting the user to the post home page but I want to redirect to /discussion/{post_id}.
Template code:
edit_reply.html
{% load static %}
{% block body %}
{% load crispy_forms_tags %}
<div class="container ">
<form method="POST">
<div class="form-group">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4 mt-4 f2" >Update Reply</legend>
</fieldset>
<label style="font-size:1rem; font-weight:bold;">Reply Content</label>
{{form|crispy}}
<input type="hidden" name="post_id" value="{{post_id}}">
<div class="form-group">
<button href="" class="btn btn-primary" type="Update">
Update
</button>
</div>
</div>
</form>
</div>
{% endblock body %}
You can redirect it to discussion view with its pk by passing args=[reply.post.id] in edit_reply view.
Try this:
views.py
from django.shortcuts import render, redirect
from django.urls import reverse
def edit_reply(request, pk):
reply = Replie.objects.get(id=pk)
if request.method == 'POST':
form = UpdateReplyForm(request.POST, instance=reply)
if form.is_valid():
form.save()
messages.success(request, "Reply updated successfully!")
return redirect(reverse('dashboard:discussion', args=[reply.post.id]))
else:
form = UpdateReplyForm(instance=reply)
context = {
'form': form
}
return render(request, 'home/edit_reply.html', context)
Note: Forms in django required Form to be the suffix, so it will be better if it changed to PostContentForm and ReplyContentForm from PostContent and ReplyContent respectively.
It must be return f'{self.user} Post' not
return f'{self.user`} Post'
As it is not any field in Replie model.
Note: ForeignKey's names are generally written in its own name and that too in snake_case, it will be better if you change user1 to user in Post model.
For better understanding:
If table name is PizzaTopingCategory so while creating ForeignKey you should name it as pizza_toping_category=models.ForeignKey(PizzaTopingCategory, on_delete=models.CASCADE)
Edit:
You need to find out post_id, so you can send it through:
Try this in the delte_reply view:
def delete_reply(request, pk=None):
reply = Replie.objects.filter(id=pk)
reply_instance = get_object_or_404(Replie,id=pk)
post_pk=reply_instance.post.id
reply.delete()
return redirect(reverse('dashboard:discussion', args=[post_pk]))
For passing pk in discussion view, you should write return redirect(reverse('dashboard:discussion', args=[reply.post.id])) in edit_post view:
views.py
def edit_post(request, pk):
post = Post.objects.get(id=pk)
if request.method == 'POST':
form = UpdatePostForm(request.POST, instance=post)
if form.is_valid():
form.save()
messages.success(request, "Post updated successfully!")
return redirect(reverse('dashboard:discussion', args=[post.id]))
else:
form = UpdatePostForm(instance=post)
context = {
'form': form
}
return render(request, 'home/edit_post.html', context)
I'm trying to populate my ModelForm with some of data that I have submitted to previous HTML page which is also ModelForm.
I just want to pass it to another form so it doesn't have to be written twice.
I've tried couple solutions from stackoverflow but they are 6+ years old, kinda outdated and also couldnt come up with solution from django docs https://docs.djangoproject.com/en/2.2/topics/forms/
I have two models, which have same fields which are name and boxid
I need to pass it from first input to second(to populate it).
forms.py
class NewCashierForm(forms.ModelForm):
class Meta:
model = Cashier
fields = ("cashier_company", "cashier_dealer", "cashier_name", "cashier_boxid", "cashier_type", "cashier_package", "cashier_otheritem", "cashier_otheritemserial", "cashier_length", "cashier_promotion", "cashier_amount", "cashier_paymenttype")
labels = {"cashier_company":('Firma'), "cashier_dealer": ('Diler'), "cashier_name":('Ime i prezime'), "cashier_boxid":('Box ID'), "cashier_type":('Tip'), "cashier_package":('Paket'), "cashier_otheritem":('Drugi uredjaj'), "cashier_otheritemserial":('SBU'), "cashier_length":('Dužina'), "cashier_promotion":('Promocija'), "cashier_amount":('Iznos'), "cashier_paymenttype":('Nacin uplate')}
exclude = ['cashier_published']
def save(self, commit=True):
cashier = super(NewCashierForm, self).save(commit=False)
if commit:
cashier.save()
return cashier
class NewPersonForm(forms.ModelForm):
class Meta:
model = Person
fields = {"person_name", "person_adress", "person_phone", "person_boxid"}
labels = {"person_name":('Ime i prezime'), "person_adress":('Adresa'), "person_phone":('Telefon'), "person_boxid":('Box ID')}
def save(self, commit=True):
person = super(NewPersonForm, self).save(commit=False)
if commit:
person.save()
return person
views.py
def addcashier(request):
if request.method == 'GET':
form = NewCashierForm()
else:
form = NewCashierForm(request.POST)
if form.is_valid():
fs = form.save(commit=False)
fs.user = request.user
fs.save()
return redirect('/byauthor')
return render (request, 'main/addcashier.html', {'form':form})
def addperson(request):
if request.method == 'GET':
form = NewPersonForm()
else:
form = NewPersonForm(request.POST)
if form.is_valid():
fs = form.save(commit=False)
fs.user = request.user
fs.save()
return redirect('/addcashier')
return render (request, 'main/addperson.html', {'form':form})
addperson.html and addcashier.html
{% extends "main/base.html" %}
{% block content %}
<form method="POST">
{% csrf_token %}
{{form.as_p}}
<button class="btn" type="submit">Unos i dodavanje pretplate</button>
</form>
<input type="button" value="Otkazi unos" onclick="window.history.back()" />
{% endblock %}
Any help and/or hint is appreciated.
To prepopulate the form, you need to pass an argument initial={} when initializing your form for the GET call. Since you are passing data from one view to another, you should use sessions.
def addperson(request):
if request.method == 'GET':
form = NewPersonForm()
else:
form = NewPersonForm(request.POST)
if form.is_valid():
fs = form.save(commit=False)
fs.user = request.user
fs.save()
request.session["person_form"] = request.POST.dict() #save the form as a dict in request.sessions
return redirect('/addcashier')
return render (request, 'main/addperson.html', {'form':form})
Then in your second view, use this data from sessions to initialize the form.
def addcashier(request):
if request.method == 'GET':
# get the form data from the request.session
form_data = request.session.pop('person_form', {})
box_id = form_data.get("person_boxid")
name = form_data.get("person_name")
form = NewCashierForm(initial={"cashier_name":name, "cashier_boxid":box_id}) # initialize the form with the data
else:
form = NewCashierForm(request.POST)
if form.is_valid():
fs = form.save(commit=False)
fs.user = request.user
fs.save()
return redirect('/byauthor')
return render (request, 'main/addcashier.html', {'form':form})
I want to show a form for invitation. I have created a form but when i go to the url /invitations/request, the invalid block is shown not the template with form. What might be the reason?
url(r'^request/$', requestInvitation, name='request-invitation'),
#csrf_exempt
def requestInvitation(request):
form = InviteForm(request.POST or None)
response_data = {}
if form.is_valid():
join = form.save(commit=False)
email = form.cleaned_data.get('email')
already_join, created = Invitation.objects.get_or_create(email=email)
if created:
already_join.invite_code = get_invite_code()
already_join.save()
response_data['result'] = "Thank you for your interest"
response_data['email'] = email
print ('response_data', response_data)
return HttpResponse(json.dumps(response_data),content_type="application/json")
else:
return HttpResponse(json.dumps({'result': 'Error message'}))
# return HttpResponseRedirect('/')
context = {"form": form}
return render(request, 'invitation/invitation.html', context)
<form method="POST" class="invitation-form vcenter" action=".">
{% csrf_token %}
<div class="ui action input">
<input type="email" class="requested_email" name="email" placeholder="Email address">
<button class="ui button primary">Request Invite</button>
</div>
</form>
I think, you need to separate out the POST call. I mean, you need to check if the request method is POST or not. Something like this:
if request.method == 'POST': # If the form has been submitted...
response_data = {}
if form.is_valid():
join = form.save(commit=False)
email = form.cleaned_data.get('email')
already_join, created = Invitation.objects.get_or_create(email=email)
if created:
already_join.invite_code = get_invite_code()
already_join.save()
response_data['result'] = "Thank you for your interest"
response_data['email'] = email
print ('response_data', response_data)
return HttpResponse(json.dumps(response_data),content_type="application/json")
else:
return HttpResponse(json.dumps({'result': 'Error message'}))
# return HttpResponseRedirect('/')
else:
# An unbound form
Here's the workflow for your request:
A GET request is made (you're just visiting /invitations/request. So request.POST is an empty {}.
form = InviteForm(request.POST or None). Thus, the InviteForm is not valid.
if form.is_valid(): is False.
else: return HttpResponse(json.dumps({'result': 'Error message'})). So, the else clause is executed, which returns a JSON response, which you're showing in your template.
Now, for the solution:
#csrf_exempt
def requestInvitation(request):
form = InviteForm()
response_data = {}
if request.method == 'POST':
# This is a POST request, so request.POST will not be {}
form = InviteForm(request.POST)
if form.is_valid():
join = form.save(commit=False)
email = form.cleaned_data.get('email')
already_join, created = Invitation.objects.get_or_create(email=email)
if created:
already_join.invite_code = get_invite_code()
already_join.save()
response_data['result'] = "Thank you for your interest"
response_data['email'] = email
print ('response_data', response_data)
return HttpResponse(json.dumps(response_data),content_type="application/json")
else:
return HttpResponse(json.dumps({'result': 'Error message'}))
context = {'form': form}
return render(request, 'invitation/invitation.html', context)
I am trying to create a frontend form in my Django site that will allow users to add entries to my SQL database.
But when I use the form nothing happens in my database. What am I doing wrong?
I thought the right way would be to use the ModelForm technique.
My models looks like this:
class Actor(models.Model):
name = models.CharField(max_length=200)
wage = models.IntegerField(default=3100)
def __str__(self):
return self.name
So I wrote this in my forms.py:
from django import forms
from .models import Actor
class ActorForm(forms.ModelForm):
class Meta:
model = Actor
fields = ['name', 'wage']
form = ActorForm()
I then added this to my views.py:
def get_actor(request):
if request.method == 'POST':
form = ActorForm(request.POST)
if form.is_valid():
return HttpResponseRedirect('/scenes/thanks/')
else:
form = ActorForm()
return render(request, 'scenes/actor.html', {'form': form})
def thanks(request):
return render(request, 'scenes/thanks.html',)
And this in a template called actors.html
<form action="/scenes/actor/" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit" />
You have to call the model form's save() method after checking that it's valid:
def get_actor(request):
if request.method == 'POST':
form = ActorForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/scenes/thanks/')
else:
form = ActorForm()
return render(request, 'scenes/actor.html', {'form': form})
I am trying to create a formset that captures a parameter from the url to prefill one of the fields. The form is displaying correctly and at the correct address, but after clicking "submit" the page redirects to "/correction/" instead of the intended /correction/A07686+dwdID19, and the form does not save. What might be the issue?
In models.py:
class correction(models.Model):
corrected_word = models.ForeignKey(item)
correction_author = models.ForeignKey(User)
correction_made = models.IntegerField(u'correction_made', choices=CORRECTION_CHOICES)
correction_word = models.CharField(u'correction_word', max_length=200, blank=True, null=True)
time = models.DateTimeField(auto_now_add=True)
approved = models.IntegerField(u'approved', choices=APPROVAL_CHOICES, blank=True, null=True)
def __unicode__(self):
return str(self.time)
In views.py:
def submit_corr(request, bdword):
if hasattr(request, 'user') and request.user.is_authenticated():
word = item.objects.filter(file_position=bdword)[0]
CorrFormSet = inlineformset_factory(item, correction, fields=['correction_made', 'correction_word','correction_author'], can_delete=False, extra=1)
form = CorrFormSet(request.POST, request.FILES, instance=word, initial=[{'correction_author': request.user,}])
if request.method == 'POST':
if form.is_valid():
for entry in form:
entry.save()
else:
form = CorrFormSet(instance=word, initial=[{'correction_author': request.user,}])
return render(request, "correctionform.html", {"form": form,"word": word})
In urls:
url(r'^correction/(?P<bdword>.*)$', 'english.views.submit_corr'),
In the template:
Submit correction</th>
Thanks in advance!
Submit correction doesn't submit a form because it's a link and when you press a link, this sends a request with a GET method to the server so never enter to if request.method == 'POST': .
Please try something like
<form action="/correction/{{word.file_position}}" method="POST">
{# your inputs fields#}
<button type="submit">Submit correction</button>
</form>
I hope to be useful. Regards