Django select_related queryset in template not rendering - django

I have a simple view like so:
def classticker(request):
tickermodel = Tickers.objects.all().select_related('subsector_fk')
form = TickerForm()
return render(request, 'feeds/main.html', {'v': 10, 'form': form, 'tickermodel': tickermodel})
tickermodel is successfully returning a queryset with all of the fields in the Tickers table and the Subsector table (through the subsector_fk field). This includes the fields 'ticker', 'company_name' and 'subsector' that I'm using in the template below.
When I render my template and iterate through the tickermodel queryset I cannot seem to access fields that are coming from the Subsector table. Below tic.ticker and tic.company_name are rendering as expected but tic.subsector is not. I have no idea why??
My template looks like this:
<table class="tbllist">
<tr><th>Current Tickers</th></tr>
{% for tic in tickermodel %}
<tr>
<td><input type="checkbox" name="myclass" value="{{tic.ticker}}"/></td>
<td class="selectable" data-tik="{{tic.ticker}}"><span class="uppercase">{{ tic.ticker }}</span> - {{ tic.company_name }}</td>
<td>{{ tic.subsector }}</td> <!-- <<<< this will not display >>>>> -->
</tr>
{% endfor %}
</table>

select_related doesn't somehow make the related fields available in the main model; it doesn't change the structure at all. Your related fields are still available by following the foreign key field. The thing that select_related does is to make that more efficient by doing a JOIN query so that the related objects are already populated.
You haven't shown your models so I can't tell what the actual FK field is, but you would need to do something like tic.subsector_fk.subsector.

Related

Adding rows and columns to HTML table with Django

I have a problem. Consider an HTML table and it has rows and columns. I want to add a new row or column when I want it and I want it to be a record in the database. And I want to do this with django. What should I do?
I think I need to use django_table2 but I don't know how. I would be glad if you write a code sample. Thank you)
Say you have a model, you could get a list of objects like so;
def my_view(request):
context = {'object_list':MyModel.objects.all()}
return render(request, 'mypage.html', context)
Then in the template, you could do a few things to create tables:
Either, fully generate the table with Django, like so:
{% for object in object_list %}
<tr>
<td>{{object.data}}</td>
<td>{{object.data}}</td>
<td>{{object.data}}</td>
</tr>
{% endfor %}
This would create a new row for every object.
Another solution is:
{% for object in object_list %}
//Create row for every object
<tr>
{% for data in object.get_field_data %}
// Create column for every field in object
<td>{{data}}</td>
{% endfor %}
</tr>
{% endfor %}
Where get_field_data would be defined as a method on the model like so:
def get_field_data(self):
datalist = []
for field in self._meta.get_fields():
datalist.append(getattr(self, field.name))
return datalist
You could then even implement some checks on the get_field_data, for example, you could exclude fields.
def get_field_data(self):
datalist = []
for field in self._meta.get_fields():
if field.name != 'id':
datalist.append(getattr(self, field.name))
return datalist
You don't need to use any external package, you can do this easily by using the Django Template Language
Here is a code example using a ListView
# views.py
from django.views.generic import ListView
class ItemListView(ListView):
template_name = 'mytable.html'
model = MyModel
context_object_name = 'item_list'
<!-- mytable.html -->
...
<table>
<thead>
<tr>
<th>Name</th>
<th>Amount</th>
</tr>
</thead>
<tbody>
{% for item in item_list %}
<tr>
<td>{{ item.name }}</td>
<td>{{ item.amount }}</td>
</tr>
{% endfor %}
</tbody>
</table>
...
In this way your template will have access to a list of objects called item_list which corresponds exactly to the records in the database table. You can cycle that list/queryset using a for loop that will automatically wrap that content in the html needed to make it part of the table.

django dynamic template link dictonary to object fields

I am working on a dynamic template and i hoped to be able to include the last part of it aswell. My problem: I got a x-amount of fields that relate to fields of the object. But when i pass another model object it should show other fields.
Example:
model 1 show object name, category, approved
model 2 show object name, attribute,
For the other variable things, i make a dictionary that holds the information, problem is, i dont know how i could link the object fields to it.
Dictonary send to template:
field_map = {'field1': 'Name', 'field2': 'Category', 'field3': 'Approved'}
Template:
{% if objects|length > 0 %}
<table style="padding: 3px;">
<tr style=" text-align: center;">
{% for key, value in field_map %}
<th>{{ value }}</th>
{% endfor %}
</tr>
{% for object in objects %}
<tr>
<td>{{ object.name }}</td>
<td>{{ object.category }}</td>
<td>{{ object.approved }}</td>
</tr>
But now i want to add the objects fields to the field_map fields.
Cause i will be sending more then 1 object
Hope i explained my question well enough.
Can someone help me out?
You are trying to re-implmenet an already solved problem. Please use django-tables2 to render tables in django: https://github.com/bradleyayers/django-tables2
Update: To answer OP's comment on how to remove or edit the pagination footer:
If you do not want to have pagination to your table then just configure your table passing paginate=None to your RequestConfig like this:
table = TestTable(Test.objects.all())
RequestConfig(request, paginate=None).configure(table)
return render(request, 'test.html', {'table': table})
If you want to edit the footer yourself then you have to provide a new table rendering template. To do this, you just need to copy the contents of table.html from here https://github.com/bradleyayers/django-tables2/blob/master/django_tables2/templates/django_tables2/table.html to your templates directory. You can then modify this file to your requirements, for instance the pagination section is between {% if table.page %} and the {% endif %} at the end of the file.
Now, after you've created your custom table template you need render your table using this template. If you named your template as mytable.html then just use the following syntax from within your normal templates:
{% render_table mytable "mytable.html" %}

Display django Model fields in a table

I have Model with 30+ fields and I want to display about 20 of them in a table. I know that there is {{ form.as_table }} but is there a comparable function for non-form models? I am currently using
{% for name, value in article.get_fields %}
<tr>
{% if value %}
<td>{{ name }} = {{ value }}</td>
{% endif %}
</tr>
{% endfor %}
-where get_fields returns all the fields of Article. This works fine. I would guess that there is a built-in django function for doing the same thing, but I can't find it in the documentation.
I agree with #kathikr, there isn't a function built in to the model class to do this for you.
One option would be to subclass Model and add a as_table() function to it that parsed available fields and used an exclude attribute where necessary.
def as_table(self):
return "".join(["<tr><td>%s</td><td>%s</td></tr>" % (field.verbose_name, field.value_to_string(self)) for field in self._meta.fields if field not in self.exclude])
hmm, this probable shouldn't be a one-liner
def as_table(self):
result = ""
for field in self._meta.fields:
if field not in self.exclude:
result += "<tr><td>%s</td><td>%s</td></tr>" %
(field.verbose_name, field.value_to_string(self))
return result

model form factory not displaying correctly

I am using model form set. If i use formset_factory then its displaying the form like this which is correct but if i use modelformset_factory then its displaying all the objects from model like this . It should be. Am I missing something? thanks
form
class MyImageForm(ModelForm):
class Meta:
model = MyImage
exclude = ('test', 'user')
MyImageFormSet = modelformset_factory(MyImage, MyImageForm)
template
{% for form in formset %}
{{ form.non_field_errors }}
<tr>
<td>{{ form.image }}</td>
<td></td>
</tr>
{% endfor %}
{{ formset.management_form }}
According to the Django documentation on modelformset, you can create MyImageFormSet as you have been doing, but simply filter it afterwards (and presumably return the new modelformset).
Create the modelformset as normal:
MyImageFormSet = modelformset_factory(MyImage, MyImageForm)
But use the modelformset with an empty query, like this:
MyImageFormSet(queryset=MyImage.objects.none())

Display a grid radio form with Django Forms or Django Floppyforms

I would like to make a form with this kind of grid :
Do you know how I can do this ? Is there a Django Form widget for that ?
Actually it is questions with the same choices list displayed as radio in a grid.
Thanks,
Natim
I'd do this with a django form with one field per line on your grid, with a ChoiceField and RadioSelect as widget:
line1 = forms.ChoiceField(widget=forms.RadioSelect, choices=TRUC)
line2 = …
Then you need to find the template layout to render this correctly. RadioSelect generates a <ul> with eahc choice being a <li>. The choice label is included in the <li>, which is not what you want here.
With floppyforms you could subclass RadioSelect and give it a cutom template_name (look at the floppyforms/radio.html template) to omit the labels. You can also alter it to render, say, table cells (<td>s) instead of <li>, and make your form markup generate a table with the labels in the table's header.
import floppyforms as forms
class RadioSelect(forms.RadioSelect):
template_name = 'myforms/radio.html'
Put your desired row markup in the above template.
Then, in the template that renders your form:
<form method="post" action="youraction">
<table>
<thead>
<td> <!-- put your form headers here --> </td>
</thead>
<tbody>
{% for field in form %}
<tr>
<td>{{ field.label_tag }}</td>
{{ field }}
</tr>
{% endfor %}
</tbody>
</table>
<!-- submit button -->
</form>
Then it's only a matter of applying a couple of CSS styles to get the layout you need :)
You can try this field django-radiogrid