Show parent_model in django template - python

I have a variable:
m2m_links = mymodel._meta.many_to_many
This has all of the fields that are m2m in a particular model. I want the template to display the names of the models that are linked. Within my view, I can list the tables like so:
for f in m2m_links:
print f.related.parent_model
But in my template, if I try
{% for table in m2m_links %}
{{ table.related.parent_model }}<br>
{% endfor %}
I get an error: "Caught DoesNotExist while rendering"
How do I get the names of the tables to render in the template? And a further question, how do I get just the name, not something like
<class 'myapp.models.ModelName'>
which is what I have showing in my terminal from the "print" statement.

There's no reason, based on the template code you've provided that you should be getting that error. Most likely, there's something else going on in your template that is causing that.
As for your second question, the way to get a class' name is:
some_class.__name__
However, the Django template engine will not allow you to use underscored properties in the template, so your best bet is to prepare a proper list in your view:
linked_models = [m2m.related.parent_model.__name__ for m2m in mymodel._meta.many_to_many]
Then, just loop through that in your template and the all the work is already done.
UPDATE (based on comment)
You do it mostly the same way, though you have a couple of choices.
You can do a list of tuples and unpack it in the template:
linked_models = [(m2m.related.parent_model.__name__, m2m.related.parent_model._meta.verbose_name) for m2m in mymodel._meta.many_to_many]
Then, in your template:
{% for class_name, verbose_name in linked_models %}
{{ class_name }} {{ verbose_name }}
{% endfor %}
Create a list of dictionaries and reference the keys in the template:
linked_models = [{'class_name': m2m.related.parent_model.__name__, 'verbose_name': m2m.related.parent_model._meta.verbose_name} for m2m in mymodel._meta.many_to_many]
Them, in your template:
{% for model in linked_models %}
{{ model.class_name }} {{ model.verbose_name }}
{% endfor %}

Related

Django - Generic detail_view doesn't accept an object_list

I have the following in urls.py:
url(r'frameworkslist/(?P<pk>\d+)$', DetailView.as_view(queryset=Category.objects.all().order_by("id"), template_name='home/subcategory.html'))
And in my html template:
{% extends "Layout.html" %}
{% block content %}
{{ subcategory.Name }}
{% for item in object_list %}
<h5> {{ item.Name }} </h5>
{% endfor %}
Back to framework list
{% endblock %}
I was wondering why object_list was empty but when I changed my urls to the following, it worked. (returned the ListView template instead of DetailView):
url(r'frameworkslist/(?P<pk>\d+)$', ListView.as_view(queryset=Subcategory.objects.all().order_by("id"), template_name='home/subcategory.html'))
Also to note, it seems like passing the variable "model=Subcategory" to the DetailView would return the first record (or what should be a single model) of the Subcategory table and pass that to the Template. So my question is two-part, the second being: How do you a collection of objects to DetailView Template?
DetailView is used for viewing a single object, and ListView is for, well, a list of objects. Usually the pattern is you have a ListView which has links to many individual things (like products), and then each product is viewed through a DetailView.
ListView is the one that automatically populates the object_list variable with your queryset.
In case of DetailView, it takes the queryset you provide and then uses the variables in the url to get() a single one. In your example that would be Subcategory.objects.all().order_by("id").get(pk={some number}). This is then given to the template in the object variable by default.
Lots more info on class based views here.
As a side note, you should be using the {% url %} tag in your templates rather than hard coding the urls.

Iterate over Django custom Form

I am trying to create a dynamic form, with a varying number of CharFields. I want to be able to display them at will in semi-arbitrary places in my form. My approach was to create an iterable function that fielded the right self.fields[INDEX]. However, when I do this, I literally see this:
<django.forms.fields.CharField object at 0x80bae6be0>
<django.forms.fields.CharField object at 0x80bae6f98>
<django.forms.fields.CharField object at 0x80bae6da0>
How do I make a CharField() render as expected?
My code is below:
class ImplementationForm(forms.ModelForm):
"""
Specifies the implementation of a given control.
"""
class Meta:
model = Implementation
fields = ['implemented', 'scope', 'separate']
def __init__(self, *args, **kwargs):
control = kwargs.pop('control')
super(ImplementationForm, self).__init__(*args, **kwargs)
self.fields['separate'].widget.attrs.update({'class': 'separate'})
self.fields['scope'].widget.attrs.update({'class': 'scope'})
for substatement in control.substatement.all():
self.fields['statement_%s'%substatement.pk] = forms.CharField()
def subfield(self):
print("Comes herE")
for index in self.fields:
if index[:10] == 'statement_':
yield self.fields[index]
The template basically does this:
{% for x in myform.subfield %} {{ x }} {% endfor %}
What you are looking for is the form's BoundFields. e.g. {{ form.email }}
You are iterating over the Field instances (not the form's BoundField instances that wraps the Field Instances) e.g. {{ form.field.email }}.
This is why you are getting the
<django.forms.fields.CharField object at 0x80bae6da0>
result from your template. See: https://stackoverflow.com/a/671305/3035260
Also see django's documentation: https://docs.djangoproject.com/en/1.10/ref/forms/api/#django.forms.BoundField
Try this dirty way (See my edit below for a much better solution):
{# Iterate over your list of field instances #}
{% for x in myform.subfield %}
{# Find the matching BoundField instance #}
{% for field in myform %}
{% if field.field == x %}
{# Matching BoudField instance found, display it. #}
{{ field }}
{% endif %}
{% endfor %}
{% endfor %}
Edit:
Just came across a better (less dirty) approach:
A Field has a
get_bound_field(self, form, field_name)
method according to the docs: https://docs.djangoproject.com/en/1.10/_modules/django/forms/fields/#Field.get_bound_field
So, in your subfield method in the last line (The 'yield' line), try this:
yield self.fields[index].get_bound_field(self, index)
Then, your template will remain the same:
{% for x in myform.subfield %} {{ x }} {% endfor %}
and everything should work as you intended.

simple loop in rendered template django cms plugin

I want to loop data taken from database in rendered template. Using cms plugin.
I dont have problem looping data in html template. But if i use CMSPlugin to insert new app in placeholder, nothing shows.
If i run url localhost:port/test.html.I got input what i want. But rendered template doesnt loop data.
{% for post in posts %}
{{ post.firstoption }}
{% endfor %}
if I use code below, nothing shows in my rendered template. Values are passed in rendered template. Because, if i try {{instance.firstoption}} i get value shown in template. Problem is i cant loop data with tag instance.
{% for post in instance.posts %}
{{ post.firstoption }}
{% endfor %}
I also tried {% for post in instance.posts_set.all %}
and {% for post in instance.posts.all %}
cms_plugins.py
class pricing(CMSPluginBase):
model = mymodel
name = _("myplugin")
render_template = "template.html"
cache = False
def render(self, context, instance, placeholder):
context.update({'instance': instance})
return context
models.py
class mymodel(CMSPlugin):
firstoption = models.CharField(max_length=200)
def __str__(self):
return self.firstoption
It is probably because you need to call all on your posts
{% for post in instance.posts.all %}
{{ post.firstoption }}
{% endfor }

How to get the number of form fields in a django template?

I have a django form that I can iterate over, for example, through a for loop:
{% for field in form %}
...
{% endfor %}
Now I'm trying to find out the total number form fields outside of the for loop. I have tried the following, but it just returns 0, even though I have 2 form fields:
{{ form|length }}
Is there any way to do this?
PS: This is in the context of django-cms 3.1.3, if this helps.
You'll need to explicitly count the fields, rather than just the form itself, such as:
{{ form.fields|length }}
As seen in the Django form documentation
Try this :
{{ form.hidden_fields|length + form.visible_fields|length }}

Django rendering field not working

My model:
class preguntas(models.Model):
pregunta = models.CharField(max_length=200)
My views:
opciones = preguntas.objects.all()
return render_to_response(template, {"pregunta": pregunta, "opciones": opciones})
Supposedly if in the template I write {{ opciones.pregunta }} it should return the field questions , but it doesnt , any idea ?
If you need more info tell me
You load a queryset opciones but don't seem to load anything called pregunta before listing it in your context variables. pregunta is an attribute of an instance of an individual member of the opciones queryset.
Since opciones is a queryset, you would need to iterate through it to see each individual item in your template. Your template should look more like:
{% for o in opciones %}
{{ o.pregunta }}
{% endfor %}
Also, I believe when you use render_to_response you should also add context_instance=RequestContext(request) in order for things to work 100% smoothly.
It looks like you're passing in a list of preguntas as opciones. So you need to iterate over the list in order to read the corresponding pregunta.
{% for p in opciones %}
{{ p.pregunta }} <!--do something with each pregunta-->
{% endfor %}
EDIT: souldeux beat me to it.

Categories