How to manually make field in HTML? Django - python

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

Related

Django UpdateView: How to display the original values?

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" />

Django inline formset will always create new object instead of update them

I've 2 model First and Second with a FK from Second to First. I created a form for the 2 class and a inline formset for Second. On template I manually designed my form and with jQuery I'm able to add dynamic forms of Second.
On UpdateView the form is correctly populated, but when I submit the form, all Second instances are created again with new ids instead of updating them. I double checked that on HTML there are name=PREFIX-FORM_COUNT-id with correct ids, but seems that Django ignores it.
I'm using Django 2.2.12 & Python 3.6
Here what I made:
models.py
class First(models.Model):
name = models.CharField(max_length=100, null=False)
class Second(models.Model):
first= models.ForeignKey(First, null=False, on_delete=models.CASCADE)
number= models.FloatField(null=False, default=0)
form.py
class FirstForm(forms.ModelForm):
class Meta:
model = First
fields = "__all__"
class SecondForm(forms.ModelForm):
class Meta:
model = Second
fields = "__all__"
SecondsFormset = inlineformset_factory(First, Second, SecondForm)
view.py
class FirstUpdateView(UpdateView):
template_name = "first.html"
model = First
form_class = FirstForm
context_object_name = "first_obj"
def get_success_url(self):
return reverse(...)
def forms_valid(self, first, seconds):
try:
first.save()
seconds.save()
messages.success(self.request, "OK!")
except DatabaseError as err:
print(err)
messages.error(self.request, "Ooops!")
return HttpResponseRedirect(self.get_success_url())
def post(self, request, *args, **kwargs):
first_form = FirstForm(request.POST, instance=self.get_object())
second_forms = SecondsFormset(request.POST, instance=self.get_object(), prefix="second")
if first_form .is_valid() and second_forms.is_valid():
return self.forms_valid(first_form , second_forms)
...
.html (putted only essential tags)
<form method="post">
{% csrf_token %}
<input type="text" id="name" value="{{ first_obj.name }}" name="name" required>
<input type="hidden" name="second-TOTAL_FORMS" value="0" id="second-TOTAL_FORMS">
<input type="hidden" name="second-INITIAL_FORMS" value="0" id="second-INITIAL_FORMS">
<input type="hidden" name="second-MIN_NUM_FORMS" value="0" id="second-MIN_NUM_FORMS">
<div id="seconds_container">
{% for s in first_obj.second_set.all %}
<input type="hidden" name="second-{{forloop.counter0}}-id" value="{{s.pk}}">
<input type="hidden" name="second-{{forloop.counter0}}-first" value="{{first_obj.pk}}">
<input type="number" min="0" max="10" step="1" value="{{s.number}}" name="second-{{forloop.counter0}}-number" required>
{% endfor %}
</div>
<button class="btn btn-success" type="submit">Update</button>
</form>
I checked how Django creates forms and it will only add DELETE checkbox on it, but all other infos are correctly stored into the formset. When I do .save() it will create new Second element on db instead of change them.
What am I missing?
I solved this!
I setted TOTAL_FORMS and INITIAL_FORMS with wrong values. From Django's docs:
total_form_count returns the total number of forms in this formset. initial_form_count returns the number of forms in the formset that were pre-filled, and is also used to determine how many forms are required. You will probably never need to override either of these methods, so please be sure you understand what they do before doing so.
So the correct way to use it is:
In views:
Generate FormSets with extra=0
In HTML:
Set TOTAL_FORMS with number of rows you are POSTing and change it dinamically if dinamically add/remove rows;
Set INITIAL_FORMSwith number of alredy filled rows (editing/deleting) and never change this;
To delete a pre-filled row use DELETE checkbox instead of removing entire row;
For me i wanted to update my images, everything suggested here and every other forums about handling the hidden form didn't worked until i changed this.
product_img_form = ProductImageFormSet(data=request.FILES or None, instance=your_model_instance)
To this.
product_img_form = ProductImageFormSet(request.POST or None, request.FILES or None, instance=your_model_instance)
Then like magic this ugly error stopped showing, and my new image successfully got updated
<tr><td colspan="2">
<ul class="errorlist nonfield">
<li>(Hidden field TOTAL_FORMS) This field is required.</li>
<li>(Hidden field INITIAL_FORMS) This field is required.</li>
</ul>
<input type="hidden" name="product_images-TOTAL_FORMS" id="id_product_images-TOTAL_FORMS">
<input type="hidden" name="product_images-INITIAL_FORMS" id="id_product_images-INITIAL_FORMS">
<input type="hidden" name="product_images-MIN_NUM_FORMS" id="id_product_images-MIN_NUM_FORMS">
<input type="hidden" name="product_images-MAX_NUM_FORMS" id="id_product_images-MAX_NUM_FORMS">
</td></tr>

bootstrap-datepicker and django template, an easy way

I would like to use date picker in my template. Is there a way to omit stuff in forms.py and simply do something like:
<tr class="new">
<form method="post">
{% csrf_token %}
<td>
<input size="10" type="text" class="form-control" id="date" name="{{ form.date }}">
<script type="text/javascript">
$("#date").datepicker({format: "dd/mm/yyyy", autoclose: true});
</script>
</td>
...
That is, to use the {{ form.date }} as a name in input for example? Unfortunately this solution doesn't work for me.
You can define custom input fields with HTML or Bootstrap, as long as you let Django know, which input field in your forms.py you mean. You do this by specifying the proper id to the HTML input field.
For example, if you have a form which takes a DateField in your forms.py:
from django import forms
class YourForm(forms.Form):
some_date = forms.DateField()
# ... more stuff
Then, your proper id for the input would be id='id_some_date'.
(And name would be name='some_date'.)
EDIT: In your case, you can try id='{{ form.date.id_for_label }}', so you do not need to hardcode the id.
When the template is rendered, {{ form.date }} would render to the HTML input form, which is the form you specified in forms.py.

How to get max_length of CharField in django template

I'm trying to set maxlength html attribute in django template but when I try to get the value I specified in my model by using {{field.max_length}} nothing is displayed. I can get any other field value just fine.
Relevant Snippet:
{% for field in form %}
{% if "_color" in field.name %}
<div class="control-group">
<label class="control-label">{{field.label}}</label>
<input type="text" ng-init="{{field.name}}='{{field.value}}'" ng-model="{{field.name}}" ng-change="{{field.name}}_picker={{field.name}}" placeholder="{{field.label}}" maxlength="{{field.max_length}}">
The field you get by iterating trough your form is actually a forms.BoundField, and does not have all the attributes of your Field. You can access the Field instance through the field attribute of your BoundField. So, {{ field.field.max_length }} should work.

Django BooleanField always checked even when value is false

I have a BooleanField in a standard Django Form defined as:
my_boolean_field = BooleanField(initial=True)
when I render my form with initial data, and my_boolean_field is set to an initial value of False, when the form renders it is still checked despite the fact that the value is false as the html shows:
<p><label for="id_2">my_boolean_field</label>:
<input checked="checked"
type="checkbox"
name="2"
value="False"
id="id_2" />
</p>
Has anyone else experienced this, or knows how to fix it so that when the initial data/input value is false then the checkbox is not checked?
UPDATE: Even if I remove the initial=True argument from the BooleanField the same thing happens.
Firstly, you can't have required=False on a BooleanField, use NullBooleanField instead:
https://docs.djangoproject.com/en/dev/ref/models/fields/#booleanfield
https://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.NullBooleanField
let me know what the HTML output of the new widget is once you've done this?
EDIT
I assumed that this is a ModelForm. Is this a regular django.forms.Form?
EDIT 2
My test form:
from django import forms
class MyForm(forms.Form) :
"""The test form"""
my_boolean_field = forms.BooleanField(initial=True)
My template:
<div>
{{ form.my_boolean_field.label_tag }}
{{ form.my_boolean_field }}
{{ form.my_boolean_field.errors }}
</div>
This is what I get for output when I view page source. EDITED
<div>
<label for="id_my_boolean_field">My boolean field</label>
<input type="checkbox" name="my_boolean_field" id="id_my_boolean_field" />
</div>
My View NEW
form = MyForm(initial={'my_boolean_field':False})
What you are showing and what I'm seeing aren't matching up. paste your full form, view and template please?
EDIT 3
I only see output like this:
<div>
<label for="id_my_boolean_field">My boolean field</label>
<input checked="checked" type="checkbox" name="my_boolean_field" value="False" id="id_my_boolean_field" />
</div>
when I put False in quotes:
form = FormLogin(initial={'my_boolean_field':"False"})
I'm posting this answer because I had the same problem and Francis's answer didn't help me.
I eventually found the solution was to re-run manage.py syncdb. My fields had previously been IntegerField and I had converted them to BooleanField. BooleanField read the presence of value="0" in the database as being initialized and checked. This is regardless of what your model says. You want to see:
<input checked="checked" id="id_cost_track_destruction" name="cost_track_destruction" type="checkbox">
when you inspect an element. Since this bug shows up in the Django Admin panel, it has nothing to do with your forms.py.
This is purely a model and database issue. Try regenerating your database if you've changed your models.py field types.
For those who are using ModelForms, this is what worked for me:
password_required = forms.CheckboxInput(attrs={'checked' : ''})
This correctly generates the checkbox with it unchecked.

Categories

Resources