Django regex - optional grouped parameters - python

I'm constructing the urlconf for a website but I'm facing a couple of issues;
At some point I have to present a list of tasks which can eventually be reordered. The problem is that I have no clue on how to go about configuring the regex.
So far I've got this:
url(r'^myapp/mytasks, myview.tasks),
The default behavior is to accept requests at www.mydomain.com/myapp/mytasks.
However should the order button be pressed by a user, I need Django to also accept requests of type:
www.mydomain.com/myapp/mytasks/sort_by/price_highest
www.mydomain.com/myapp/mytasks/sort_by/price_lowest
but not
www.mydomain.com/myapp/mytasks/price_lowest
Is there a regex for this scenario?
Thank you all in advance.
P.S
Ideally I would also like to know how I could possibly reverse them.

Create two url records for the same view:
url(r'^myapp/mytasks/$', myview.tasks, name='tasks'),
url(r'^myapp/mytasks/sort_by/(price_highest|price_lowest)/$', myview.tasks,
name='sorted_tasks'),
And then change the signature of the tasks() view to:
def tasks(request, sort_by=None):
...
In the template you can easily point to the both versions:
{% url 'tasks' %}
{% url 'sorted_tasks' 'price_highest' %}
UPDATE: If you really want to make the only one url record then the regex will be:
'^myapp/mytasks/(?:sort_by/(price_highest|price_lowest)/)?$'
But I am not sure that it will work with {% url %} tag.

Related

I want to display only the sentences of the passed id on the screen

Template Language question. I want to pass the ID of the sentence I want to the url and display only the sentence of the passed ID on the screen.
url:
path('sentenceCard/<str:listName>/<int:listId>/', views.sentenceCard, name='sentenceCard')
views.py:
def sentenceCard(request, listName, listId):
sentence = Sentence.objects.filter(Classification=listName)
return render(request, 'english_note/sentenceCard.html', {'sentences':sentence, 'listId': listId})
html:
<a href='#'>{{sentences.0.korean_sentence}}<br>
<a href='#'>{{sentences.1.korean_sentence}}<br>
Variables in Template Variables?
like this?
{{sentences.listId.korean_sentence}}
Loop through the sentence. Something like the following if I'm understanding your setup. See the documentation on url builtin tag.
{% for sentence in sentences %}
<a href='{% url 'sentenceCard' listName=sentence.classification listId=listId %}'>{{ sentence.korean_sentence }}</a><br />
{% endfor %}
You may need to prefix the url path name with your app name:
{% url 'yourapp:sentenceCard' listName=....%}
Not asked for, but a suggestion or two which may make your Django coding easier:
lowercase your fields. Classification becomes classification
use def sentence_card(request, list_name, list_id):
when filtering, name your queryset with a plural: sentences = Sentence.objects.filter(classification=list_name)
when possible context variables mimic the object {'sentences':sentences}
None is absolutely to make the code work, but when trouble shooting later, it is nice to know by case what sort of thing you are dealing with. In Django in particular, it will help when you start doing some advanced filtering by never having to check how you named a field. Knowing the uppercased thing is the class, and the lower cased version is the instance will also come in handy.

Django: How can I pass a variable into the url from an anchor tag?

Django again...
I have seen only one way to do this but I am getting an error.
I have the url:
url(r'^wish_item/(?P<id>\d#)$', views.wish_item, name="wish_item")
and the view,
def wish_item(request, id):
but the anchor tag in my template is causing me a NoReverseMatch.
{% for x in myitems %}
{{x.item}}
{% endfor %}
What is the correct way to pass the variable into the url? Is anything wrong with the regex in my url or am I writing this wrong in the template tag? both?
EDIT:
changed the template tag to
{{x.item}}
but I still get the error (after clearing the url to just /wish_item because the regex gave me an error also):
Reverse for 'wish_item' with keyword arguments '{u'id': 1}' not found. 1 pattern(s) tried: ['wish_item']
It's getting longer than comments allow, so:
The argument is part of the path, not a query param: {% url 'wish_item' id=x.id %}
Your regexp is (very likely to be) wrong.
(?P<id>\d#)
This accepts exactly one digit followed by exactly one hash sign. Probably you meant this?
(?P<id>\d+)
That is, one or more digits?
For reference, you have the full regex syntax over here. By the way, if you just have a numeric id, I suggest sticking to this:
(?P<id>[0-9]+)
The difference is \d will also accepts other characters marked as digits in unicode, which you probably won't handle later on.

Django templates and whitespace

I started using custom inclusion tags within my django templates. For example I have a {% profilelink profile %} tag that inserts a link to a user profile together with a small version of the profile's picture, like so (profilelink.html):
<a href='{% url ... %}'><img src='{{ ... }}' alt='...'> {{ profile.name }}</a>
However, when I use it in the following snippet (sometemplate.html):
<p>Owned by {% profilelink owner %} (uploaded by {% profilelink uploader %})</p>
Then I get whitespace between the HTML produced by the second template tag and the closing parenthesis. This whitespace is unwanted. It comes from the final newline character in the file profilelink.html. This is a very common problem and searching Stackoverflow yields a lot of questions about whitespace in templates in general. Here's a summary of solutions found so far and why they don't work:
Some of these problems are solvable with the {% spaceless %} tag, but not all of them. This tag only removes whitespace between tags, which is not the case in the above example.
One possible solution is to not have a final EOL in profilelink.html but that's highly undesirable. Reasons: It is generally bad style; some editors (vim) silently add one back by default; that's how POSIX defines a line; it might make some SCMs unhappy; etc.
Another solution is switching to another template engine, like Jinja2, which may or may not solve this problem. It has support for constructs like {% ... -%} which eat the next EOL character. This is useful in some situations, but is also useless for my example above. But switching the templating backend for such a small annoyance seems a little overkill and adds another dependency. I'd like to stick to whatever is the standard "django" way of doing things. There are apparently plans to make Jinja2 the new Django default, though.
Some people suggested using a middleware class to remove redundant whitespace from the generated HTML before it's being sent to the browser. This is useful, but only for transforming the HTML in a way that is functionally equivalent, i.e. same semantics: it will then still be displayed the same way in the browser. That's not what I want, I want an actual change in semantics in order to have it display properly. This is impossible to implement in a generic middleware class. I need to have control over this on a case by case basis from within the template itself. I don't care about making the HTML prettier, I care about it being correct in the first place.
There's also bug #2594 which has been closed as WONTFIX with the argument (quote) "the Django template language is good enough for generating HTML, which isn't sensitive to whitespace". In my oponion this is just totally wrong. HTML is very much sensitive to whitespace, it just doesn't care how much there is of it. It cares a lot about whether there is some whitespace or none at all.
Some my question is: Is there any sane way to fix this problem in general? (One that always works, not just in some situations.)
(Any CSS-based fixes do not count. Copy/paste surprises are evil.)
I believe one solution is to use a simple_tag instead of an inclusion tag, hopefully without to much clutter.
I assume your tag is something like this:
#register.inclusion_tag('profilelink.html')
def profilelink(user):
return {"profile": user}
Would it be possible to substitute this with
from django.template.loader import render_to_string
#register.simple_tag
def profilelink(user):
t = render_to_string("profilelink.html", {"profile": user})
return t.strip()
I don't have a Django-project in front of me now, so this is untested.
This is the best I came up with so far. I still hope for a better solution, but for now it will do.
I defined a custom filter like this in base/templatetags/basetags.yp (taken from this answer):
from django import template
from django.template.defaultfilters import stringfilter
register = template.Library()
#register.filter
#stringfilter
def trim(value):
return value.strip()
And then use it as follows:
{% load basetags %}
<p>Owned by {% profilelink owner %} (uploaded by
{% filter trim %}{% profilelink uploader %}{% endfilter %})</p>

For a checkbox with multiple values in my html template how to access it through python code?

I'm a python and django newbie.
This is in my html template
<input type ="checkbox" value={{ item.id }} name="ck1[]">
In views.py when i do a checked = request.POST.get(['ck1']) i get unhasable list error. Kindly guide me.
Please don't use PHP syntax when you're writing Django. name="ck1[]" is a PHP-ism that's completely unnecessary.
If you want the field to be called ck1, just call use name="ck1", and use `request.POST.getlist('ck1') in your view.
If you really have to use that horrible bracket syntax, you'll need to use request.POST.getlist('ck1[]'), because Django quite sensibly believes that the name you use in the HTML is the name you should get in the POST data.
If u want to get array from html in Django view u need to use
checked = request.POST.getlist('ck1[]')
or
checked = request.POST.getlist('ck1')
getlist method will convert all selected values into python list

Why can't iterate through this list in a Django template

I have a variable from my view that is the output of a Model.objects.all() call on that Model. I'm passing it to my template in my view, and I'm trying to iterate over it in the template. I can access the first element of it simply by this line of code. 'code' is the name of a field in my django model. This line does print the first element's 'code' attribute correctly.
{{ var_name.0.code }}
However, when I try to iterate over var_name in a template for loop, nothing shows up. I tried the following code:
{% for single_var in var_name %}
{{ single_var.code }}
{% endfor %}
This isn't actually what I want to do in the for loop, but getting this to work will let me do what I need in the template. It may be noteworthy to add that at the moment this list has only one element in it.
This is for a work project, so that's why I changed the variable names to something generic.
I found that changing the name of single_var to something without an underscore seemed to fix it. This doesn't make a lot of sense to me because the Django template language documentation states the following:
Variable names consist of any combination of alphanumeric characters and the underscore ("_").
Does anyone know why this seemed to fix the problem?

Categories

Resources