Hi guys,
I have this models:
class Pais(models.Model):
nome = models.CharField('Nome', max_length=50)
class Brinq(models.Model):
descricao = models.CharField('Nome', max_length=50)
class Filhos(models.Model):
nome = models.CharField('Nome', max_length=50)
idade = models.IntegerField('Idade')
pai = models.ForeignKey('Pais')
brinq = models.ForeignKey('Brinq', related_name='Brinq')
This view:
def editPai(request, idpai=None):
if idpai:
pai = Pais.objects.get(id=idpai)
else:
pai = None
ItensInlineFormSet = inlineformset_factory(Pais, Filhos, form=FilhosForm, extra=1)
formPais = PaisForm()
formsetItens = ItensInlineFormSet(instance=pai)
return render_to_response("base.html", {
"formPais": formPais, "formsetItens": formsetItens
}, context_instance=RequestContext(request), )
and this forms:
class PaisForm(ModelForm):
class Meta:
model = Pais
class FilhosForm(ModelForm):
class Meta:
model = Filhos
Ok, How can I get "descricao" value from "Brinq" model in my template? I think it's a simple question but, I tried looking, looking and looking again from internet and I don't find anything about this.
I start to thing it's not possible to do it using django, I want to believe that I'm wrong, but as I said, I didn't find anything about this in internet.
I try:
{% for form in formsetItens %}
<tr>
<td> {{ form.nome }}</td>
<td> {{ form.idade }}</td>
<td> {{ form.brinq__descricao }}</td>
</tr>
{% endfor %}
and {{ form.brinq.descricao}} to, and nothing... :(
Can anyone help me with this problem?
Regards,
You are trying to iterate over a FormSet. As the docs say "The formset gives you the ability to iterate over the forms in the formset and display them as you would with a regular form".
So you can for example do the following to display all the fields included in the form:
{% for form in formsetItens %}
{{ form.as_table }}
{% endfor %}
..or if it fits your use case you could wrap each form into a form tag, and loop over the form fields:
{% for form in formsetItens %}
<form action="/contact/" method="post">
{% for field in form %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
</div>
{% endfor %}
<p><input type="submit" value="Send message" /></p>
</form>
{% endfor %}
Related
In my Django application, I have a form with Parent/Child model objects laid out using loop. To dynamically add child form instances, I am using Django dynamic formset.
Every thing works fine including saving of user inputs without hassle. So far, so good.
However, now my user wants that I place one button before a particular field (spl_instructions) in each of the dynamically rendered rows (of fields). The instant field spl_instructions (of the child table) is a CharField of 255 chracters and is being rendered as Textarea in the page. The "button" is intended to be used to open the field spl_instructions if and when there is a need to enter text in the field. This route is being taken to conserve space.
models.py
class ProductAssy(models.Model):
prod_assy_id = models.AutoField(primary_key=True, ...)
prod_assy_num = models.CharField(max_length=24, ...)
prod_assy_type = models.ForeignKey(MaterialType, ...)
short_text = models.CharField(max_length=55, verbose_name="Description")
# ... Rest of the fields
class BillOfMatlItems(models.Model):
bom_item_id = models.AutoField(primary_key=True, ...)
prod_assy_id = models.ForeignKey(ProductAssy, ...)
short_text = models.CharField(max_length=55, verbose_name="Description")
spl_instructions = models.CharField(max_length=255, ...)
# ... Rest of the fields
forms.py
class CreateProdAssyForm(forms.ModelForm):
class Meta:
model = ProductAssy
fields = (...)
class CreateAssyBomForm(forms.ModelForm):
class Meta:
model = BillOfMatlItems
fields = (...)
widgets = {
'short_text': forms.TextInput(attrs={'style': 'width:300px; text-align:right;'}),
# ...
# The Button needs to be placed HERE
'spl_instructions': forms.Textarea(attrs={'rows':4, 'cols':35, 'placeholder': 'type spl inst'}),
}
exclude = ()
Template
...
<table id="...>
{{ bill_of_matl_list.management_form }}
{% for form in bill_of_matl_list.forms %}
...
{{ form.non_field_errors }}
{% if forloop.first %}
<thead id="...>
<tr>
{% for field in form.visible_fields %}
<th>{{ field.label|capfirst }}</th>
{% endfor %}
</tr>
</thead>
{% endif %}
<tr class="{% cycle 'row1' 'row2' %} formset_row">
{% for field in form.visible_fields %}
...
<td>
{{ field.errors.as_ul }}
{{ field }}
</td>
...
{% endfor %}
</tr>
{% endfor %}
</table>
...
Partial image of the page with fields and the column where the button is needed is shown below (please note that, an image of button "Open Pad" has been placed in the image where an actual button is needed):
My question is: How can a button be placed in the column before the field 'spl_instructions' (Textarea )?
You can add a condition in your loop where you render the form:
{% for field in form.visible_fields %}
...
<td>
{{ field.errors.as_ul }}
{% if field.id == 'id_spl_instructions' %}
<button>Button</button>
{% endif %}
{{ field }}
</td>
{% endfor %}
I'm having trouble getting my form to save in Dajngo due to the following error on validation:
<ul class="errorlist"><li>pt_medical_condition<ul class="errorlist"><li>Select a valid choice.
['anx', 'Bip'] is not one of the available choices.
>pt_surgical_history<ul class="errorlist"><li>Select a valid choice.
['bre', 'pca'] is not one of the available choices.
I've got this model:
class pt_data(models.Model):
condition_choices = [('ane', 'Anemia'), ('anx', 'Anxiety'), ('art', 'Arthritis'),
('ast', 'Asthma'), ('Bip', 'Bipolar'), ('ca', 'Cancer'), ('clo', 'Clotting disorder'),
('chf', 'CHF'), ('mdd', 'Depression'), ('cop', 'COPD'), ('ger', 'GERD'),
('gla', 'Glaucome'), ('hiv', 'HIV/AIDS'), ('ibs', 'IBS/Crohn\'s'),
('hld', 'High cholesterol'), ('ckd', 'Kidney disease'), ('ner', 'Nerve/Muscle disease'),
('ocd', 'OCD'), ('ost', 'Osteoporosis'), ('pai', 'Pain disorder'), ('pts', 'PTSD'),
('sch', 'Schizophrenia'), ('sei', 'Seizures'), ('sca', 'Sickle cell anemia'),
('su', 'Substance use disorder'), ('thy', 'Thyroid disease')]
surgery_choices = [('app', 'Appendix removal'), ('bra', 'Brain surgery'),
('bre', 'Breast surgery'), ('cabg', 'CABG'), ('pca', 'Cardiac stent'),
('cho', 'Gallbladder removal'), ('col', 'Bowel surgery'), ('csec', 'C-section'),
('fra', 'Bone fracture repair'), ('her', 'Hernia repair'), ('hys', 'Uterus removal'),
('joi', 'Joint replacement'), ('lun', 'Lung surgery'), ('spi', 'Spine/back surgery'),
('thy', 'Thyroid surgery'), ('ton', 'Tonsil removal'), ('strf', 'Tubal ligation'),
('strm', 'Vasectomy'), ('wei', 'Weight reduction surgery')]
pt_medical_condition = models.CharField(max_length=100, blank=True, null=True,
choices=condition_choices)
pt_surgical_history = models.CharField(max_length=100, blank=True, null=True, choices=surgery_choices)
And this form:
class ptForm(forms.ModelForm):
class Meta:
model = pt_data
fields = ('__all__')
widgets = {
'pt_medical_condition': CheckboxSelectMultiple(attrs={'class': 'cond_checkbox'}),
'pt_surgical_history': CheckboxSelectMultiple(attrs={'class': 'surg_checkbox'}),
}
And this is my HTML:
{% for check in form.pt_medical_condition %}
{% if forloop.counter|divisibleby:3 %}
<div> </div>
{% endif %}
<label class='mx-2' id="{{ check.choice_label }}">
{{ check.tag }} {{ check.choice_label }}
</label>
{% endfor %}
{% for check in form.pt_surgical_history %}
{% if forloop.counter|divisibleby:2 %}
<div> </div>
{% endif %}
<label class='mx-2' id="{{ check.choice_label }}">
{{ check.tag }} {{ check.choice_label }}
</label>
{% endfor %}
The HTML is rendered just fine, the problem seems to arise on submit. It looks like the correct characters are there, however they are surrounded by incorrect characters. The following "anx" is appropriate but won't be validatated by Django because everything else that has been tacked on 'anx'. Could it be a problem with posting the information with AJAX? Or maybe using a CSRF cookie to POST? Has anyone else encountered this problem? Any suggestions would be helpful.
I have the following model:
class Portfolio(models.Model):
id = models.AutoField(primary_key=True)
member = models.ForeignKey(Member, on_delete=models.CASCADE)
image = models.ImageField(upload_to='portraits/', default='/images/some_image.png')
For that I made the ModelForm:
class PortfolioForm(forms.ModelForm):
class Meta:
model = Portfolio
exclude = ['id']
I need many of those in one template so I am creating them in the Following way in my view
def portfolio_form(request, pk):
...
formset = PortfolioFormSet(queryset=Portfolio.objects.filter(pk__in=list_of_ids))
for x in p]
finally in the html I have this:
<form enctype="multipart/form-data" action="{% url 'elec:portfolio_form' pk=id %}" method="POST">{% csrf_token %}
...
{{ formset.management_form }}
{% for form in formset.forms %}
<tr>{% for field in form %}
{% if field.name == 'image' %}
<td><img src="{{field.image.url}}"></td>
{% else %}
<td align="center" valign="middle">{{field}}</td>
{% endif %}
{% endfor %}</tr>
{% endfor %}
<input type="submit" class="btn btn-default" value="Save and Refresh" />
</form>
Now what I expect to see is the image that I am saving into that Model. The if statement is coming back as false but why?. What am I doing wrong? Everywhere I looked it should work like this.
Also I have added the request.FILES in PortfolioForm with that the instance is not called how can I fix that?
OK I found the solution in Stackoverflow since I used some other words to find a solution.
what you need to do in the template instead of :
{<td><img src="{{field.image.url}}"></td>}
is this :
{<td><img src="{{form.instance.image.url}}"></td>}
(I'm quite new at django, i googled for this a lot but could not find an answer, so i hope you don't mind the low level question)
There are these Classes:
class Cl(models.Model):
user = models.ForeignKey(User,editable=False)
title = models.CharField(max_length=100)
class Member(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField()
cl = models.ForeignKey(Cl)
class ClForm(ModelForm):
class Meta:
model = Cl
I want to make a page where i can create an Object of Cl and some related Member Objects (I plan to use django-dynamic-formset but that is not the point here). My view looks like this:
class NewView(TemplateView):
def get(self, request):
cform = ClForm(prefix="cl", instance=Cl(user=request.user))
MemberFormSet = modelformset_factory(Member)
memberfs = MemberFormSet(queryset=Member.objects.none())
return render_to_response(self.template_name, {'cl_form': cform, 'memberformset': memberfs}, context_instance=RequestContext(request))
def post(self,request):
cform = ClForm(request.POST, prefix="cl", instance=Cl(user=request.user))
MemberFormSet = modelformset_factory(Member)
memberfs = MemberFormSet(request.POST)
if cform.is_valid() and memberfs.is_valid():
new_cl = cform.save()
new_members = memberfs.save(commit=False)
for mf in new_members:
mf.cl = new_cl
mf.save()
return HttpResponseRedirect("unimportant")
return render_to_response(self.template_name, {'cl_form': cform, 'memberformset': memberfs}, context_instance=RequestContext(request))
My template looks like this:
<form id="myForm" method="post" action="">
{% csrf_token %}
{{ memberformset.management_form }}
<table>
{{ cl_form }}
<tr><th colspan="2">Members</th></tr>
{% with memberformset.empty_form as form %}
<div id="id_empty_form" style="display:none;">
{{ form }}
</div>
{% endwith %}
</table>
<input type="submit" value="Save" />
</form>
My problem is now, that the member is not stored. Also, the memberfs.is_valid() doens't complain, if e.g. the Email field is not filled out correctly.
I also tried the inlineformset_factory, but that didn't worked either.
I think the problem is that you are using the "empty_form" in that template. The correct way of using the formset is described here. In your example, you should write:
<form id="myForm" method="post" action="">
{% csrf_token %}
{{ memberformset.management_form }}
<table>
{{ cl_form }}
<tr><th colspan="2">Members</th></tr>
<!-- THIS IS NOT NECESSARY UNLESS YOU WANT TO ADD FORMS WITH JAVASCRIPT-->
<div id="id_empty_form" style="display:none;">
{{ memberformset.empty_form }}
</div>
<!-- END NOT NECESSARY-->
{% for form in memberformset.forms %}
{{ form }}
{% endfor %}
{% endwith %}
</tbody>
</table>
<input type="submit" value="Save" />
</form>
well it's quiet simple.
2 models with ManyToMany relation:
class Artist(models.Model):
name = models.CharField(max_length=100, unique=True)
slug = models.SlugField(max_length=100, unique=True,
help_text='Uniq value for artist page URL, created from name')
birth_name = models.CharField(max_length=100, blank=True)
class Song(models.Model):
title = models.CharField(max_length=255)
slug = models.SlugField(max_length=255, unique=True,
help_text='Unique value for product page URL, create from name.')
youtube_link = models.URLField(blank=False)
artists = models.ManyToManyField(Artist)
my view suppose to display latest 5 songs:
def songs(request, template_name="artists/songs.html"):
song_list = Song.objects.all().order_by('-created_at')[:5]
return render_to_response(template_name, locals(),
context_instance=RequestContext(request))
and the problem is in the template... i want to display the artist name
but just dont realy know how to do it, i tried:
{% for song in song_list %}
{{ artists__name }} - {{ song.title }}
{% endfor %}
would appreciate any help !
Try changing your template code to:
{% for song in song_list %}
{% for artist in song.artists.all %}
{{ artist.name }} - {{ song.title }}
{% endfor %}
{% endfor %}
artists is another type of manager, so you have to iterate through artists.all and print the name attribute of each element.
Well, I worked on above solution of Mr #Dominic Rodger, but because am using Django version 3.2 it did not worked for me. Therefore, the problem may remain the same but according to how Django version changes, the way to solve them sometimes become different. If you're using Django 3.x use below solution.
In views.py
def songs(request):
song_list = Song.objects.all().order_by('-created_at')[:5]
song_list = {'song_list':song_list}
return render(request, 'artists/songs.html', song_list)
In your HTML Template use code below
<div class="table-responsive">
<table class="table table-bordered" id="dataTable" width="100%" cellspacing="0">
<thead>
<tr>
<th>Artist - Song Title</th>
</tr>
</thead>
<tbody>
{% for song in song_list %}
</tr>
<td>{{ song.artist.name }} - {{ song.title }}</td>
<tr>
{% endfor %}
</tbody>
</table>
In urls.py
path('songs/', views.songs, name='songs'),
If you're running source code from localhost, then type on your browser http://127.0.0.1:8000/songs/
Thank you ....