I'm using Django UpdateView to update a Model class
class TestCase(models.Model):
name = models.CharField(max_length=200)
executable = models.CharField(max_length=1023)
parameter_value_list = models.TextField()
test_type = models.CharField(max_length=200)
created_by = models.CharField(max_length=200, default = "user")
create_datetime = models.DateTimeField("testcase created on", auto_now = True)
My view is as:
class MyEditCaseView(UpdateView):
model = TestCase
fields = ['name', 'executable', 'parameter_value_list', 'test_type']
template_name_suffix = '_update_form'
def get_success_url(self):
return reverse("myApp:testCase")
My template is as:
<form action="{% url 'myApp:editCase' case.id %}" method="post">
{% csrf_token %}
<input type="submit" value="Edit">
</form>
urls:
path('editCase/<int:pk>/', views.MyEditCaseView.as_view(), name='editCase')
It works OK, but I have 3 questions:
The update view page pop out is blank for all fields even they have old values. I won't like to change all fields. How to show the old values, if I don't want update all fields?
The default lay out of the update view page seems not elegant. Can I change the style?
When clicking the input box, saying Name field, a drop down list will show to give some historic values I had used as candidates. Can I delete or change this historic list?
Django form can be spread out.
<!--begin::Form-->
<form method="post">
{% csrf_token %}
{% field in form.fields %}
<input name="{{ field.name }}" type="text" value="{{ field.value }}"/>
{% endfor %}
</form>
<!--end::Form-->
The update view page pop out is blank for all fields even they have old values. I won't like to change all fields. How to show the old values, if I don't want update all fields?
You can use default value as above example, value field.
The default lay out of the update view page seems not elegant. Can I change the style?
You can use class attribute in each input fields.
When clicking the input box, saying Name field, a drop down list will show to give some historic values I had used as candidates. Can I delete or change this historic list?
If you set autucomplete attribute as off, then any history would not appear.
<input type="text" autocomplete="off" />
Related
I'm new to Django and I'm currently trying to create a form which should contain input fields for all existing objects of another model. Let's say that I would like to manage my supplies at home and make sure that I have enough of various products at diffect storage locations.
For example, I would like to make sure that the storage locations bathroom and basement should always have plenty of the supply toilet paper. I don't need toilet paper in the location kitchen. The storage locations are pre-defined and available through a model. I couldn't find any way to create a form for Supply which dynamically generates form fields for MinimumQuantity objects based on all available StorageLocation objects.
My form should look like this when creating the supply "toilet paper":
supply name: <input example: "toilet paper">
minimum supply quantities
bathroom - amount: <input example: 6>
kitchen - amount: <input example: 0>
basement - amount: <input example: 3>
I'm a bit lost here and any hints would be much appreciated.
This is my current code (shortened):
models.py:
class Supply(models.Model):
name = models.CharField(max_length=50)
class StorageLocation(models.Model):
name = models.CharField(max_length=50)
class MinimumQuantity(MinimumQuantity):
storage_location = models.ForeignKey(StorageLocation, on_delete=models.PROTECT)
supply = models.ForeignKey(Supply, on_delete=models.PROTECT)
amount = models.IntegerField()
views.py:
class SupplyCreateView(CreateView):
model = Supply
template_name = "supplies_form.html"
fields = [ 'name', ]
supplies_form.html:
<div class="card-body">
{% csrf_token %}
{{ form|crispy }}
</div>
I stumbled upon various related questions on stackoverflow and other sites and fiddled around with formsets, but my issues seem to be that:
I have a one-to-many from Supply to MinimumQuantity and can't think of any way to tell Supply about it, and
while all StorageLocation objects exist already, the MinimumQuantity objects don't.
Have I perhaps even made this construct too complicated and is there perhaps a way to solve the whole thing without the MinimumQuantity model at all? Thanks!
In this, we have to use a ModelForm and set the fields attribute to include the fields of the MinimumQuantity model that you want to include in the form. In your case, this would be the storage_location field and the amount field.
Now, First add this in your code and make changes to SupplyCreateView:
from django.forms import ModelForm
class MinimumQuantityForm(ModelForm):
class Meta:
model = MinimumQuantity
fields = ['storage_location', 'amount']
class SupplyCreateView(CreateView):
model = Supply
template_name = "supplies_form.html"
form_class = MinimumQuantityForm
fields = ['name']
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['minimum_quantities'] = MinimumQuantity.objects.all()
return context
and then in your supplies_form.html do like this:
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<div class="card-body">
<h4>Minimum supply quantities</h4>
{% for minimum_quantity in minimum_quantities %}
<div class="form-group">
<label for="id_{{ minimum_quantity.storage_location.name }}">{{ minimum_quantity.storage_location.name }}</label>
<input type="number" name="{{ minimum_quantity.storage_location.name }}" id="id_{{ minimum_quantity.storage_location.name }}" required>
</div>
{% endfor %}
<button type="submit" class="btn btn-primary">Save</button>
</div>
in forms.py
class PlaceOrder(forms.ModelForm):
class Meta:
model = Order
fields = ["Product_ID","HowMany","DateSubmit",]
to call a form i usually use
{{ Form }}
that will render the form automatically
but is it possible to make it manually?
for example i want the form to be exactly like this
<input id="Product_ID" type="hidden" value="{{ Product.PId }}" >
<input id="HowMany" type="text">
<input id="DateSubmit" type="hidden" value="{{ date }}" >
i have tried wrapping them in
{% for field in form %}
but it gave the wrong output
Sorry if this is confusing
but i don't really know how to explain it,
i am still new to Django
You should be able to access individual fields in the form using something like
{{Form.Product_ID}}
which will give you the Product_ID field widget.
Now if you want to access the already pre-filled data you should be able to do so with
{{Form.Product_ID.label}}
or
{{Form.Product_ID.value}}
Also check:
https://docs.djangoproject.com/en/dev/topics/forms/#looping-over-the-form-s-fields
I am trying to create a form that is a list of cars with one field being a BooleanField. I want this to appear as a form with the BooleanField being a checkbox. If the user checks this, then the BooleanField will be set = True and something will happen when a POST occurs and the user is redirected to the next page.
model.py:
class Car(models.Model):
year = models.IntegerField()
make = models.CharField(max_length=30)
model = models.CharField(max_length=30)
send = models.BooleanField(default=False)
currenly the email.html looks like this:
<form action="" method="post">{% csrf_token %}
{% for car in object_list %}
<input type="checkbox" name="car" id="car{{ forloop.counter }}" value="{{ car.id }}">
<label for="car{{ forloop.counter }}">{{ car.year }} {{ car.make }} {{ car.model }}</label><br>
{% endfor %}
<input type="submit" value="Preview">
</form>
views.py
class Email(ListView):
model = Car
template_name = 'cars/email.html'
Suggestions?
I ended up adding a post() function to the ListView which processes the form data, but I am having trouble redirecting without a valid HttpResponse object and am getting an error when one of the boxes isn't checked in the form. Here is the additional post() code that I added for the time being:
def post(self, request, *args, **kwargs):
cars = Car.objects.all() # initially reset "self.send" field == False
for i in range(len(cars)):
cars[i].send = False
cars[i].save()
cars = Car.objects.filter(id__in=request.POST.getlist('car'))
for i in cars:
i.send = True
i.save()
return HttpResponseRedirect(reverse('cars:email_preview'))
Any suggestions on how to make the form re-render with an error msg if no boxes are checked?
Thanks
I wish to edit ini files over web server, decided to use django, been using it for few days now. I can't figure out how to accomplish this. I have ini file structure looking like this:
{'GROUP', {PROPERTY : VALUE}}
Example when I read this kind of ini file:
[LOG]
FilePath = C:/Log
[CMD]
Level = 5
I will get my data structure filled like this:
{'LOG', {'FilePath' : 'C:/Log',},
{'CMD', {'Level', '5'}}}
Loop looks like this:
for group in settingsDict:
print group # group
for property in settingsDict[group]:
print property , # property
print settingsDict[group][property] # value
I am using ini file parser.
I am having trouble understanding how to correctly develop in django: views.py is some kind of controller for django and templates are views and model would be my ini file (probably linked with db using django model), or am I getting something wrong?
I have no problem passing this dictionary to template, making a for loop in it and creating html tags like: <input type="text" name={{ property }} value={{ value }} maxlength="100" />. But how do I then post all the edited values back to control to save them in file (or db)? I Would need all 3 values, that is GROUP, PROPERTY and VALUE.
Then I discovered django also has html widgets, which you create in views.py and then pass it to template. But this is where I stop understanding things, since I am creating widget in my controller class, but even if I am.
Shall I create a list of all django widgets and pass it to template? Same question occurs, how do I get all the widget values back to controller (views.py)?
Update (11.6.2012):
My code looks like this:
views.py
class DynForm(forms.Form):
def setFields(self, kwds):
keys = kwds.keys()
keys.sort()
for k in keys:
self.fields[k] = kwds[k]
def settings(request):
global Settings #my ini dict
kwargs = {}
for group in Settings:
for property in Settings[group]:
kwargs[property] = forms.CharField(label = property, initial = Settings[group][property])
f = DynForm()
f.setFields(kwargs)
return render_to_response('/settings.html',
{
'textWidget' : f,
})
#csrf_exempt
def save(request):
if request.method == 'POST': # If the form has been submitted...
form = DynForm(request.POST) # A form bound to the POST data
if form.is_valid(): # All validation rules pass
# process form data
# and return response
settings.html
<form action="/save/" method="post">
{% csrf_token %}
{% for field in textWidget %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label }}: {{ field }}
</div>
{% endfor %}
<p><input type="submit" value="Save" /></p>
</form>
The problem is, DynForm(request.POST) returns null so I can't get field values. My request.POST is correct, containing all fields and values. As much as I know, I am not suppose to parse request.POST data "by hands"?
OK, finally figured it out, taking me a lot of time (I am lacking a lot of python and django knowledge). I can't paste final solution because of copy right permissions, here is the concept:
Form
class DynamicForm(forms.Form):
def __init__(self,*k,**kw):
forms.Form.__init__(self,*k,**kw)
# loop over data from **kw
# create field
# set field default value
Notes about this code:
If form doesn't use super(SuperForm, self).__init__(*args, **kwargs), you must use forms.Form.__init__(self,*k,**kw) so you can append fields to form using self.fields attribute.
If you need to use default field value, use self.data[field] = defVal not initial = defVal. Form becomes unbound and you won't be able to parse data in your request.POST method. Unbound form (and with errors) will always return is_valid() False.
With this class, you have no problems parsing request.POST data. Looping over dynamic form fields looks like this:
View
for name,field in form.fields.items():
# name - field name
# form.data[name] - field value
Notes:
For the sake of simplisity use #csrf_exempt tag before POST method. See http://jordanmessina.com/2010/05/24/django-1-2-csrf-verification-failed/
Template code loops over fields in form displaying field label and value separated with :
Template
<form action="/Tris/save/" method="post">
{% csrf_token %}
{% for field in textWidget %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.non_field_errors }}
{{ field.label }}: {{ field }}
</div>
{% endfor %}
<p><input type="submit" value="Save" /></p>
</form>
Most of the solution is from here: http://jacobian.org/writing/dynamic-form-generation/ and django documentation.
I am developing a Leave of Absence Request Form for a client. The form which is filled out by an employee allows the employee to select mutiple days which he/she wants to take off. When the employee initially views the form only one date entry is shown. They can add more dates dynamically (javascript) by click an add button.
Database setup: Form_Table, Date_Table, Form_Date_ManyToMany Table (generated by Django)
I have 2 issues with Django.
1) If the employee enters 3 dates, each date field will have the same name. How can I validate each field using Django's Form or ModelForm? Here is an example of the the date field.
<input name="dates[]" />
<!-- or -->
<input name="dates" /> <!-- I have read this is the Django way -->
2) In my database I have a ManyToMany relationship with the Form and the Dates. I am sure I need ManyToMany and not simply a ForeignKey for tracking changes (this is not the question). How can I save multiple dates (in the dates table) and have the ManyToMany relationship with the form (in the forms table) using Django.?
I am relatively new to Python & Django. I switched from PHP since Django is the best framework I have found.
Edit: I guess I did not ask the correct question. Here is more information.
# Model
class Date(models.Model):
date = models.DateField()
emp_requested = models.ForeignKey(EmployeeRequested,null=True)
hr_approved = models.ForeignKey(HumanResourcesApproved,null=True)
class Form(models.Model):
pay_period = models.ForeignKey(PayPeriod)
employee = models.ForeignKey(Employee)
ack_ip = models.CharField(max_length=15, default='')
emp_signature = models.CharField(max_length=100)
date_of_hire = models.DateField()
state = models.ForeignKey(State)
scheduler = models.ForeignKey(Scheduler)
scheduler_form = models.ManyToManyField(SchedulerForm)
hr_status = models.CharField(max_length=100, default='')
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
enabled = models.BooleanField(default=True)
parent = models.ForeignKey('self',related_name='+')
root = models.ForeignKey('self',related_name='+')
dates = models.ManyToManyField(Date)
# View - this is an ajax call
def ajax_save_form(request):
form = EmployeeForm(request.POST or None)
return HttpResponse(form.is_valid())
# Form
class EmployeeForm(forms.ModelForm):
employee_name = forms.CharField(max_length=30)
employee_email = forms.EmailField()
county = forms.ModelChoiceField(queryset=County.objects.all())
job_type = forms.ModelChoiceField(queryset=JobType.objects.all())
pay_period = forms.CharField()
total_hours = forms.DecimalField()
class Meta:
model = Form
exclude = ( 'employee', 'ack_ip', 'state', 'scheduler', 'scheduler_form', 'hr_status', 'parent', 'root', 'dates',)
# HTML (template)
<!-- Stuff -->
<div id="date-group" class="control-group date-controls">
<label class="control-label" for="date">Date</label>
<div class="controls">
<div class="input-append">
<input type="text" placeholder="Click to see Calendar" name="dates[]" class="input-xlarge emp-dates" id="date">
<span class="add-on"><i class="icon-calendar"></i></span>
<a id="AddDateBtn" class="btn btn-primary"><i class="icon-plus icon-white"></i> Add additional day</a>
<br><br>
</div>
<div class="pull-left sub-controls">
<h4>Employee Section</h4>
<div class="well">
Reason for Absence:<br>
<select name="reasons[]" class="emp-reasons">
{% for reason in reasons %}
<option value="{{ reason.id }}">{{ reason.reason }}</option>
{% endfor %}
</select>
<span class="add-on emp-reason-help"><i class="icon-question-sign"></i></span>
<br><br>
Hours: <br>
<select name="hours[]">
{% for hour in hours %}
<option value="{{ hour }}">{{ hour }}</option>
{% endfor %}
</select>
<br><br>
Explanation Required:<br>
<textarea class="input-xlarge" name="explanations[]"></textarea>
</div>
</div>
</div>
</div>
<!-- Stuff -->
The Employee can have as many of the HTML blocks as they want. Using JavaScript I dynamically "copy" the html that is shown above. This allows the employee to submit multiple dates (dates[], hours[], reasons[], explanations[]). I need to save each date group (dates[i], hours[i], reasons[i], explanations[i]) in the Date Model. Then I need to have a ManyToMany relationship with the Form Model and all the dates that were submitted. How can I do this using ModelForm.
I have seen some code online that suggests that it is possible to do this:
form = EmployeeForm()
if form.is_valid():
# do relationships here
I am also at a loss of how to get the values form dates[], hours[], reasons[], and explanations[] using Django.
If you really need to store these dates in separate table with ManyToMany relationship, then you should extend your ModelForm a little bit.
First, specify the class for your dates field, which should inherit from django.forms.ModelMultipleChoiceField. In it, override the clean function, and create all the Date objects there. The function should return the list of ids of created objects (or consider returning the results of parent's clean function, passing it this list of ids). Then in your ModelForm you just specify that the field is of your new class, and then all the validation and saving will work.
Hope it will help; if I've been unclear, ask more:)