have a form by which user can enter details about some expenses but i want to have same row in the form again and again but couldn't find out how to do that :
if you see figure above this forms works well for 1 row of data , saves well but with more then 1 row it cant . Can someone suggest any way to do that . Below are the codes :
models.py
from django.db import models
class Expenditure(models.Model):
exp_date = models.DateField("Expenditure_Date")
description = models.CharField(max_length=500)
amount = models.FloatField(default=0)
currency = models.CharField(max_length=15,default="USD")
class Meta:
unique_together = ('exp_date', 'description',)
def __unicode__(self):
return self.description
forms.py
from django import forms
from moni.models import Expenditure
from django.contrib.admin.widgets import AdminDateWidget
class ExpenditureForm(forms.ModelForm):
#exp_date = forms.DateField(help_text="Date")
exp_date = forms.DateField(widget=AdminDateWidget)
description = forms.CharField(max_length=500)
amount = forms.FloatField(initial=0)
currency = forms.CharField(widget=forms.HiddenInput(), initial="USD")
# An inline class to provide additional information on the form.
class Meta:
# Provide an association between the ModelForm and a model
model = Expenditure
fields = ('exp_date', 'amount', 'description')
views.py
from django.template import RequestContext
from django.shortcuts import render_to_response
from moni.models import Expenditure
from moni.forms import ExpenditureForm
def add_expenditure(request):
context = RequestContext(request)
if request.method == 'POST':
form = ExpenditureForm(request.POST)
if form.is_valid():
form.save(commit=True)
return index(request)
else:
print form.errors
else:
form = ExpenditureForm()
return render_to_response('moni/add_expenditure.html', {'form': form}, context)
add_expenditure.html
{% extends 'moni/base.html' %}
{% block title %}Add Shipment {% endblock %}
{% block body_block %}
<h1>Add a Expenditure</h1>
<p id="p_hide"> I am a paragraph to be hidden</p>
<button id ="btn1">Hide Paragraph</button>
<form id="expenditure_form" method="post" class="vDateField" action="/moni/add_expenditure/">
{% csrf_token %}
<table border=1>
<tr><th><label >Date:</label></th> <th><label for="id_description">Description:</label></th><th><label for="id_amount">Amount:</label></th></tr>
<tr><td><input class="vDateField" name="exp_date" size="10" type="text" /></td><td>{{form.description}}</td><td>{{form.amount}}<input id="id_currency" name="currency" type="hidden" value="MYR" /></td></tr>
<tr><td><input class="vDateField" name="exp_date" size="10" type="text" /></td><td>{{form.description}}</td><td>{{form.amount}}<input id="id_currency" name="currency" type="hidden" value="MYR" /></td></tr>
</table>
<input type="submit" name="submit" value="Create Expenditure" />
</form>
{% endblock %}
For that use Formeset function, Here is the idea for print form in multiple times
ExpenditureFormSet = formset_factory(ExpenditureForm, extra=3,)
And views like
if formset.is_valid():
for data in formset.cleaned_data:
And pass it into {formset} So html will print the extra 3 forms
You should use ModelFormSets instead of ModelForm.
And if you're going to add forms dynamically, use corresponding JavaScript plugin (since management form should be changed every time new form is added).
Related
I need to get the data from a form in a Django database. The problem when I use .cleaned_data['name'] I am getting an attribute error
'SnippetForm' object has no attribute 'cleaned_data'.
when I tried passing through if old_form.is_valid(), the if is False.
With my code, I can get the HTML info, but I can not parser it with .clean_data.
Basically I don't want to create a regex and parse the html, I am looking for some Django Method that can help.
Html code got from Django:
<tr><th><label for="id_name">Name:</label></th><td><input type="text" name="name" value="Ariel" maxlength="100" id="id_name"></td></tr>
<tr><th><label for="id_email">Email:</label></th><td><input type="email" name="email" value="as#onsemi.com" maxlength="254" id="id_email"></td></tr>
<tr><th><label for="id_subject">Subject:</label></th><td><input type="text" name="subject" value="Test" maxlength="100" id="id_subject"></td></tr>
<tr><th><label for="id_body">Body:</label></th><td><textarea name="body" cols="40" rows="10" id="id_body">
This is a test</textarea></td></tr>
In my views.py
def data_detail (request, request_id):
data_detail_django = get_object_or_404(Snippet, pk=request_id)
if request.method == "POST": #Also, it is not going throu this if...
old_form = SnippetForm(request.POST, instance=data_detail_django)
else: #The old_form is the html output and is get it with this
old_form = SnippetForm(instance=data_detail_django)
if old_form.is_valid():
print(old_form.cleaned_data['name'])
return HttpResponse("contact view")
In my models
from django.db import models
# Create your models here.
class Snippet(models.Model):
name = models.CharField(max_length=100, blank=True, null=True)
email = models.EmailField(blank=True, null=True)
subject = models.CharField(max_length=100, blank=True, null=True)
body = models.TextField(blank=True, null=True)
def __str__(self):
return self.name
in my form.py
from django import forms
from .models import Snippet
class SnippetForm(forms.ModelForm):
class Meta:
model = Snippet
fields = ('name', 'email','subject', 'body')
The solution was: Uning .objects.get(pk = vaule)
def data_detail (request, request_id):
data_dbs = Snippet.objects.get(pk= request_id)
data_out = {'data_dbs': data_dbs}
return render(request, 'form_app/detail.html', data_out )
and in the html to render:
{% extends 'form_app/base.html' %}
{% block main_content %}
{% if data_dbs %}
<p>Name: {{data_dbs.name}}</p>
<p>Email: {{data_dbs.email}}</p>
<p>Subject: {{data_dbs.subject}}</p>
<p>Body: {{data_dbs.body}}</p>
{% else %}
<p> No data</p>
{% endif %}
<a href = '/data'><b>See Form</b></a></li>
{% endblock %}
I make comments on the site and cannot understand why, after the user has filled out comment forms, they are not displayed, I try to display them through a template
P.S
I need to display the text and the nickname that the user would enter
views.py
def CommentGet(request):
if request.method == 'POST':
comment = Comments(request.POST)
name = request.POST['name']
text = request.POST['text']
if comment.is_valid():
comment.save()
return HttpResponseRedirect(request.path_info)
comments = CommentModel.objects.all()
else:
comment = Comments(request.POST)
comments = CommentModel.objects.all()
return render(request, 'news/post.html', {'comment': comment,'comments':comments})
post.html
<form method="post" action="{% url 'comment' %}">
{% csrf_token %}
<input type="text" name="name" value="{{ name }}">
<input type="text" name="text" value="{{ text }}">
<input type="submit">
</form>
{% for comm in comments %}
<h1> {{ comm.name }} </h1>
<h1> {{ comm.text }} </h1>
{% endfor %}
models.py
class CommentModel(models.Model):
name = models.CharField(max_length=100)
text = models.TextField(default='')
dates = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['-dates']
def __str__(self):
return self.name
I'd suggest using a ModelForm to make things simpler, Try something like this:
# views.py
def CommentGet(request):
if request.method == 'POST':
comment_form = CommentForm(request.POST)
comment_form.save()
else:
comment_form = CommentForm()
comments = CommentModel.objects.all()
return render(request, 'news/post.html', {'comment_form': comment_form,'comments':comments, })
# forms.py
class CommentForm(forms.ModelForm):
class Meta:
model = CommentModel
fields = ['name', 'text']
Then, in your template, replace the two text fields with {{ comment_form }}
I am currently struggling to get my form to work properly. I created the form manually (template.html) and I can see all the data when I call it with print(request.POST) (in views.py - checkout) however form.is_valid(): (in views.py - checkout) doesn't work. Means my form is not valid.
I think the issue is, that I created the form manually and combined it with a model form where I want after validating my data with form.valid() save it in. Can anyone of you guys help me with my problem, why it's not valid?
template.html
<form action="{% url 'checkout:reserve_ticket' %}" method="post">
{% csrf_token %}
{% for ticket in event.tickets.all %}
<p>
{{ ticket.name }} for {{ ticket.price_gross }} with quantity:
<input type="hidden" name="order_reference" value="123456af">
<input type="hidden" name="ticket" value="{{ ticket.id }}">
<input type="hidden" name="ticket_name" value="{{ ticket.name }}">
<input type="number" name="quantity" max="{{ ticket.event.organiser.max_quantity_per_ticket }}" placeholder="0">
</p>
{% endfor %}
<button type="submit" class="btn btn-primary">Continue</button>
</form>
models.py
class ReservedItem(models.Model):
order_reference = models.CharField(
max_length=10,
unique=True
)
ticket = models.ForeignKey(
Ticket,
on_delete=models.PROTECT,
related_name='reserved_tickets'
)
ticket_name = models.CharField(max_length=100)
quantity = models.IntegerField()
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
forms.py
class ReserveForm(forms.ModelForm):
class Meta:
model = ReservedItem
fields = ['order_reference', 'ticket', 'ticket_name', 'quantity']
views.py - events
# Create your views here.
class EventDetailView(DetailView):
context_object_name = 'event'
def get_object(self):
organiser = self.kwargs.get('organiser')
event = self.kwargs.get('event')
queryset = Event.objects.filter(organiser__slug=organiser)
return get_object_or_404(queryset, slug=event)
views.py - checkout
def reserve_ticket(request):
if request.method == 'POST':
form = ReserveForm(request.POST)
if form.is_valid():
print("Hello World")
return redirect("https://test.com")
else:
print("back to homepage")
When I trying to add image from admin panel all OK, but when I trying to add image from site, I have this error: image of error. When I trying to post Detail without image, I have the same problem. Before this wasn't.
views.py:
def new_detail(request):
if request.user.is_authenticated:
if request.user.is_superuser:
if request.method == 'POST':
car = request.POST['car']
author = request.user
detail = request.POST['detail']
price = request.POST['price']
description = request.POST['description']
image = request.FILES['images']
detail = Detail(car = car, author = author, detail = detail, price = price, description = description, images = image)
detail.save()
return redirect('/new_detail/')
else:
return redirect('/login/')
return render(request, 'shop/new_detail.html')
new_detail.html:
{% extends 'base.html' %}
{% block content %}
<div class="content container">
<div class="row">
<div class="col-md-8">
<div class=".signin">
<form action="" method="POST">
{% csrf_token %}
<h3>Автомобіль: </h3>
<select name="car">
<option selected>Audi A8 D2 3.3 TDI</option>
<option>Audi A8 D2 3.7</option>
...
...
...
<h3>Ціна: </h3><textarea name="price"></textarea>
<h3>Фотки: </h3><input type="image" name="images" />
<p>
<input type="submit" value="Опублікувати" />
</form>
</div>
</div>
</div>
models.py:
from django.db import models
class Detail(models.Model):
author = models.ForeignKey(
'auth.User',
on_delete=models.CASCADE,)
car = models.CharField(max_length=100)
detail = models.TextField()
description = models.TextField()
price = models.CharField(max_length=30)
images = models.ImageField(upload_to='details', null = True, blank = True)
def __unicode__(self):
return self.detail
def __str__(self):
return self.detail
The first problem is that you are missing enctype="multipart/form-data" from your form tag in the template. See the docs on file uploads for more info.
<form action="" method="POST" enctype="multipart/form-data">
Secondly, your view doesn't handle the case when data is missing from the form. Instead of doing request.POST['detail'] you should be checking if 'detail' in request.POST or using request.POST.get('detail').
However it would be very time consuming to check every field individually. You should look at Django forms and model forms, which can handle a lot of this for you.
from django import forms
class DetailForm(forms.ModelForm):
class Meta:
model = Detail
fields = ['car', 'author', 'detail', 'price', 'description', 'images']
Then your view will be something like
from django.contrib.auth.decorators import user_passes_test
#user_passes_test(lambda u: u.is_superuser)
def new_detail(request):
if request.method == 'POST':
form = DetailForm(request.POST)
if form.is_valid():
detail = form.save()
return redirect('/new_detail/')
else:
form = DetailForm(request.POST)
return render(request, 'shop/new_detail.html', {'form': form})
You can use the form to simplify your template as well:
<form action="" method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ form }}
</form>
See the docs on rendering fields manually if you need more control in the template.
The truth i'm new to django and i would like to know how I can capture a value of an input type = hidden in a view of django, using request.POST [ 'address'] so that it can enter a value in my model in this case I want to fill my field direction but does not receive any data appears in the database as empty. This is the code I have so far:
views.py
def formularioLleno(request):
form = InformationForm()
if request.method == 'POST':
form = InformationForm(request.POST or None)
if form.is_valid():
form.ubicacion = request.POST['direccion']
form.save()
#return redirect('formas.index')
return HttpResponseRedirect(reverse('index'))
else:
form = InformationForm()
data = {
'form': form,
}
return render_to_response('forma_form.html', data, context_instance=RequestContext(request))
forms.py
from django import forms
from .models import forma
class InformationForm(forms.ModelForm):
class Meta:
model = forma
fields = ('nombre', 'telefono')
models.py
class forma(models.Model):
nombre = models.CharField(verbose_name='nombre', max_length=50, unique=False)
telefono = models.CharField(verbose_name='telefono', max_length=10, unique=False)
ubicacion = models.CharField(verbose_name='ubicacion', max_length=15, unique=False)
forma_form.html
<div id="formularios">
{% block form_content %}
<form action="" method="POST">
{% csrf_token %}
{{ form.as_p }}
<div id="ubicacion"></div>
<input type="hidden" id="direccion" name="direccion" value="hello">
<button type="submit" onclick="alerta()">Contactar</button>
</form>
{% endblock form_content %}
The reason you aren't seeing the input is that the form field "direccion" is not a member of the class InformationForm. When you load data from the request with form = InformationForm(request.POST or None) the direccion field is not captured.
I would recommend adding a new member to the InformationForm form (direccion), and set the widget to HiddenInput (read more about Widgets here: https://docs.djangoproject.com/en/1.10/ref/forms/widgets/)
This keep the input hidden on the form but will pass the information back to the View. You can then remove the hard coded hidden input HTML from your template.