How to Insert multiple data in django to django form? - python

I want to insert multiple row into my database from form2. Below are my codes
first model.py
class DataPribadiSiswa(models.Model):
SiswaID = models.AutoField(primary_key=True)
WaliKelasID=models.CharField(max_length=5,blank=True,null=True)
second model.py
class RiwayatSekolah(models.Model):
SekolahID=models.AutoField(primary_key=True)
SiswaID_FK=models.ForeignKey(DataPribadiSiswa,blank=True, null=True)
SekolahNama=models.CharField(max_length=50,blank=True,null=True)
SekolahThMasuk=models.CharField(max_length=4,blank=True,null=True)
SekolahThKeluar=models.CharField(max_length=4,blank=True,null=True)
SekolahKet=models.TextField(blank=True,null=True)
views.py
def tambah_siswa(request):
form = datasiswa(request.POST)
form2 = riwayatsekolah(request.POST)
FormSet2 = inlineformset_factory(DataPribadiSiswa, RiwayatSekolah, extra=2, fields=('SekolahID','SiswaID_FK','SekolahNama','SekolahThMasuk','SekolahThKeluar','SekolahKet'))
if request.method == 'POST':
if form.is_valid():
siswa_instance = form.save()
form2 = FormSet2(request.POST, instance=siswa_instance)
if form2.is_valid():
form2.save()
return redirect('index')
else:
formall={}
formall['form'] = datasiswa()
formall['form2'] = riwayatsekolah()
return render(request, 'siswa/tambah_siswa.html', formall)
and this is my template
<form action="" method="post">
{% csrf_token %}
<table >
{{ form2.management_form }}
{{ form2.as_table }}
</table>
</form>
How to insert multiple row from form2 into database? when i run this code, it just insert one row.

To simplify working with related objects you can use Inline formsets
You can implement it this way:
from django.forms import inlineformset_factory
FormSet2 = inlineformset_factory(DataPribadiSiswa, RiwayatSekolah, extra=2)
Now in view try this:
def tambah_siswa(request):
form = datasiswa(request.POST or None)
FormSet2 = inlineformset_factory(DataPribadiSiswa, RiwayatSekolah, extra=2, fields=('SekolahID','SiswaID_FK','SekolahNama','SekolahThMasuk','SekolahThKeluar','SekolahKet'))
if request.method == 'POST':
if form.is_valid():
siswa_instance = form.save()
form2 = FormSet2(request.POST or None, instance=siswa_instance)
if form2.is_valid():
form2.save()
return redirect('index')
form2 = FormSet2(request.POST or None)
formall={}
formall['form'] = form
formall['form2'] = form2
return render(request, 'siswa/tambah_siswa.html', formall)
And in template:
{{ form2.management_form }}
{{ form2.as_table }}
or
{{ form2.management_form }}
{% for frm in form2 %}
{{ frm.as_table }}
{% endfor %}

Related

Django "if request.method == 'POST':" returns False

I'm making Django app and I have an issue, I've never had problem with before. As always in form view, I'm checking if request.method == 'POST' but somehow it returns False,
My code looks like that:
def recipe_create_view(request):
context = {}
form = RecipeForm(request.POST or None)
IngredientFormset = formset_factory(IngredientForm)
formset = IngredientFormset(request.POST or None)
context['form'] = form
context['formset'] = formset
if request.method == 'POST':
if form.is_valid():
if formset.is_valid():
form.save()
print("made a recipe")
for form in formset:
child = form.save(commit=False)
child.recipe = parent
child.save()
print("made a Ingredient")
else:
print("formset is not valid")
else:
print("form is not valid")
else:
print("request method is not correct")
return render(request, 'recipes/create_recipe.html', context)
create_recipe.html file:
<form method="POST">
{% csrf_token %}
<label>recipe</label>
<p>{{form}}</p>
<label>ingredients</label>
{% for form in formset %}
<ul>
<label>name</label>
<li>{{ form.name }}</li>
<label>quantity</label>
<li>{{ form.quantity }}</li>
</ul>
{% endfor %}
<div>
<input type="submit" value="submit" class="button-33" role="button">
</div>
</form>
Where is the problem?
It is necessary to return HttpResponseRedirect after dealing with POST data, the tip is not specific to Django, it's a good web practice in general.
Also, try to maintain both GET and POST request separately, so try below view:
def recipe_create_view(request):
context = {}
form="" # for the error of variable refrenced before assignment.
IngredientFormset=""
formset=""
if request.method == 'POST':
form = RecipeForm(request.POST)
IngredientFormset = formset_factory(IngredientForm)
formset = IngredientFormset(request.POST)
if form.is_valid():
if formset.is_valid():
form.save()
print("made a recipe")
for form in formset:
child = form.save(commit=False)
child.recipe = parent
child.save()
print("made a Ingredient")
return redirect('some_success_path_name')
else:
print("formset is not valid")
else:
print("form is not valid")
else: # GET method
print("request method is GET")
form = RecipeForm()
IngredientFormset = formset_factory(IngredientForm)
formset = IngredientFormset()
context['form'] = form
context['formset'] = formset
return render(request, 'recipes/create_recipe.html', context)
add action in your HTML form and POST in small case.
<form action="/your_backend_url_to_view/" method="post">
{% csrf_token %}
<label>recipe</label>
<p>{{form}}</p>
<label>ingredients</label>
{% for form in formset %}
<ul>
<label>name</label>
<li>{{ form.name }}</li>
<label>quantity</label>
<li>{{ form.quantity }}</li>
</ul>
{% endfor %}
<div>
<input type="submit" value="submit" class="button-33" role="button">
</div>
</form>

HttpRequest after form method in django?

I'm new in django, and I can't to figure out how to redirect site to main page after submit.
I read here, and in others places that I need to return HttpResponseRedirect in method.
But my form looks that:
#login_required
##staff_member_required
def hero_detail_create_view(request):
#creating by form
form = HeroCreateModelForm(request.POST or None)
if form.is_valid():
obj = form.save(commit=False)
slugCreate = str.lower(form.cleaned_data.get('name') + "-" + form.cleaned_data.get('nickname'))
obj.slug = slugCreate.replace(" ","")
obj.user = request.user
obj.save()
form = HeroCreateModelForm()
template_name='form.html'
context = {'form':form}
return render(request, template_name, context)
It's creating a hero. And I need to redirect to main page after submit.
How can I do that? I can't just add second return. I tried create new method to redirect, and put in instide this, but of course it didn't wokrs.
My 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 %}
#login_required
def hero_detail_create_view(request):
# creating by form
form = HeroCreateModelForm(request.POST or None)
if form.is_valid():
obj = form.save(commit=False)
slugCreate = str.lower(form.cleaned_data.get("name") + "-" + form.cleaned_data.get('nickname'))
obj.slug = slugCreate.replace(" ","")
obj.user = request.user
obj.save()
return redirect("home.html")
template_name="form.html"
context = {"form":form}
return render(request, template_name, context)
You can redirect after saving the object like this:
obj.user = request.user
obj.save()
return redirect('you_main_page_url')
And don't call your form after saving the object
With handling the get request, you can do the following way:
#login_required
def hero_detail_create_view(request):
if request.method == "POST":
form = HeroCreateModelForm(request.POST or None)
if form.is_valid():
obj = form.save(commit=False)
slugCreate = str.lower(form.cleaned_data.get('name') + "-" + form.cleaned_data.get('nickname'))
obj.slug = slugCreate.replace(" ","")
obj.user = request.user
obj.save()
return redirect('your_home_page')
else:
form = HeroCreateModelForm()
return render(request, 'form.html', {'form':form})

'ManagementForm data is missing or has been tampered with' error when loading multiple model forms django

views.py
#login_required(login_url='/account/login/')
def TaskCreateView(request,pk,todo_id):
if not request.user.is_authenticated:
return redirect('accounts:index')
else:
instance = get_object_or_404(Level, pk=pk)
qs = instance.todo_set.get(id = todo_id)
todo = Task.objects.filter(todo=qs, student=request.user)
if todo.exists():
messages.warning(request, 'You Already Completed This Task')
return HttpResponseRedirect(instance.get_absolute_url())
form = StudentTaskForm(request.POST or None, request.FILES or None)
if form.is_valid():
form.instance.user = User.objects.get(id=request.user.id)
obj = form.save(commit=False)
obj.student = request.user
obj.todo = qs
obj.level = instance
obj.save()
ImageFormSet = modelformset_factory(Images,
form=ImageForm, extra=3)
formset = ImageFormSet(request.POST, request.FILES,
queryset=Images.objects.none())
if request.method == 'POST':
if formset.is_valid():
for form in formset.cleaned_data:
image = form['image']
photo = Images(post=form, image=image)
photo.save()
return redirect('student:dashboard')
return render(request,'task_form.html',
{'form':form,"qs":qs,'formset':formset})
forms.py
class StudentTaskForm(forms.ModelForm):
title = forms.CharField(widget=forms.TextInput(attrs={'class':
'form-control',' type': "text",'placeholder':'Enter Title'}))
content = forms.CharField(widget=SummernoteWidget())
class Meta:
model = Task
fields = [
'title',
'content',
]
widgets = {
'content': SummernoteWidget(),
}
class ImageForm(forms.ModelForm):
image = forms.ImageField(label='Image')
class Meta:
model = Images
fields = ('image', )
I have two models Task and Images and I'm using two forms for the same.
Im trying to implement multiple image upload for the same. When I try to load the form I'm encountering this error. I have added the {{ formset.management_form }} in the template. The images model has a foreign key to the Task.
template:
<form id="post_form" action="" method="post"
enctype="multipart/form-data">
{% csrf_token %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in form %}
{{ field }} <br />
{% endfor %}
{{ formset.management_form }}
{% for form in formset %}
{{ form }}
{% endfor %}
<div class="panel-body">
<button type="submit" class="btn btn-primary m-t-10">Submit</button>
</div>
</form>
You should only instantiate the formset with request.POST for POST requests.
if request.method == 'POST':
formset = ImageFormSet(request.POST, request.FILES,
queryset=Images.objects.none())
...
else:
# GET request
formset = ImageFormSet(queryset=Images.objects.none())
...

How to get value from form and redirect to /value in Django 1.10

I need to get value from tag and redirect to '/value/' by submit.
Now I'm getting:
'ApartmentForm' object has no attribute 'cleaned_data'
I'm totally missing something.
forms.py
class ApartmentForm(ModelForm):
class Meta:
model = Apartment
fields = ['title']
views.py
def index(request):
context = {}
context['apartments'] = get_list_or_404(Apartment)
if request.method == 'POST':
form = ApartmentForm(request.POST or None)
context = {'form': form,}
id = form.cleaned_data.get('id', None)
return redirect(id)
else:
context['apartment_form'] = ApartmentForm
return render(request, 'main/main.html', context)
template
<form action="/{{ apartment.id }}" method="post">
{% csrf_token %}
<p><select size="10">
<option disabled>Chose apartment</option>
{% for apartment in apartments %}
<option value="{{ apartment.id }}">{{ apartment.title }}</option>
{% endfor %}
</select></p>
<input type="submit" value="Chose">
</form>
Update
Thanks Daniel!
It was such a fail not to call form in the template. I fixed that, but it still passing None to url (http://127.0.0.1:8000/None). Can't figure out why.
view.py
def index(request):
context = {}
context['apartments'] = get_list_or_404(Apartment)
if request.method == 'POST':
form = ApartmentForm(request.POST or None)
if form.is_valid():
id = form.cleaned_data.get('id', None)
return redirect(id)
else:
context['apartment_form'] = ApartmentForm
return render(request, 'main/main.html', context)
forms.py
APARTMENTS = ()
for apartment in Apartment.objects.all():
APARTMENTS += ((apartment.id, apartment.title),)
class ApartmentForm(Form):
apartment = ChoiceField(label='', widget=Select, choices=APARTMENTS)
template
<form action="." method="post">
{% csrf_token %}
{{ apartment_form }}
<input type="submit" value="Chose">
form.cleaned_data comes from form.is_valid(), so you sould change your views.py like this:
def index(request):
[...]
if request.method == 'POST':
form = ApartmentForm(request.POST or None)
if form.is_valid():
[...]
id = form.cleaned_data.get('id', None)
return redirect(id)

Take In Input from User and Display the same input on the same page

Hi i am trying to create a post form in django where the user creates a post and the post is displayed back to them on the same page so far i have been unsuccessful. My articles display on the page but the form to post articles doesnt only the submit button shows.
views.py
def articles(request):
args = {}
args.update(csrf(request))
args ['posts'] = post.objects.filter(user = request.user)
args ['full_name'] = User.objects.get(username = request.user.username)
return render_to_response('articles.html', args)
def article(request, post_id=1):
return render(request, 'article.html',
{'post': post.objects.get(id=post_id) })
def create(request):
if request.POST:
form = PostForm(request.POST, request.FILES)
if form.is_valid():
a = form.save(commit=False)
a.user = User.objects.get(username = request.user.username)
a.save()
messages.add_message(request, messages.SUCCESS, "You Article was added")
return HttpResponseRedirect('/posts/all')
else:
form = PostForm()
args = {}
args.update(csrf(request))
args['form'] = form
return render_to_response('articles.html', args)
articles.html
<form action="/posts/create/" method="post" enctype="multipart/form-data">{% csrf_token %}
<ul>
{{form.as_ul}}
</ul>
<input type="submit" name="submit" value="Create Article">
</form>
{% if posts.count > 0 %}
{% for post in posts %}
<div>
<h2>{{full_name}}</h2>
<p>{{ post.body|lower|truncatewords:50 }}</p>
<p>{{post.likes}} people liked this article</a></p>
</div>
{% endfor %}
{% else %}
<p>None to show!</p>
{% endif %}
{% endblock %}
urls.py
from django.conf.urls import patterns, include, url
urlpatterns = patterns('',
url(r'^create/$', 'posts.views.articles'),
url(r'^get/(?P<post_id>\d+)/$', 'posts.views.article'),
url(r'^create/$', 'posts.views.create'),
url(r'^like/(?P<post_id>\d+)/$', 'posts.views.like_article'),
url(r'^article/(?P<post_id>\d+)/$', 'posts.views.add_comment'),
)
First off you aren't passing the form to the template in articles(). You need to have something along the lines of:
args['form'] = YourForm()
In your first view function. Also, in your create view you do this:
a.user = User.objects.get(username = request.user.username)
Which does an unnecessary database lookup of the user again, you can just do this to be clearer and faster:
a.user = request.user

Categories

Resources