Django template tag can access string variable but can't call a table function? - django-templates

According to https://docs.djangoproject.com/en/2.2/ref/templates/language/ you should be able to call a function from a tag as long as it takes no arguments.
I tried this:
class TaskTable(Table):
test = "test"
def give_aids():
return "aids"
def give_tuple():
return ('y', 'e', 'e', 't',)
class Meta:
template_name = 'some_template.html'
Then, in the corresponding template file, i attempted to access these like so.
{{table.test}}
{{table.give_aids}}
{% for char in table.give_tuple %}
{{char}}
{% endfor %}
Upon rendering the template "test" is displayed, while "aids" and "yeet" aren't. What am I doing wrong?

That's what I get for being a monkey at python. I'm not passing "self" to the methods. Sorry for wasting your time xD

Related

how to render django-taggit common tags in template

I've seen a lot of questions and answers about how to get most common tags using django-taggit. However that's not really my issue. My issue is how to pass that common tags to my django templates.
To return all tags I had:
{% for tag in model.tags.all %}
<p>{{tag}}</p>
{% endif %}
And that worked fine. But how do I return the common tags in the template? To get the common tags I have this:
class Home(ListView):
model = Model
template_name = 'home.html'
def get_common_tags(self):
common_tags = Model.tags.most_common()[:2]
return common_tags
But how do I access these common_tags? Do I need to get the common tags from the template or should I be passing them from the view?
it is better to read about Django GCBV.
in your case:
class Home(ListView):
model = Model
template_name = 'home.html'
...
def get_context_data(self, **kwargs):
kwargs['common_tags'] = self.get_common_tags()
return super().get_context_data(**kwargs)
here we override get_context_data, to get in template variable common_tags
https://docs.djangoproject.com/en/4.0/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin.get_context_data
after that, in template:
ΒΆ
{% for tag in model.tags.all %}
<p>{{tag}}</p>
{% endif %}
<p> Most common tag are: {{ common_tags }}</p>
common_tags - is a list, you can made something with django template filter, like join:
{{ common_tags|join:" ," }}
or unordered_list:
<ul>{{ common_tags|unordered_list }}</ul>
more - here:
https://docs.djangoproject.com/en/4.0/ref/templates/builtins/#unordered-list

How to add external Json as variables to shopify

In my online shop I want to show some more data about each product. I have managed to do this by adding an extra nodes to settings_data.json file. Like this:
{
"current": {
...
...
"7887193478": { //Product ID
"has-badge" => true,
"show-image" => false
...
},
"7887193479": { //Product ID
"has-badge" => true,
"show-image" => true
...
},
}
}
It is working and I am getting the data and showing it successfully.
The good thing about this solution is the page load is very fast.
But the problem is when some one updates the theme setting it overrides the settings_data.json file. Is there any way that I can import this extra json settings separably into my Shopify?
Please do not advise me with Metadata App. Metadata app is very slow and I am not interested to use it.
You can create a snippet products_data.liquid (or any other name you want) that stores the information you need, that's separate from the theme settings file, and won't be overwritten. Here's an example:
{% assign "7887193478-has-badge" = true %}
{% assign "7887193478-show-image" = false %}
{% assign "7887193479-has-badge" = true %}
{% assign "7887193479-show-image" = true %}
...
Then you'll want to include it somewhere in there theme.liquid file, above where you'd be using it:
{% include "products_data" %}
The downside is that it's not as clean in terms of data entry.

Django {{ c }} not rendering

Problem is that i can't get value to my template.
Views.py:
from django.shortcuts import get_object_or_404, render_to_response
from django.httpimport HttpResponse
def index(request):
c='hi'
return render_to_response('list.html', c)
list.html:
{% extends "base.html" %}
{% block content %}
list{{ c }}
{% endblock %}
It renders list but not{{ c }} what could cause this? And it gives no error..
render_to_response expects its context to be a dictionary, whereas you are passing your string directly:
def index(request):
context = { 'c': 'hi' }
return render_to_response('list.html', context)
Based on your comment below, if you want 'c' to be a list of things, it would look something like this instead:
def index(request):
context = { 'c': ['hello', 'world'] }
return render_to_response('list.html', context)
The basic idea is that you're building a mapping of the variables you want to reference in your template. The names that you reference in the template are keys in the dictionary.

Django: user info in template

I have this in my base.html template:
{% if user.is_authenticated %}
<p style="color:#000;">
Welcome
{{ user.first_name }}
|
Logout
</p>
{% endif %}
After I authenticate, and go to this page, my first name does not show up. Can anybody tell me why?
The "Welcome" also does not show up. So, this must be failing on user.is_authenticated.
Thanks. :)
The django.contrib.auth.context_processors.auth middleware is responsible for setting request.user before a request reaches the controller.
In order to access it from a template, you need to pass this variable or a RequestContext. Example:
def something(request):
context_instance = RequestContext(request)
template_name = 'your_template.html'
extra_context = { 'other_variable': 'some value' }
return render_to_response(template_name, extra_context, context_instance)
This way, all the request variables are accessible from the template.

in SQL, or Django ORM, what's the conventional way to have an ordered one-to-many?

Say I wanted to have a project, and one-to-many with to-do items, and wanted to re-order the to-do items arbitrarily?
In the past, I've added a numbered order field, and when someone wants to change the order, had to update all the items with their new order numbers. This is probably the worst approach, since it's not atomic & required several updates.
I notice Django has a multi-valued CommaSeparatedIntegerField which could contain the order by storing the ordered keys to the items in the to-do items table right in one field of the project table.
I've pondered a dewey decimal system where if I wanted to take item 3 and put it between 1 and 2 I would change it's order number to 1.5.
Something tells me there's an easier option that I'm missing though...
How would you give order to a one-to-many relationship?
I hate this problem ... and I run into it all the time.
For my most recent Django site we had a Newsletter which contained N Articles and, of course, order was important. I assigned the default order as ascending Article.id, but this failed if Articles were entered in something other than "correct" order.
On the Newsletter change_form.html page I added a little bit of jQuery magic using the Interface plugin (http://interface.eyecon.ro/). I show the titles of the associated Articles and the user can drag them around as they like. There is an onChange handler that recomputes the Article.id's in article_order field.
Enjoy,
Peter
For app=content, model=Newsletter, the following is in
templates/admin/content/newslettter/change_form.html
{% extends 'admin/change_form.html' %}
{% block form_top %}{% endblock %}
{% block extrahead %}{{ block.super }}
<script type="text/javascript" src="/media/js/jquery.js"></script>
<script type="text/javascript" src="/media/js/interface.js"></script>
<script>
$(document).ready(
function () {
$('ol.articles').Sortable(
{
accept : 'sortableitem',
helperclass : 'sorthelper',
activeclass : 'sortableactive',
hoverclass : 'sortablehover',
opacity: 0.8,
fx: 200,
axis: 'vertically',
opacity: 0.4,
revert: true,
trim: 'art_',
onchange:
function(list){
var arts = list[0].o[list[0].id];
var vals = new Array();
var a;
for (a in arts) {
vals[a] = arts[a].replace(/article./, '');
}
$('#id_article_order').attr('value', vals.join(','));
}
});
}
);
</script>
{% endblock %}
{% block after_related_objects %}
{% if original.articles %}
<style>
.sortableitem {
cursor:move;
width: 300px;
list-style-type: none;
}
</style>
<h4>Associated Articles</h4>
<ol class="articles" id="article_list">
{% for art in original.articles %}
<li id="article.{{art.id}}" class="sortableitem">{{art.title}}</li>
{% endfor %}
</ol>
{% endif %}
{% endblock %}
"added a numbered order field" - good.
"update all the items with their new order numbers" - avoidable.
Use numbers with gaps.
Floating point. That way, someone can insert "1.1" between 1 and 2. I find that this works nicely, as most people can understand how the sequencing works. And you don't have to worry too much about how much space to leave -- there's lots and lots of space between each number.
On the initial load, number the articles by the 100 or 1000 or something with space between each one. In this case, you have to guess how many digits to leave for reordering.
A comma-separated position. Initially, they're all (1,0), (2,0), (3,0), etc. But when you want to rearrange things, you might have to introduce (2,1) and (2,2) that go after (2,0) but before (3.0).
This looks kind of complicated, but some people like this kind of complexity. It's essentially the same as floating-point, except the single number is replace by a (whole-number, implicit-fraction) tuple. And this extends to handle hierarchies.
I have had this problem with two projects I've worked on in the last little while. For my example solution I have a "Form" that has many "Variables" assigned to it and the order of the variables on the form needs to be sortable. So I have implemented the following:
models.py
class Form(models.Model):
FormName = models.CharField(verbose_name="Form Name:", max_length=40)
VariableOrder = models.CommaSeparatedIntegerField(default="[]", editable=False)
def __unicode__(self):
return "%s" % (self.FormName)
class Variable(models.Model):
FormID = models.ForeignKey(Form, default=0, editable=False, related_name="Variable")
VarName = models.CharField(max_length=32, verbose_name="Name of variable in the database:")
def __unicode__(self):
return "%s" % self.VarName
The key from above is the VariableOrder CommaSeparatedIntegerField is where we are going to store the order of the Variables on the Form, and we are going to be using it as a python list, which is why the default is [].
For the template I render my Variables in an that we are going to make drag and drop sortable (the list elements I actually use have a ton more CSS related styling and information about the Variable).
<ul id="sortable">
{% for Variable in VarList %}
<li id="{{ Variable.id }}">{{ Variable }}</li>
{% endfor %}
</ul>
Now we are going to make the list drag and drop for the changing of order. For this to work you need to have the AJAX CSRF snippet from Django site in the head
$(function() {
$("#sortable" ).sortable({
placeholder: "ui-state-highlight",
update: function(event, ui){
$.ajax({
type:"POST",
url:"{% url builder.views.variableorder %}",
data: {Order: JSON.stringify($('#sortable').sortable('toArray')) },
success: function(data){
// Do stuff here - I don't do anything.
}
});
}
});
$( "#sortable" ).disableSelection();
});
The important part above is that "update" calls the function every time there is a position change of any of the variables, which sends the AJAX. toArray on sortable along with the JSON stringify gets us sending the top to bottom id's of each variable, which is used by the view as follows. Note: I keep the active Form object as a session variable, but in another case you would just need to call the Form object you were wanting to change the order of.
def variableorder(request):
if request.is_ajax():
Order = request.POST['Order']
updateOrder = request.session['FormID']
updateOrder.VariableOrder = newOrder
updateOrder.save()
request.session['FormID'] = Form.objects.get(id=updateOrder.id)
return HttpResponse("Order changed.")
else:
pass
The key of all of this is that you can use this CommaSeparatedIntegerField as a list by evaluating the string. For example:
Adding a Variable:
aForm = Form.objects.get(id=1)
currentOrder = aForm.VariableOrder
currentOrder = eval(currentOrder)
newVar = Variable(stuff in here)
newVar.save()
currentOrder.append(newVar.id)
aForm.VariableOrder = currentOrder
aForm.save()
Removing a Variable:
aForm = Form.objects.get(id=1)
currentOrder = aForm.VariableOrder
currentOrder = eval(currentOrder)
# Variable ID that we want to delete = 3
currentOrder.remove(3)
aForm.VariableOrder = currentOrder
aForm.save()
Rendering the Variables in Order:
aForm = Form.objects.get(id=1)
currentOrder = aForm.VariableOrder
currentOrder = eval(currentOrder)
VarList = []
for i in currentOrder:
VarList.append(Variable.objects.get(id=i))
This is a rough first draft of what I am going to use, but it is working well for me. The obvious first improvement being the evaluation to python list being a method in the class. eg.
def getVarOrder(self):
return eval(self.VariableOrder)
and then just call Form.getVarOrder() when want to manipulate the list. In any case hopefully this helps out.
JD
I've run into this so many times that I've settled on managing these dynamically in the BL or UI, and then just persisting the ordering to a purpose-built column once the user is happy. SQL is just intentially designed not to handle orderings, and it always fights back.
This is a late answer to the question, but I just wanted to chime in and point out that B-Trees are a great data structure for this sort of thing, especially if your access patterns don't require you to retrieve the entire list at once.
http://en.wikipedia.org/wiki/B-tree