Django 1.8 Passing data between pages with using form - django

I already have codes and it doesn't working. But I'am looking for solution or practice on how to pass data between pages with using form. Should I work with hiddenfields or sessions?. I am ready to change or rewrite my codes. I am open the other suggestions, thought.
Here is my codes
forms.py
class applyForm(forms.ModelForm):
basvuru_mesaji = forms.CharField(required=True,error_messages={'required':'Bu alanı boş bırakmamanız gerekiyor'}, widget=forms.Textarea(attrs={'class': 'full','placeholder': 'Başvuru mesajınızı buraya yazınız'}))
tcn = forms.IntegerField(required=False, error_messages={'invalid':'Numara dışında karakter girişi yaptınız'}, widget=forms.TextInput(attrs={'class': 'full','placeholder': 'T.C. Kimlik Numaranız'}))
hidden = forms.CharField(widget=forms.HiddenInput(), required = False)
class Meta():
model = apply
fields = '__all__'
models.py
class apply(models.Model):
tcn = models.PositiveIntegerField(blank=True, verbose_name='T.C.N :', null=True)
basvuru_mesaji = models.TextField(verbose_name='Başvuru Mesajı')
views.py
def form_for_apply(request):
form = applyForm(request.POST or None)
if form.is_valid():
new_join = form.save(commit=True)
new_join.save()
basvuru_mesaji = form.cleaned_data["basvuru_mesaji"]
return HttpResponseRedirect('/apply_ok/')
context = {"form":form}
template = "apply.html"
return render(request, template, context)
def apply_ok(request):
allfield = apply.objects.all()
print allfield
form = applyForm(request.GET)
context = {"form":form}
#print context.data
template = "apply_ok.html"
return render(request, template, context)
apply.html
{% csrf_token %}
{% if form.errors %}
{{ form.errors }}
{% endif %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
<div class="mTopTwe">
<label for="{{ form.basvuru_mesaji.id_for_label }}">
{{form.basvuru_mesaji.field.label}}
</label>
{{ form.basvuru_mesaji.errors }}
{{ form.basvuru_mesaji }}
</div>
apply_ok.html
<div class="mTopTwe">
{{form.basvuru_mesaji.data}} {{ form.hidden.data }}
</div>

You can using django wizard-form for passing data between pages.

render_to_response solved my problem.
return render_to_response('apply_ok.html', context_instance=RequestContext(request,{'form':form}))
forms.py
def apply(request):
form = applyForm(request.POST or None)
if form.is_valid():
new_join = form.save(commit=True)
new_join.save()
basvuru_mesaji = form.cleaned_data['basvuru_mesaji']
return render_to_response('apply_ok.html', context_instance=RequestContext(request,{'form':form}))
context = {"form":form}
template = "apply.html"
return render(request, template, context)

Related

Django booleanfield modelform

So I'm making a to-do list and I made a booleanfield modelform which has attribute "complete". I want that user to check it when it's complete and I tried wriring if task.complete == True cross out the item and it didn't work(it only worked when I checked it from the admin panel). Then I tried form.complete instead of task.complete and it doesn't do anything.
models:
class Task(models.Model):
title = models.CharField(max_length=200)
complete = models.BooleanField(default=False)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
forms:
from .models import *
class TaskForm(forms.ModelForm):
title = forms.CharField(widget= forms.TextInput(attrs={'placeholder':'Add new task...'}))
class Meta:
model = Task
fields = '__all__'
html:
<div class="main-container">
<form method="POST" action="/">
{% csrf_token %}
<input type="submit"/>
{{ form.title }}
</form>
{% for task in tasks %}
{{ form.complete }}
{% if form.complete == True %}
<h1><strike>{{task.title}}</strike></h1>
{% else %}
<h1>{{task.title}}</h1>
{% endif %}
{% endfor %}
</div>
views:
def index(request):
tasks = Task.objects.order_by('-created')
form = TaskForm()
if request.method == 'POST':
form = TaskForm(request.POST)
if form.is_valid():
form.save()
return redirect('/')
context = {
'tasks': tasks,
'form': form,
}
return render(request, 'to-do.html', context)
There are some problems with your code I don't know how to explain. Try this. It should work.
<div class="main-container">
<form method="POST" action="/"> # create new task
{% csrf_token %}
{{ form.title }}
<input type="submit" name="new-task"/>
</form>
<form method="post"> # update task status
{% csrf_token %}
{% for task in tasks %}
{% if task.complete %}
<input type="checkbox" name="if_completed" checked value="{{ task.pk }}">
<h1><strike>{{task.title}}</strike></h1>
{% else %}
<input type="checkbox" name="if_completed" value="{{ task.pk }}">
<h1>{{task.title}}</h1>
{% endif %}
{% endfor %}
<input type="submit" name="update-task"/>
</form>
</div>
view.py (Only for form, add your other code with it)
from django.http import HttpResponseRedirect
from django.urls import reverse
def index(request):
tasks = Task.objects.order_by('-created')
form = TaskForm()
if request.method == 'POST':
if 'new-task' in request.POST:
form = TaskForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('home')) # replace home with url name where you want to redirect
elif 'update-task' in request.POST:
task_pk = request.POST.getlist("if_completed")
for i in task_pk:
Task.objects.filter(pk=i).update(complete=True) # I have replace pk with i here
return HttpResponseRedirect(reverse('home')) # replace home with url name where you want to redirect
context = {
'tasks': tasks,
'form': form,
}
return render(request, 'to-do.html', context)
in forms.py
class TaskForm(forms.ModelForm):
class Meta:
model = Task
fields = ('title',)
widgets = {
'title': forms.TextInput(attrs={'placeholder':'Add new task...'})
}
This should work. There may be be some error because of typos or indentation. Let me know if you get any issue
def index(request):
tasks = Task.objects.order_by('-created')
form = TaskForm()
context = {
'tasks': tasks,
'form': form,
}
if request.method == 'POST':
if 'new-task' in request.POST:
form = TaskForm(request.POST)
if form.is_valid():
form.save()
elif 'update-task' in request.POST:
task_pk = request.POST.getlist("if_completed")
for i in task_pk:
Task.objects.filter(pk=pk).update(complete=True)
return render(request, 'to-do.html', context)

Django: Create an editable form for each instance within a queryset all in one page?

Sorry if this is too much code, but I believe it is all relevant to the question at hand.
Long story short, on my series_detail page, all episodes belonging to each series is shown, as well as forms to add a new episode or edit an existing one.
The edit episode form, however, requires an instance, which always returns the very first object of the episodes queryset. This is presumably because of the .first(), but I used this since you can only have one object passed as an instance.
What I am trying to achieve is:
after showing the edit modal next to each episode, show the instance of each episode instead of only the first episode.
save only that episode's instance after the form is filled
achieve this without redirecting to an edit page
models.py
class Series(models.Model):
name = models.CharField(max_length=100)
class Episode(models.Model):
series = models.ForeignKey(Series, on_delete=models.CASCADE)
name = models.CharField(max_length=100)
episode_no = models.IntegerField(null=True)
description = models.TextField(max_length=500)
image = models.ImageField(upload_to='pics/episodes',)
forms.py
class EpisodeForm(forms.ModelForm):
name = forms.CharField()
description = forms.CharField(widget=forms.Textarea, required=False)
episode_no = forms.IntegerField()
class Meta:
model = Episode
fields = ['name', 'description', 'episode_no' ,'image']
views.py
def series_detail(request, pk):
try:
series = Series.objects.get(pk=pk)
except:
return render(request, 'error_404.html')
episodes = Episode.objects.filter(series=series).first()
if request.method == 'POST':
if 'addepisodeform' in request.POST:
e_form = EpisodeForm(request.POST, request.FILES, prefix='addepisode')
e_form.instance.series = Series.objects.get(pk=pk)
if e_form.is_valid():
e_form.save()
return redirect('series_detail', pk=pk)
messages.success(request, 'Episode was created')
else:
return redirect('series_detail', pk=pk)
messages.error(request, 'Episode was not created')
elif 'editepisodeform' in request.POST:
edit_e_form = EpisodeForm(request.POST, request.FILES, instance=episodes, prefix='editepisode')
edit_e_form.instance.series = Series.objects.get(pk=pk)
if edit_e_form.is_valid():
edit_e_form.save()
return redirect('series_detail', pk=pk)
messages.success(request, 'Episode was updated')
else:
return redirect('series_detail', pk=pk)
messages.error(request, 'Episode was not updated')
else:
e_form = EpisodeForm(prefix='addepisode')
edit_e_form = EpisodeForm(instance=episodes, prefix='editepisode')
context = {
'episodes': episodes,
'e_form': e_form,
'edit_e_form': edit_e_form
}
return render(request, 'series/series_detail.html', context)
def delete_episode(request, pk1, pk2):
try:
series = Series.objects.get(pk=pk1)
except:
return render(request, 'error_404.html')
try:
episode = Episode.objects.get(series=series, episode_no=pk2)
except:
return render(request, 'error_404.html')
episode.delete()
return redirect('series_detail', pk=pk1)
urls.py
path('series/<int:pk>/', views.series_detail, name='series_detail'),
path('series/<int:pk1>/episode/<int:pk2>/delete/', views.delete_episode, name='delete_episode'),
series_detail.html
<button type="submit" name="addepisodeform">
Add Episode
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ e_form }}
</form>
</button>
{% for episode in episodes %}
{{ episode.name }}
{{ episode.description}}
<img src="{{ episode.image.url }}" height="125px" width="300px" style="object-fit: cover;">
<button type="submit" name="editepisodeform">
Edit Episode
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ edit_e_form }}
</form>
</button>
{% endfor %}
Okay, so it turns out that formsets were the way to go after all. Thanks to Willem Van Onsem's answer, I decided to go that route after all and it worked like a charm.
A form can only edit one instance, but with formsets, I was able to not only edit each episode rather than just the first instance, but even create a new object and delete multiple objects at the same time!
views.py
#import the formset
from django.forms import modelformset_factory, inlineformset_factory
#formset
EpisodeFormset = inlineformset_factory(Series, Episode, fields=('name', 'episode_no', 'description', 'image'), can_delete=True, extra=1)
#post call
if request.method == 'POST':
if 'editepisodeform' in request.POST:
formset = EpisodeFormset(request.POST, request.FILES, instance=series, prefix='editepisode')
if formset.is_valid():
formset.save()
return redirect('series_detail', pk=pk)
else:
return redirect('series_detail', pk=pk)
else:
formset = EpisodeFormset(instance=series)
series_detail.html
<div>
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ formset.management_form }}
{% for form in formset %}
<button type="submit" class="btn btn-primary" name="editepisodeform">Edit</button>
{{ form.as_p }}
{% for episode in episodes %}
{% if episode.episode_no == form.episode_no.value %}
Episode: {{ episode.episode_no }} <br>
Name: {{ episode.name }} <br>
<img src="{{ episode.image.url }}" height="125px" width="300px" style="object-fit: cover;"> <br> {% endif %}
{% endif %}
{% endfor %}
{% endfor %}
</form>
</div>

Django , upload multiple images with formset's

I've been trying for days to understand the reason for my error, in the first phase I detected that it was missing {{ formset.management_form }} in the html, which i include and still continues to give the same error:
"ManagementForm data is missing or has been tampered with"
And I don't know if my views are the way they should be done.
Models
class Intervencao(models.Model):
........
class Imagem(models.Model):
intervencao = models.ForeignKey(Intervencao, related_name='intervencaoObjectsImagem', on_delete=models.CASCADE)
imagem = models.ImageField(upload_to=get_image, blank=True, null=True, verbose_name="Fotografia")
def __str__(self, ):
return str(self.intervencao)
<!-- e
Forms
class TabletForm2(forms.ModelForm):
class Meta:
model=Intervencao
fields = __all__
class TabletFormImagem(forms.ModelForm):
imagem = forms.ImageField(required=True)
class Meta:
model=Imagem
fields = ['imagem',]
Views
def project_detail_chefe(request, pk):
ImagemFormSet = modelformset_factory(Imagem,form=TabletFormImagem, extra=3)
instance = Intervencao.objects.get(id=pk)
d1 = datetime.now()
intervencaoForm = TabletForm2(request.POST or None, instance=instance)
formset = ImagemFormSet(request.POST, request.FILES,queryset=Imagem.objects.none())
if request.method == "POST":
if intervencaoForm.is_valid() and formset.is_valid():
instance_form1 = intervencaoForm.save(commit=False)
instance_form1.data_intervencao_fim = d1
instance_form1.save()
images = formset.save(commit=False)
for image in images:
image.intervencao = instance_form1
image.save()
return redirect('index')
else:
intervencaoForm = TabletForm2(request.POST)
formset = ImagemFormSet(queryset=Imagem.objects.none())
context = {
'intervencaoForm':intervencaoForm,
'formset':formset,
}
return render(request, 'tablet/info_chefes.html', context)
HTML
<form method="post" enctype="multipart/form-data" id="gravar">
<div class="row">
<div class="col-md-12">
<table>
{{ formset.management_form }}
{% for form in formset %}
{{ form }}
{% endfor %}
</table>
</div>
</div>
</form>
in my case , the problem was the
else:
intervencaoForm = TabletForm2(request.POST)
formset = ImagemFormSet(queryset=Imagem.objects.none())
beacause is in line with the wrong if. all working now

How to display django-simple-history in template from a views.py or other?

I do not know how to display a history in a Django template, nor even how to use it in the Django views.py:
views.py:
class Fournisseur(models.Model):
photo = models.FileField(verbose_name="Photo")
nom_f = models.CharField(max_length=40, verbose_name="Fournisseur")
adresse = models.CharField(max_length=50, verbose_name="Adresse")
email = models.EmailField(verbose_name="Courriel")
contact = models.PositiveIntegerField(verbose_name="Contact")
date_f = models.DateTimeField(auto_now_add=True, verbose_name="Date de création")
history = HistoricalRecords()
def __str__(self):
return self.nom_f
You can try like this:
in views.py
def some_view(request, pk):
if request.method == "GET":
obj = Fournisseur.objects.get(pk=pk)
return render(request, 'template.html', context={'object': obj})
in template.html:
{% for h in object.history.all %}
{{ h }} // history object
{{ h.changed_by }}
{{ h.comment }}
{% endfor %}
For details please see in documentation
def some_view(request, pk):
if request.method == "GET":
obj = Fournisseur.objects.get(pk=pk)
return render(request, 'template.html', context={'object': obj})
{% for h in object.history.all %}
{{ h }} // history object
{{ h.history_object }} // the object of the model
{{ h.history_date }} // the date of history
{{ h.history_user }} // Changed by, the user
{% endfor %}

Django "The submitted file is empty"

I have used multiple FileFields in a model and my app gives error "The submitted file is empty" on execution, folowing are the details of my code:
My models.py:
class KBCTest(models.Model):
algorithm = models.CharField(max_length=10, blank=False)
entityFile = models.FileField(blank=False,
upload_to=updateFilename,
validators=[validateTestingFileExtension])
relationFile = models.FileField(blank=False,
upload_to=updateFilename,
validators=[validateTestingFileExtension])
My forms.py
class KBCTestForm(forms.ModelForm):
class Meta:
model = KBCTest
fields = ('algorithm', 'entityFile', 'relationFile')
def clean(self):
super(KBCTestForm, self).clean()
data = self.cleaned_data
return data
My views.py:
def testing(request):
title = 'Testing'
template = 'testing.html'
form = ''
if request.method == 'GET':
form = KBCTestForm()
if request.method == 'POST':
form = KBCTestForm(request.POST, request.FILES)
if form.is_valid():
form.save()
runAlgo = Run(form.cleaned_data)
runAlgo.configAndTest()
return HttpResponseRedirect(reverse('learning', kwargs={'function': 'testing'}))
context = {'title': title, 'form': form}
return render(request, template, context)
My template:
{% if request.user.is_authenticated %}
<div class='col-sm-4 col-sm-offset-4'>
<h1>{{ title }}</h1>
<!-- If form not rendered(i.e. views context) don't show submit button -->
{% if form %}
<!-- Use 'csrf_token' to prevent cross-site forgery -->
<form enctype='multipart/form-data' method='POST', action=''>
{% csrf_token %}
{{ form|crispy }} </br>
{{ form.non_field_errors|crispy }}
<input type='submit' value='Test' class='btn btn-default'/>
</form>
{% endif %}
</div>
{% endif %}
When I run this template it fails to validate the form and gives error "The submitted file is empty" error as visible in the screenshot below:
Check out this part of the Django docs, where it mentions the parameter allow_empty_file for the forms.FileField. Maybe it gives you a few clues.
Note: I'm not exactly sure how this applies to ModelForm or Model.FileField.