passing django variables as parameters into href url - python

On my home page i want to have 3 links that will redirect the user to a page ('127.0.0.1:8000/person/<str:name>') which will display the name that they clicked. I would like to use a for loop to create links for these names as i plan to have much more than 3 names.
I have tested with the two methods (for loop / manually writing out all of the links) but can't get the for loop to work.
I thought these two methods below would produce the same result.
<h2>does not work</h2>
{% for person in people %}
{{person}}
{% endfor %}
<h2>works</h2>
logan
paul
nicola
What the urls look like in page source:
views.py
def home(request):
return render(request, "APP/home.html", context={"people":['logan', 'paul', 'nicola']})
def person(request, name):
return render(request, 'APP/person.html', context={"name":name})
urls.py
urlpatterns = [
path('home/', views.home, name='home'),
path('person/<str:name>/', views.person, name='person'),
]

You don't need to wrap person variable into {{}} signs since in url tag you should use it directly:
{% for person in people %}
{{person}}
{% endfor %}
Check example here.

Related

How can I redirect to a page depend on different user group correctly by django?

I am creating a feature to let the banned user (user without any group) go to a specific page banned_alert when they click the "post", because they are not allowed to do so. But then when I test this feature, the Chrome shows This page isn’t working | the IP redirected you too many times. Can somebody tell me how to do it correctly? Did I miss any configuration? Below is my code snippets. Thank you for your time!
base.html: (has_group function already works correctly somewhere else)
{% load get_group %}
{% if request.user|has_group:"mod" or request.user|has_group:"default" or user.is_staff %}
<a class="nav-link" href="/create-post">Post</a>
{% else %}
<a class="nav-link" href="/banned_alert">Post</a>
{% endif %}
banned_alert.html:
{% extends 'main/base.html' %}
{% block title %}Your account has been banned by Admin{% endblock %}
{% load crispy_forms_tags %}
{% block content %}
<h2>Please contact the Admin!</h2>
{% endblock %}
view.py
def banned_alert(request):
return redirect('/banned_alert')
urls.py
urlpatterns = [
path('', views.home, name='home'),
path('home', views.home, name='home'),
path('sign-up', views.sign_up, name='sign_up'),
path('create-post', views.create_post, name='create_post'),
path('banned_alert', views.banned_alert, name='banned_alert'),
]
You have a recursion:
this is your path
path('banned_alert', views.banned_alert, name='banned_alert'),
User visit this banned_alert path,
it redirects user to view banned_alert
Which redirects user back to url banned_alert
and it redirects back to view banned_alert
reapeat N times (it has no ending)
best way to ban user is to create a flag in his model:
models.py
class User(AbstractUser):
is_banned = models.BooleanField(default=False)
if you want to ban user, change user's field is_banned to true, and then in your template or view, check if user is banned or not, and do your logic according to it
By the way, in your ulrs.py you need to close paths with backslash like this path('home/', views.home, name='home'),

TypeError: topics() missing 1 required positional argument: 'topic_id'

I'm following along a Django tutorial book to make a basic blogging application where users can write journal entries about whatever topic they choose. I've written the url, pattern, view, and template for my topic page but I keep getting this same error. but I think something is wrong with the url pattern.
urls.py
# Defines url patterns for learning_logs app
from django.conf.urls import url
from . import views
urlpatterns = [
# Home Page
url(r'^$', views.index, name='index'),
# Topic Main Page
url(r'^topics/$', views.topics, name='topics'),
# Detail page for a single topic
url(r"^topics/(?P<topic_id>\d+)/$", views.topics, name='topic'),
]
views.py
from django.shortcuts import render
from .models import Topic
# Create your views here.
def index(request):
# This is the home page for our learning_logs app
return render(request, 'learning_logs/index.html')
# This is the view for 'topics' page 9.5.20
def topics(request, topic_id):
'''show a single topic and its entries '''
topic = Topic.objects.get(id=topic_id)
entries = topic.entry_set.order_by('-date_added')
context = {'topic': topic, 'entries': entries}
return render(request, 'learning_logs/topics.html', context)
And the error:
TypeError: topics() missing 1 required positional argument: 'topic_id'
Any advice? Thank you.
EDIT**
What I'm trying to do is to have a page that lists all of the topics in general. When the link for one topic in particular is clicked, it will lead to the page for that particular topic.
Here's the code for the topics.html (all topics displayed) and topic.html (when one particular topic is chosen)..
topics.html
{% extends "learning_logs/base.html" %}
{% block content %}
<p>Topics</p>
<ul>
{% for topic in topics %}
<li>
{{ topic }}
</li>
{% empty %}
<li>No topics have been added yet</li>
{% endfor %}
</ul>
{% endblock content %}
and topic.html
{% extends "learning_logs/base.html" %}
{% block content %}
<p>Topic: {{ topic }}</p>
<p>Entries:</p>
<ul>
{% for entry in entries %}
<li>
<p>{{ entry.date_added|date:'M d, YH:i' }}</p>
<p>{{ entry.text|linebreaks }}</p>
</li>
{% empty %}
<li>No topics have been added yet</li>
{% endfor %}
</ul>
{% endblock content %}
The error clearly specifies that the function is not getting "topic_id", so there can be two cases
First, if you are using a template to redirect to that function(or view) you are not providing id, in that case, I might want to have a look at your template
Second, it's because of complex URL patterns so switch to something more simple likepath('topics/<int:topic_id>/', views.topics, name='topics'),
Lastly do not follow tutorial word to word because of things changes with update.
Your view is expecting a parameter passed to it ...
def topics(request, topic_id):
But your url does not have one:
url(r'^topics/$', views.topics, name='topics'),
You need to change the url to be something like:
path('topics/<int:topic_id>/', views.topics, name='topics'),
This means you would access that specific record at the url:
yourdomain.com/topics/1/
The 1 would be passed to the view, and used in topic = Topic.objects.get(id=topic_id)
The fact that you also have the url:
url(r'^topics/$', views.topics, name='topics'),
confuses matters - what is this view going to show with no topic set? From your code I suspect you want a list view here, which should ideally link to a different view, and maybe be named topics-list for clarity and ease of access in reverse lookups later. Your topics view specifically states in the docstring it is for viewing a single record, so don'ttry and use it for multiple ones as well. Much simpler to create a distinct view for that.
Edit: I see you've updated your path in urls.py in the question now. That should work for the single access, but note that your link topics/ is still directing to the same view - i.e. it's looking for a single record, but you're not telling it which.

Two variables in Django URL

I want a URL something like this:
/(category)/(post-slug)
On the link this is what I have:
{% url blog.category blog.slug %}
and for the url.py:
url(r'^(I DON"T KNOW WHAT TO PUT ON THIS PART TO GET THE CATEGORY)/(?P<slug>[0-9A-Za-z._%+-]+)', views.post, name='post'),
thanks
EDIT:
This is what I have now:
Still have NoReverseMatch error at /
urls.py
url(r'^(?P<category>[0-9A-Za-z._%+-]+)/(?P<slug>[0-9A-Za-z._%+-]+)$', views.post, name='post'),
index.html
<a href="{% url blog.category blog.slug %}">
views.py
def post(request, slug, category):
try:
blog = Blog.objects.get(slug=slug)
except Blog.DoesNotExist:
raise Http404('This post does not exist')
return render(request, 'parts/post.html', {
'blog': blog,
})
Firstly, your URL tag needs the name of the pattern you are reversing as the first argument:
{% url 'post' blog.category blog.slug %}
or if you are using a namespace, something like:
{% url 'blog:post' blog.category blog.slug %}
You haven't shown your views or models, so we can only guess what your URL pattern should be. I'm not sure why you find the category confusing - you just need to choose a name for the group (e.g. category_slug), and the regex for the group (you might be able to use the same one as you use for slug). That would give you:
url(r'^(?P<category_slug>[0-9A-Za-z._%+-]+)/(?P<slug>[0-9A-Za-z._%+-]+)$'
Note that there should be a dollar on the end of the regex.

Dynamic URL with variable django template

I'm trying to build a dynamic list of urls, based on a list of pages.
In my urls.py, the whole application is behind the namespace base:
urlpatterns = patterns('',
url(r'^(?P<pk>[\w]+)/title/$', TitleSection.as_view(), name='title'),
url(r'^(?P<pk>[\w]+)/amount/$', AmountSection.as_view(), name='amount'),
url(r'^(?P<pk>[\w]+)/description/$', DescriptionSection.as_view(), name='description'), )
And in my context data I have the following list:
sections: ['title', 'amount', 'description']
I am trying to build the urls for each of the element in the sections.
I tried the following:
{% for section in sections %}
..
{% endfor %}
But I got the following error:
Could not parse the remainder: '+section' from '"base:"+section'
Then I tried:
{{ section }}
Error:
Reverse for '{{section}}' with arguments '()' and keyword arguments '{u'pk': 77}' not found. 0 pattern(s) tried: []
Do you know how to do this?
You can use the add template filter:
{% url "base:"|add:section pk=project.id %}
for my case that also worked
{% for section in sections %}
..
{% endfor %}
where url pattern is
url=[
path('base/<pk>/',base,name='base'),
]
Each of my models has a list view, a create/update view, and a delete view. These will be used by different functions within the customer's organisation to maintain the data they are responsible for. Each list view has links to the relevant create, update, and delete views. I wanted to build a page with a list of links to the list view. Here's how I did it.
I created a function based view in views.py.
def index(request):
app = request.resolver_match.app_name
models = apps.get_app_config(app).get_models()
names = [model._meta.model.__name__ for model in models]
context = {
"names" : names,
}
return render(request, app + '/index.html', context)
I created a template app/templates/app/index.html
{% for name in names %}
<li>{{ name}}</li>
{% endfor %}

Django: html without CSS and the right text

First of all, this website that I'm trying to build is my first, so take it easy. Thanks. Anyway, I have my home page, home.html, that extends from base.html, and joke.html, that also extends base.html. The home page works just fine, but not the joke page. Here are some parts of my files, for you to understand how I want my system to work:
views.py
def joke_page(request, joke_id):
joke = Joke.objects.get(id=int(joke_id))
return render(request, 'joke.html', {'joke': joke})
urls.py
urlpatterns = [
url(r'^$', views.home_page, name='home_page'),
url(r'^(?P<joke_id>[0-9]+)/$', views.joke_page, name='joke_page'),
]
joke.html
{% extends 'base.html' %}
{% block header_text %}{{ joke.title }}{% endblock %}
{% block text %}{{ joke.text }}{% endblock %}
What I want is that URLs that end like jokes/1/ to render a page with the right html using joke.html. Instead, it renders a page without CSS or with joke.title and joke.text Also, I noticed that jokes/1/ doesn't find anything:
DoesNotExist at /jokes/1/
Joke matching query does not exist..
I had 20 jokes in the database and I can find jokes/2/ through jokes/21/, which means their ids have shifted? :P
Can someone experienced with Django point out my(many, without a doubt) mistakes? Thank you!
Edit: second urls.py
urlpatterns = [
url(r'^$', jokes_views.home_page, name='home'),
url(r'^jokes/', include(jokes_urls)),
url(r'^admin/', include(admin.site.urls)),
]
Are you using the {% load staticfiles %} in your templates?

Categories

Resources