I am new to python and django and was wondering how I would go about making a dict of lists.
My 4 lists are;
ap = request.POST.getlist('amount_paid[]')
pd = request.POST.getlist('paid_date[]')
method = request.POST.getlist('method[]')
comments = request.POST.getlist('comments[]')
How would I make that into a dictionary I could then loop over in a django template such as;
{% for i in the_dict %}
{{i.amount_paid}}
{% endfor %}
Thanks in advance!
Update:
hmm I not sure I posted my question properly. In php, I can do the following on an array of fields:
for($i=0;$i<count($_POST['amount_paid']);$i++) {
echo $_POST['amount_paid'][$i];
echo $_POST['paid_date'][$i];
}
All the form fields are input text fields.. How would I do this in Django?
Python's dict syntax is very simple. It's just key-value pairs inside a pair of curly braces, like this:
the_dict = {
'amount_paid': request.POST.getlist('amount_paid[]'),
'paid_date': request.POST.getlist('paid_date[]'),
'method': request.POST.getlist('method[]'),
'comments': request.POST.getlist('comments[]'),
}
Following your update, it looks like you don't want a dict at all but zip():
post = request.POST
lists = zip(post.getlist('amount_paid[]'),
post.getlist('paid_date[]'),
post.getlist('method[]'),
post.getlist('comments[]'),
)
for amount_paid, paid_date, method, comments in lists:
print amount_paid
print paid_date
# et cetera...
You could create:
the_dict = dict(amount_paid=ap, paid_date=pd, method=method, comments=comments)
Also your template code does not make sense. You are iterating over the keys of the dict and not using them in the body.
EDIT
{% for key in the_dict %}
{% for val in the_dict[key] %}
<input name="{{key}}" value="{{val}}"/>
{% endfor %}
{% endfor %}
As often happens, you're not really asking about the problem you actually need to solve: you've done things in a certain (wrong) way, and are asking about how to get yourself out of the problem you've got yourself into.
If I understand you correctly, you've got a set of fields - amount_paid, paid_date, method, comments - and each field appears multiple times on the form, so you've got one set of values for each entry. You're presumably trying to sort these into a list of dicts for each row.
Well, this is not the right way to go about it in Django. You should be using formsets, which give you one form for each row in a table - ie, exactly what you want to achieve.
Related
I have a SQLite DB that I query like this:
products = cursor.execute(
Select Item,EntryDate,json_group_array(json_object('color',P.option)) as colorarray
.....
).fetchall()
The results of products can look like this
[('dress', '2022-12-27 00:00:00', '[{"color":"blue"},{"color":"green"}]')]
In my jinja template I try to loop over the JSON, but my data is treated like a string and printed out 1 character at a time.
{% for color in products[2] %}
{{ color }}
{% endfor %}
What is the proper way to get this done? I can change my SQLite query to not use json_group_array if there is a more idiomatic option. Also I would rather refer to my data by column names (ex products.colorarray) if possible.
I've tried this query with SQLite and also tried mocking the data.
As said in the comments, products[0][2] is a string, in fact SQLite's json_object() returns a serialized JSON, and beacuse strings are iterables you're noticing this:
In my jinja template I try to loop over the JSON, but my data is treated like a string and printed out 1 character at a time.
deserialize products[0][2] with json.loads() .
Also I would rather refer to my data by column names (ex products.colorarray) if possible.
Jinja can read a dictionary like this:
d = {
"item": products[0][0],
"timestamp": products[0][1],
"colorarray": json.loads(products[0][2])
}
then get access by the colorarray key:
{% for color in d["colorarray"] %}
{{ color["color"] }}
{% endfor %}
I've got modules that if enabled/disabled would require a different arrangement of tables and iframes on the frontend webpage. In order to do this I set up a function to check which modules are enabled/disabled and assigned a number to each 'set' and will be created separate templates for each "set1.html", "set2.html", "set3.html", etc...
I'd like to utilize one single view where I can pass the set number from from function I created but I can't seem to figure out how.
def homeset(request):
return render(request, 'app/set1.html', {})
Looking to figure out some way to make the "1" the return of the function I created to determine which set# to load as template and would prefer to not have to create a view for every single template needed.
Just taking a stab at this, do you have a problem with setting the template name before rendering?
def homeset(request):
# define 'my_set'
# define num
...
my_template_name = None
if num in my_set:
my_template_name = 'app/set{}.html'.format(num)
return render(request, my_template_name)
Looks like Scott Skiles answered your question, but an alternative way is to use a single base template and the "include" templatetag.
You can pass the set number to the template and use the "if" templatetag" to include the content from appropriate template(s) for each set number.
{% if set_num == 1 %}
{% include "foo/bar.html" %}
{% elif set_num == 2 %}
{% include "foo/two.html" %}
{% endif %}
I'm trying to access some data in a template. I don't think the way I'm doing it now is the best way, but I can't get it even half working any other way.
def room(request, room_id):
#get room data
room = Room.objects.filter(id=room_id).get()
modules = []
#pull all actuator devices for the room
actuators = Device.objects.filter(room_id=room_id,type="actuator")
#build a list of modules then use set to remove duplicates
for actuator in actuators.values():
module = Module.objects.get(module_id=actuator["module_id"]).name_only()
modules.extend([module])
modlist = list(set(modules))
moduleData = {}
#loop through the modules, pull out the required data and send it all off to the template
for module in modlist:
data = Module_List.objects.get(name=module)
dict = {"name": data.name, "widget_mqtt_js": data.widget_mqtt_js, "widget_setup_js": data.widget_setup_js, "widget_body": data.widget_body}
moduleData[module] = dict
print dict["widget_mqtt_js"]
context = {"room_name" : room.name, "actuators" : actuators, "modules" : moduleData}
return render(request, 'control/room.html', context)
This is my code as it stands. The problem I'm having is that the loop in my template is returning blank. It looks like this:
{% for module in modules %}
{{module.widget_mqtt_js}}
{% endfor %}
I think there will be a way to do it with the Module_List model, but I could't get that working either..
modules in the template context is moduleData in your view code. But moduleData is a dict, and iterating over a dict yields its keys, not its values.
You need to iterate over the values, try:
{% for module in modules.values %}
{{module.widget_mqtt_js}}
{% endfor %}
My template has if/else functionality to handle displaying buttons on a page, I've managed to add an elif statement that displays the buttons only if an element in a mongo database is not one of three values. I'm trying to clean this up as the elif appears four times across two jinja2 templates. My code which works now looks like this:
{% elif (
('string1' not in database.category) and ('string2' not in database.category) and
('string3' not in database.category)) %}
I've tried declaring a tuple and doing a:
{% set hidebuttons = ['string1' , 'string2' , 'string3'] %} //sets tuple
{% elif not database.category in hidebuttons %} // checks if value not in tuple
and plenty of other methods to make this work but every time I reload the web page i keep seeing the buttons when i shouldn't be. Any advice is greatly appreciated.
I believe this should be in your view, not your template. If you need to do the query in more then one place, you can create a utility function that gets the results you need, then in your views, you can call the function and pass the data as context to your templates
if you're using a view_config decorator to render template, it could be something like:
#view_config(renderer='templates/foo.pt')
def my_view(request):
show_buttons = logic_to_determine_should_buttons_be_shown()
return {'show_buttons': show_buttons }
# your template
{% if show_buttons %}
show buttons
{% endif %}
In a Django template how do I remove the first Zero from all the this mobile numbers I'm displaying. In Python I have tried this but with no success....
{% for object in data %}
{{ object.mobile.lstrip('0') }}
{% endfor %}
views.py
def sms(request, incentive):
objectQuerySet = Recipient.objects.filter(incentiveid=incentive)
context = {'data':objectQuerySet}
return render_to_response('smssend.html', context, context_instance=RequestContext(request))
There are many ways to do that.
write custom template filter
filter user input and store phones with leading zeros already stripped
create a custom object #property returning mobile with zeroes stripped (this one a little bit dirty)
do cleanup before rendering template
I assume you will need to use similar logic in other locations of your application so why not just add a method to your model to clean the data? The code below assumes your mobile field is a string.
class Recipient(models.Model):
...
def mobile_no_zero(self):
return self.mobile[1:] if self.mobile.startswith('0') else self.mobile
And then you can call the method from your template:
{% for object in data %}
{{ object.mobile_no_zero }}
{% endfor %}
You should pass your data to your template in the correct format. Django templates are not "Python interspersed with HTML" like PHP is.
For example, when you first pass your data in your view, you should make sure that it is an iterable with the zeroes already stripped.
There is no lstrip in the Django template mini-language.
Edit: If you know that the first digit will always be a 0, you can also do this:
{{ object|slice:"1:" }}
There is one method that does work (but is more of a kludge that anything and removes 0 or more 0s) - and only if the number can be converted to a float to start with (ie, no spaces)
In [23]: t = Template('{{ value|floatformat:0 }}')
In [24]: t.render(Context({'value': '00123'}))
Out[24]: u'123'
You can use cut ( it will cut all zeros from number )
or you can use
phone2numeric
Imo its beter opption