Django auto generated form-fields - python

What I want to do is some of the fields in my form to be automatically added according to the previous value. Let me show you my example:
my model
class Measurement(models.Model):
group = models.CharField(max_length=250)
subgroup = models.CharField(max_length=250)
number=models.PositiveIntegerField(default=1)
voltage= models.PositiveIntegerField()
comment = models.TextField(default='no comment')
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.group
forms.py
class MeasurementForm(forms.ModelForm):
class Meta:
model = Measurement
fields = ['group','subgroup','number','voltage','comment']
my views.py
def measurement(request):
if request.method == "POST":
form = MeasurementForm(request.POST, request.FILES)
if form.is_valid():
measurement = form.save(commit=False)
measurement.save()
return redirect('data:measurement')
else:
form = MeasurementForm()
context = {'form': form,}
template = 'data/measurement.html'
return render(request, template, context)
html.file
<div class="panel panel-primary">
<div class="panel-heading">
<h4>Add a measurement</h4>
</div>
<div class="panel-body">
<form method='POST' enctype="multipart/form-data">
{% csrf_token %}
{{ form|crispy }}
<button type = 'submit' class="btn btn-success">Save</button>
</form>
</div>
</div>
What I would like to have though is the fields group, subgroup and number to be automatically generated according to what I entered before.
For example, first measurement I enter:
Group:House Subgroup:Light Number:1 Voltage: 10 Comment: No comment
Once I click save I want the fields Group, Subgroup and Number to have the following information already:
Group:House Subgroup:Light Number:2 Voltage: 12 Comment: No comment
The next one:
Group:House Subgroup:Light Number:3 Voltage: 15 Comment: No comment
In order to add only my measurement and save time. However that does not mean that I can't change the Group, Subgroup or Number fields.

Related

Show item details together with item name in forms dropdown

currently I'm trying to show part quantity (quan) together with part name in the dropdown. I have a Part table that carries the part name and part quantity and this table called as ForeignKey into the Order table. So, in the Order form during choose the part name from the part dropdown, I would like to show part quantity as well besides the part name. Any idea to make it like that?
models.py
class Part(models.Model):
partno = models.CharField(max_length=50)
partname = models.CharField(max_length=50)
quan = models.PositiveIntegerField(default= 0)
def __str__(self):
return '{}, quantity - {}'.format(self.partname, self.quan)
class Order(models.Model):
supplier = models.ForeignKey(Supplier, on_delete=models.CASCADE)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
part = models.ForeignKey(Part, on_delete=models.CASCADE)
views.py
def create_order(request):
from django import forms
form = OrderForm()
if request.method == 'POST':
for form_data in forms_data:
forms = OrderForm(request.POST)
if forms.is_valid():
supplier = forms.cleaned_data['supplier']
product = forms.cleaned_data['product']
part = forms.cleaned_data['part']
order = Order.objects.create(
supplier=supplier,
product=product,
part=part,
)
return redirect('order-list')
context = {
'form': form
}
return render(request, 'store/addOrder.html', context)
HTML
<form action="#" method="post" id="form-container" novalidate="novalidate">
{% csrf_token %}
<div class="form-group">
<label for="product" class="control-label mb-1">Product</label>
{{ form.product }}
</div>
<div class="form-group">
<label for="supplier" class="control-label mb-1">Supplier</label>
{{ form.supplier }}
</div>
<div class="form-group">
<label for="part" class="control-label mb-1">Part Name</label>
{{ form.part }}
</div>
</form>
You will have to write "__ str __"(without spaces between str and __) method for model 'Part'
def __str__(self):
return '{}, quantity - {}'.format(self.partname, self.quan)
Check this post also: What is doing __str__ function in Django?

Django - Why is this random text rendering when I get errors upon form submission attempt?

I have a page with a form that takes in an employee # (using foreignkey), and when it is submitted it verifies that this employee # is in fact in another model (Salesman), and checks if 'WF' is in the team field for this employee. While the logic works and everything is being displayed, I keep getting this random bold text under the box Salesman object (406) (or whichever number I entered that would give me an error) after submitting the form, along with the proper error on top.
I think this is related to the foreignkey field part, but I'm not sure how to prevent this from showing up when there are errors.
models.py
class EmployeeWorkAreaLog(TimeStampedModel, SoftDeleteModel, models.Model):
employee_number = models.ForeignKey(Salesman, on_delete=models.SET_NULL, null=True, blank=False)
...
def __str__(self):
return self.employee_number
forms.py
class WarehouseForm(AppsModelForm):
class Meta:
model = EmployeeWorkAreaLog
widgets = {
'employee_number': ForeignKeyRawIdWidget(EmployeeWorkAreaLog._meta.get_field('employee_number').remote_field, site, attrs={'id':'employee_number_field'}),
}
fields = ('employee_number', 'work_area', 'station_number')
def clean_employee_number(self):
employee_number = self.cleaned_data.get('employee_number')
if 'WF' in employee_number.team:
raise forms.ValidationError("Employee not valid, please contact manager")
else:
pass
return self.cleaned_data
views.py
class EnterExitArea(CreateView):
model = EmployeeWorkAreaLog
template_name = "operations/enter_exit_area.html"
form_class = WarehouseForm
def form_valid(self, form):
emp_num = form.cleaned_data['employee_number']
area = form.cleaned_data['work_area']
station = form.cleaned_data['station_number']
if 'enter_area' in self.request.POST:
form.save()
EmployeeWorkAreaLog.objects.filter((Q(employee_number=emp_num) & Q(work_area=area) & Q(time_out__isnull=True) & Q(time_in__isnull=True)) & (Q(station_number=station) | Q(station_number__isnull=True))).update(time_in=datetime.now())
return HttpResponseRedirect(self.request.path_info)
elif 'leave_area' in self.request.POST:
form.save()
return HttpResponseRedirect(self.request.path_info)
enter_exit_area.html
{% extends "base.html" %}
{% block main %}
<form id="warehouseForm" action="" method="POST" novalidate >
{% csrf_token %}
<div>
<div style="color: red">{{ form.employee_number.errors.as_text }}</div>
<div>
<label>Employee</label>
{{ form.employee_number }}
</div>
<!-- ... More fields ... -->
</div>
<div>
<div>
<button type="submit" name="enter_area" value="Enter">Enter Area</button>
<button type="submit" name="leave_area" value="Leave">Leave Area</button>
</div>
</div>
</form>
{% endblock main %}
That is part of the ForeignKeyRawIdWidget widget and it's the representation of the selected object (the Salesman object with ID 406).
If you wanted to get rid of it you would have to create a new widget which extends ForeignKeyRawIdWidget and removes that bit from the template. Here you can see how ForeignKeyRawIdWidget and its template look like.
Alternatively, and possibly better, you could consider to define the __str__ method of the Salesman model to show something more meaningful, in the same way you did for EmployeeWorkAreaLog.

Django forms with variable user entries

I want to create a django form that captures user entry such as name, address, age. For this type of information I can create a model such as
class GeneralUserInfo(models.Model):
firstname = models.CharField()
lastname = models.CharField()
address = models.CharField()
# etc....
However, I also want to capture maybe some information like their class schedule or family information.
class UserSchedule(models.Model):
course_number = model.IntegerField()
course_name = model.CharField()
# etc....
class FamilyInfo(models.Model):
family_member_type = models.CharField(choices = MEMBER_CHOICES) # mother, father, sibling
family_member_name = models.CharField() # jon doe
# etc....
where by each user, the number of courses and number of family members could vary.
I would like the form to look something like below
with a simple submit button to send things off to be saved.
My question is, how should I structure the form template considering there are multiple models?
The answer to the above question can take a couple of forms. I'll rewrite the example above to add more context.
Say there's a student, Ashley, with college course work (say she's taking 4 course) and with family (mom, pop, sis, bro). I'd like to capture all this information for Ashley. So I've written the following models.py
class Student(models.Model):
firstname = models.CharField()
lastname = models.CharField()
address = models.CharField()
# etc....
class Course(models.Model):
user = models.ForeignKey(GeneralUserInfo, on_delete = models.CASCADE)
course_number = model.IntegerField()
course_name = model.CharField()
# etc....
class Family(models.Model):
user = models.ForeignKey(GeneralUserInfo, on_delete = models.CASCADE)
family_member_type = models.CharField(choices = MEMBER_CHOICES) # mother, father, sibling
family_member_name = models.CharField() # jon doe
# etc....
Next, what is needed is to use inlineformset_factory inside your views.
You could potentially have two views in views.py. One that creates the student, and another that edits the information belonging to that student.
from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from .forms import StudentForm
from django.forms import inlineformset_factory
from .models import Student, Course, Family
#login_required
def createstudent(request):
context = {'studentform': StudentForm}
if request.method == "POST":
form = StudentForm(request.POST)
if form.is_valid():
instance = form.save(commit = False) # https://www.youtube.com/watch?v=2h57cqFRcqg
instance.user = request.user
instance.save()
messages.success(request, "Saved new contact!")
return redirect('home')
return render(request, 'mainapp/createstudent.html', context)
#login_required
def editview(request, id):
student = Student.objects.get(pk = id)
CourseFormSet = inlineformset_factory(Student, Course, fields = ('name', 'skill'), extra=5, max_num=5)
FamilyFormSet = inlineformset_factory(Student, Family, fields = ('name', 'skill'), extra=5, max_num=5)
if request.method == "POST":
courseformset = CourseFormSet(request.POST, instance = contact)
Familyform = FamilyFormSet(request.POST, instance = contact)
if courseformset.is_valid():
courseformset.save()
if Familyform.is_valid():
Familyform.save()
if courseformset.is_valid() or Familyform.is_valid():
messages.success(request, "Saved new information")
return redirect('editview', id=id)
courseformset = CourseFormSet(instance = contact)
Familyform = FamilyFormSet(instance = contact)
context = {'courseformset': courseformset, 'title': 'Edit View', 'Familyform': Familyform}
return render(request, 'mainapp/editview.html', context)
Then inside an edit view template, editview.html
{% extends "mainapp/base.html" %}
{% block content %}
<h1>{{ title }}</h1>
<br>
<h5>Edit the form below</h5>
<br>
<form method = "POST">
<br>
<h2>Courses</h2>
<br>
{% csrf_token %}
{{ courseformset.management_form }}
{% for form in courseformset %}
<article class="media content-section">
<div class="media-body">
{{ form.as_p }}
</div>
</article>
{% endfor %}
<br>
<h2>Family</h2>
<br>
{{ Familyform.management_form }}
{% for form in Familyform %}
<article class="media content-section">
<div class="media-body">
{{ form.as_p }}
</div>
</article>
{% endfor %}
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Submit</button>
</div>
</form>
{% endblock content %}
This is just an example. However, for a whole project example, please see: https://github.com/Johnnyboycurtis/onlineforms-project/

MultiValueDictKeyError when I trying to post image

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.

same row multiple times in a form in django

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).

Categories

Resources