Is it possible to dinamically change a variable name in template?
In the view below I am sending to the template an url parameter called sl.
is it possible to pass that sl to the {{ devize.sl{{sl}} }} so that it changes dinamicaly ?
thank you
#login_required
def slList(request,centrudecost,SL):
queryset = Deviz.objects.filter(centrudecost_id=centrudecost)
sl = SL
print(centrudecost)
return render(request, "proiecte/sl_list.html", {"queryset": queryset,"sl":sl})
{% for devize in queryset %}
<td>{{ devize.sl{{sl}} }}</td>
{% endfor %}
You can not change the template variable dynamically but there is a workaround on the query side. You can create (annotate) a field (my_field) and fill it dynamically in the query:
field = "xyz_fieldname" # in your case field = "sl" + SL
queryset = Deviz.objects.annotate(my_field=F(field)).values('my_field',...).filter(centrudecost_id=centrudecost)
print(centrudecost)
return render(request, "proiecte/sl_list.html", {"queryset": queryset})
and in the template:
{% for devize in queryset %}
<td>{{ devize.my_field }} }}</td>
{% endfor %}
Related
So I have the following table in my template:
<tbody>
{% for user in users %}
<tr>
<td>{{ user.title }} </td>
{% for fruit in fruits %}
{{ sum|add:user|get_attr:fruit }}
<td>{{ user|get_attr:fruit }} </td>
{% endfor %}
{% for vegetable in vegetables %}
{{ sum|add:user|get_attr:vegetable }}
<td>{{ user|get_attr:vegetable }} </td>
{% endfor %}
<td>{{ sum }}</td>
{% endfor %}
</tbody>
"fruits" and "vegetables" are lists passed as context from the view. The following custom filter allows me to iterate through those lists extract integer values from the model "user". The table columns are generated the same way, so this filter has to be in the table:
#register.filter
def get_attr(obj, attr):
return getattr(obj, attr)
The variable "sum" is passed as context from the view with the value 0. I'm trying to make it summarize all the relevant row variables in the template, but it remains 0. As far as I can see there are three ways I could go about this:
Solve this in the template (as I'm trying now)
Generate the value in the view (although I have no idea how I would go about this)
Add some JS to solve it (would prefer to avoid this).
How should I go about solving this?
Solved this on the back end by generating a dictionary:
views.py
sum = {}
for user in users:
identity = user.pk
score = 0
all_food = fruits + vegetables
for food in all_food:
score += getattr(user,food)
sum[identity] = score
The summarized value can now be accessed in the template by using another custom template tag:
#register.filter
def get_value(dictionary, key):
return dictionary.get(key)
Adding it to the template:
{{ sum|get_value:user.pk }}
I am trying to create a HTML table, with a 2 fields on each row for the user to fill in (sports matches predictions). It loads data from one table(List) and should write into another one (Predictions)
Right now I have a cycle which loops through the matches and based on that creates the HTML table.
input.html
{% block body %}
<form method="post">
{% csrf_token %}
<table class="table">
<tr>
<th>Round</th>
<th>Date</th>
<th>Time</th>
<th>Home</th>
<th class="col-md-1"></th>
<th class="col-md-1"></th>
<th class="col-md-1"></th>
<th>Away</th>
</tr>
{% for item in query_results %}
<tr>
<td>{{ item.match_round }}</td>
<td>{{ item.match_date }}</td>
<td>{{ item.match_time }}</td>
<td>{{ item.home_team_name }}</td>
<td>{{ form.home_goals_predictions|add_class:"form-control"}}</td>
<td class="text-center">:</td>
<td>{{ form.away_goals_predictions|add_class:"form-control"}}</td>
<td>{{ item.away_team_name }}</td>
</tr>
{% endfor %}
</table>
<button type="submit" class="btn btn-success">Submit</button>
</form>
{% endblock %}
This is works and displays the table excatly as I want.
However I am not able to extract the data as I want from it - to be more exact, when submiting the form, the data from the last row gets assigned to all the rows.
views.py
query_results = List.objects.all()
form = PredictionsForm()
if request.method == 'POST':
form = PredictionsForm(request.POST)
if form.is_valid():
user_prediction = form.save(commit = False)
for result in query_results.all():
for home_goals_predictions, away_goals_predictions in form.cleaned_data.items():
user_prediction.id = result.id
user_prediction.match_round = result.match_round
user_prediction.home_team_name = result.home_team_name
user_prediction.away_team_name = result.away_team_name
user_prediction.user_id = request.user.id
user_prediction.home_goals_predictions = form.cleaned_data['home_goals_predictions']
user_prediction.away_goals_predictions = form.cleaned_data['away_goals_predictions']
user_prediction.save()
return redirect('/matches/')
else:
return redirect('/matches/')
else:
template = loader.get_template('matches/input.html')
context = {
'query_results': query_results,
'form': form
}
return HttpResponse(template.render(context, request))
forms.py
class PredictionsForm(forms.ModelForm):
home_goals_predictions = forms.IntegerField(widget=forms.Textarea(attrs={'cols': 1, 'rows': 1, 'maxlength': '2'}))
away_goals_predictions = forms.IntegerField(widget=forms.Textarea(attrs={'cols': 1, 'rows': 1, 'maxlength': '2'}))
class Meta:
model = Predictions
fields = ('home_goals_predictions', 'away_goals_predictions')
I would really appreciate the help, as I am stuck on this problem and cannot figure out correct solution using formset/for loop.
I'm not entirely sure what's going on in your code since I can't see the definition of query_results but I'm pretty sure that what you are looking for is formsets. In short, a form submit's one thing / record. A formset is as the name suggest a set of forms, see the documentation for a full example. Also take a look at modelformsets, depending on your usecase this might really come in handy as well.
Edit:
Yeah so I would definitely go the modelformset route. Here's a short example of what that would like
in your views.py (the GET request).
from django.forms import modelformset_factory
ListFormSet = modelformset_factory(List, form=ListForm, extra=0)
list_formset = ListFormSet(queryset=List.objects.all())
Then during POST you can just do
ListFormSet = modelformset_factory(List, form=ListForm, extra=0)
list_formset = ListFormSet(request.POST, queryset=List.objects.all())
if list_formset.is_valid():
for list_form in list_formset:
list_form.save()
analogue to how a normal single form works.
Then in your template
<form enctype="multipart/form-data" method="post">
{{ list_formset.management_form }}
{% for list_form in list_formset %}
...
{{ list_form.instance.match_round }}
...
{{ list_form.home_goals_predictions }} #formfield
{{ list_form.away_goals_predictions }} #formfield
{% endfor %}
</form>
As you can see it is possible to access the query data via .instance
note: I typed this from memory so you might have to debug some typo's.
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
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())
I am trying to set up links to a view that allows to edit objects, in previous view.
Model:
class List(models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length=200)
type = models.PositiveIntegerField(choices=TYPE_DICT)
def __unicode__(self):
return self.name
#models.permalink
def get_absolute_url(self):
return ('EditList', None, {'list_id':self.id} )
View:
lists = List.objects.filter(user=request.user)
array = []
for list in lists:
ListDict = {'Name':list.name, 'type':types[str(list.type)], 'edit':list }
array.append(ListDict)
context = { 'array':array,}
Template:
{% for dict in array %}
<tr>
{% for key,value in dict.items %}
{% ifequal key 'edit' %}
<td>{{ key }}</td><td>{{ value.name }}</td>
{% else %}
<td>{{ key }}: </td><td>{{ value }}</td>
{% endifequal %}
{% endfor %}
</tr>
{% endfor %}
and urls conf:
urlpatterns = patterns('tst.list.views',
(r'^$', 'list'),
(r'^edit/(?P<list_id>\d+)/$', 'EditList')
,
What this line with link gives me is http://localhost/list/ as url, not http://localhost/list/edit/[objectid]/
Can anyone please tell me what am i doing wrong?
Alan
If you had wanted to do it for an unnamed urlconf, you just needed to pass the whole import string:
#models.permalink
def get_absolute_url(self):
return ('yourproject.yourapp.views.EditList', None, {'list_id':self.id} )
I also suggest you follow the PEP8 naming conventions for functions.
Ok. I got it working. What i needed to do ,was to give name to this view. When i changed my urlconf to this:
url(r'^edit/(?P<list_id>\d+)/$', 'EditList', name = 'EditList'),
Then everything started working.