In my online store django project, I want to create a sub-page which shows the details of a product that is listed in a page.
in urls.py I created the urls for both pages like bellow:
path('wwqm', views.water_quality_sensor , name='wwqm'),
path('wwqm/<str:water_sensor_title>', views.water_sensor_item, name='water_sensor_item'),
in this scenario, a bunch of items are being shown in wwqm. user click on a product and the water_sensor_item should load up.
I know its not important but here is views.py:
def water_quality_sensor(request):
queryset_list = Water_quality_sensor.objects.order_by('-product_name').filter(is_published=True)
context = {
'water_quality_sensor': queryset_list,
}
return render(request, 'products/water_quality_sensor.html', context)
def water_sensor_item(request, water_sensor_title):
water_sensors = get_object_or_404(Water_quality_sensor, title=water_sensor_title)
context = {
'water_sensors': water_sensors
}
return render(request, 'products/water_sensor_item.html' , context)
I try to build the url for each item based on a parameter that is passed to its view(products title).
In my templates, I try to create a link like the following:
<a href="{% url 'water_sensor_item' w_q_sensor.title %}" class="card hoverable mb-4 text-dark" >
one my products' title is 3725. when I click on that product in the main page, I get the following error:
Django Version: 3.1.2
Exception Type: NoReverseMatch
Exception Value: Reverse for 'water_quality_sensor' not found. 'water_quality_sensor' is not a valid view function or pattern name.
What am I doing wrong?
in your urls.py
path('wwqm', views.water_quality_sensor , name='wwqm'),
you used name wwqm. But it looks like somewhere in your template (most likely water_sensor_item.html), you have something similar to :
<a href="{% url 'water_quality_sensor' %}"
Change it to wwqm or change name in urls.py
UPDATE
It is better to use <str:title><int:pk> in your urls, to avoid when you have the same name in two products. pk is unique.
in your urls.py
path('wwqm/<str:water_sensor_title><int:pk>', views.water_sensor_item, name='water_sensor_item'), # add <int:pk>
in your template:
# since url is taking both title and pk arguments, you need to provide both of them.
<a href="{% url 'water_sensor_item' title= w_q_sensor.title pk=w_q_sensor.pk %}" class="card hoverable mb-4 text-dark" >
in your view:
def water_sensor_item(request, water_sensor_title, pk): # added pk
water_sensors = get_object_or_404(Water_quality_sensor, pk=pk) # use pk to get the object
context = {
'water_sensors': water_sensors
}
return render(request, 'products/water_sensor_item.html' , context)
Related
I am building a blog where users can click on several <li> items in the sidebar to show blog posts according to the clicked category.
The desired outcome is somewhat to the official documentation, so that I will end up with /blog/category and the according blog posts rendered.
The problem is that if I visit the main page (or http://127.0.0.1:8000/ in development) it raises an error
render_blog() missing 1 required positional argument: 'category'
So how can I use the view render_blog both for the main page and for the categories clicked to render the according blog posts?
html
<li class="navigation-item" id="spotlights-item">
<div id="spotlights-ctn">Hot Stocks<img id="fire-icon" src="{% static 'images/fire.svg' %}" alt="finsphere.io"></div>
</li>
urls
urlpatterns = [
path('AsiaPacific/<category>', render_blog, name='AsiaPacific'),
url(r'^$', render_blog, name='render_blog'),
]
views.py
def render_blog(request, category):
category = category
if not category:
# Main blog as landing page
# Get 5 latest posts and order by publish date, newest first
posts = Post.objects.filter(publish_date__lte=now).order_by('-publish_date')[:5]
return render(request, 'blog/blog.html', {'posts': posts})
else:
# Blog displayed as Category Selection
posts = Post.objects.filter(categories__title=category, publish_date__lte=now)
return render(request, 'blog/blog.html', {'posts': posts})
Im not 100% sure I'm following, but you don't have to use the href on an anchor tag to link anywhere. You can just set href="" and give every link a class such as "category-link". Then tie your ajax onclick event to the class, and have the code first pull the text or another attribute from the link and submit it as a variable:
$('.category-link').on('click', function() {
var link = $(this);
var page = link.data('page');
var category = link.data('category');
$.ajax({
type: 'post',
url: '/lazy_load_posts/',
data: {
'page': page,
'category': category,
'csrfmiddlewaretoken': window.CSRF_TOKEN // from blog.html
},
(...)
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.
I have a block of code on my template which does not show up on my html nor does it give any error on Chromes console. I am trying to display a list of images which when clicked takes you to the detail of that image.
Here is the key part of my HTML(base.html):
<div class="container-fluid">
<h2>Popular</h2> #only this shows up
{% for obj in object_list %}
<img src = "{{ obj.mpost.url}}" width="300"><br>
<a href='/m/{{ obj.id }}/'> {{obj.username}} </a><br/>
{% endfor %}
</div>
views.py:
from django.shortcuts import render,get_object_or_404
from .models import m
# Create your views here.
def home(request):
return render(request,"base.html",{})
def m_detail(request,id=None):
instance = get_object_or_404(m,id=id)
context = {
"mpost": instance.mpost,
"instance": instance
}
return render(request,"m_detail.html",context)
def meme_list(request): #list items not showing
queryset = m.objects.all()
context = {
"object_list": queryset,
}
return render(request, "base.html", context)
urls.py:
urlpatterns = [
url(r'^$', home, name='home'),
url(r'^m/(?P<id>\d+)/$', m_detail, name='detail'),#issue or not?
]
models.py:
class m(models.Model):
username = "anonymous"
mpost = models.ImageField(upload_to='anon_m')
creation_date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return m.username
Thank you so much for your time. :)
I assume the problem is the fact that you don't have a url at all for the meme list, so either you're showing the home view and need to move the code from the meme_list view into your home view, or you need to make a url for the meme_list (and navigate to that new url instead)
I am attempting to create a simple forum application and am getting this error. I am inclined to think this may have something to do with my URLConf or possibly the way I am using the URL template tag to generate the URL for each thread.
/forums/urls.py
# ex: /forums/general_forum
url(r'^(?P<forum_slug>[-\w\d]+)/$', views.forum, name='forum'),
# ex: /forums/general_forum-1/my_first_thread
url(r'^(?P<forum_slug>[-\w\d]+)/(?P<thread_slug>[-\w\d]+)/$', views.thread, name='thread'),
/forums/views.py
The index view works fine, the forum view does not.
def index(request):
context = RequestContext(request)
forum_list = Forum.objects.order_by("sequence")
for forum in forum_list:
forum.url = slugify(forum.title) + "-" + str(forum.id)
context_dict = {'forum_list': forum_list}
return render_to_response('forums/index.html', context_dict, context)
#login_required
def forum(request, forum_slug):
context = RequestContext(request)
try:
forum = Forum.objects.get(slug=forum_slug)
threads = Thread.objects.filter(forum=forum)
context_dict = {'forum': forum,
'threads': threads}
except Forum.DoesNotExist:
pass
return render_to_response('forums/forum.html', context_dict, context)
This is how I am linking to the forum view inside index.html.
<a href={% url 'forum' forum.slug %}>{{ forum.title }}</a>
And in forum.html, this is how the links are formulated to view the posts inside the thread. This :
<a href={% url 'forum' forum.slug %}/{% url 'thread' thread.slug %}>{{ thread.title }}</a>
The error. One of the threads is titled 'django'
NoReverseMatch at /forums/web-development/
Reverse for 'thread' with arguments '(u'django',)' and keyword arguments '{}' not found. 2 pattern(s) tried: ['forums/(?P<forum_slug>[-\\w\\d]+)/(?P<thread_slug>[-\\w\\d]+)/$', '$(?P<forum_slug>[-\\w\\d]+)/(?P<thread_slug>[-\\w\\d]+)/$']
In the error, the url template tag for 'thread' is highlighted in red and states there was an error during template rendering. This error seems unclear to me and I am not sure if this is an issue with the way I am using the template tags or something else.
You're not passing the Forum slug in your thread URL, which your URL configuration requires:
<a href={% url 'forum' forum.slug %}/{% url 'thread' thread.slug %}>{{ thread.title }}</a>
You should not be using both urls, either. Instead, what you want is:
{{ thread.title }}
I'm just starting with django (and python too, to be honest)
I am trying to get a model method that would cut the self.slug from current URL and return it to template.
This is the method I tried:
class Category(models.Model):
...
def remove_filter(self):
url = HttpRequest.get_full_path()
slug = '/' + self.slug
return url.replace(slug, '')
But as you can imagine, it doesn't work.
Template's snippet:
{% for object in active_filters %}
<li><i class="icon-remove"></i>{{ object }}</li>
{% endfor %}
My core goal here is to have a front-end icon with a url altered by removing current object's slug.
I have no idea how to do it through views, but I'm open to any suggestions.
def category_page(request, url):
slugs = url.split('/')
active = Category.objects.filter(slug__in=slugs)
sorted_slugs = []
for i in active:
sorted_slugs.append(i.slug)
if slugs != sorted_slugs:
url = '/'.join(sorted_slugs)
return redirect('http://127.0.0.1:8000/catalog/' + url)
inactive = Category.objects.exclude(slug__in=slugs)
return render(request, 'category.html', {'active_filters': active,
'inactive_filters': inactive})
Thanks.
You can send a list of all active slugs to the template and then build a custom template filter to construct the modified url.
views.py
# Send your list of active slugs to the template
return render(request, 'category.html', {
'active_filters': active,
'inactive_filters': inactive,
'slugs': slugs,
})
tags_and_filters.py
import copy
from django import template
register = template.Library()
#register.filter(name='remove_filter')
def remove_filter(category, slugs):
copied_slugs = copy.copy(slugs)
slug = category.slug
if slug in copied_slugs:
copied_slugs.remove(slug)
return '/'.join(copied_slugs)
your template
{% for object in active_filters %}
<li>
<i class="icon-remove"></i>{{ object }}
</li>
{% endfor %}
Your remove_filter method has no access to the current request. HttpRequest is the class, not the current request instance.
I suggest that you rewrite remove_filter as a custom tag or filter. That way your function can access the category and request instance. You will have to activate the request template context processor in your settings as well.