trouble converting Python regex to path with django - django-views

I am working on a project which uses regex urls. The way it is currently designed is you have to manually type the url as a model field which then gets passed to the urls/views as an argument? (I don't fully understand this part yes, still learning). These are the views, urls, and the templates which I think are the issue here. I am trying to automatize the process of adding the slug and that part is working. However, I can't seem to find a way around getting it to work with the way urls are configured currently.
the views sections:
class QuizDetailView(DetailView):
model = Quiz
slug_field = 'url'
template_name = 'exam/quiz_detail.html'
another section of the view where I think the url from the above snippet is turned into a variable which then gets used in url:
class QuizTake(FormView):
form_class = QuestionForm
template_name = 'exam/question.html'
def dispatch(self, request, *args, **kwargs):
self.quiz = get_object_or_404(Quiz, url=self.kwargs['quiz_name'])
if self.quiz.draft and not request.user.has_perm('quiz.change_quiz'):
raise PermissionDenied
The urls:
#passes variable 'quiz_name' to quiz_take view
url(regex=r'^(?P<slug>[\w-]+)/$',
view=QuizDetailView.as_view(),
name='quiz_start_page'),
url(regex=r'^(?P<quiz_name>[\w-]+)/take/$',
view=QuizTake.as_view(),
name='quiz_question'),
and finally the template snippets, this is a detail view of the model/quiz:
<a href="{% url 'quiz_start_page' quiz.url %}">
this one displays the model (which is a quiz users take):
<a href="{% url 'quiz_question' quiz_name=quiz.url %}">
What I have tried so far:
first, since I have the slug field:
class QuizDetailView(DetailView):
model = Quiz
slug_field = 'url' ---this was commented out
template_name = 'exam/quiz_detail.html'
next, I changed the urls from:
url(regex=r'^(?P<slug>[\w-]+)/$',
view=QuizDetailView.as_view(),
name='quiz_start_page'),
url(regex=r'^(?P<quiz_name>[\w-]+)/take/$',
view=QuizTake.as_view(),
name='quiz_question'),
to:
path('<slug:slug>/', QuizDetailView.as_view(), name='quiz_start_page'),
path('<slug:slug>', QuizTake.as_view(), name='quiz_question'),
Then I changed the temlates from:
<a href="{% url 'quiz_start_page' quiz.url %}">
<a href="{% url 'quiz_question' quiz_name=quiz.url %}">
To:
<a href="{% url 'quiz_start_page' quiz.slug %}">
<a href="{% url 'quiz_question' quiz.slug %}">
When I click on the listview for the model/quiz, the url is displayed correctly on browser which I think means the automatic slug is working. However, once I click the link I see this error:
Reverse for 'quiz_question' with keyword arguments '{'quiz_name': ''}' not found. 1 pattern(s) tried: ['(?P<slug>[-a-zA-Z0-9_]+)$']
Really appreciate any help/pointers

Just figured it out myself, I realized I left out the argument which links the Quiz to the TakeQuiz model above.
path('<quiz_name>', QuizTake.as_view(), name='quiz_question'),
Above, instead of the slug I passed the argument <quiz_name> and changed the templates too:
{% url 'quiz_question' quiz_name=quiz.slug %}
That worked.

Related

Does This Hierarchy work with ListView? Getting NoReverseMatch Error

I'm running into an issue debugging the following error:
Reverse for 'tasks' with arguments '('',)' not found. 1 pattern(s) tried: ['customer/(?P[-a-zA-Z0-9_]+)/tasks/$']
However, I'm pretty certain that my url parameters are correct and without typos. The url and page worked fine with a function based view, the problem started when I changed to a ListView.
Template:
<a href="{% url 'customerportal:tasks' object.slug %}" class="nav-link">
I also tried:
<a href="{% url 'customerportal:tasks' slug=object.slug %}" class="nav-link">
<a href="{% url 'customerportal:tasks' slug=object.slug|slugify %}" class="nav-link">
DetailView - passing slug param to url
class ProjectDetailView(DetailView):
model = Project
template_name = 'customerportal/customer_portal.html'
def get(self, request, *args, **kwargs):
self.object = self.get_object()
if not self.object.access_verification(request.user):
raise PermissionDenied()
context = self.get_context_data(object=self.object)
return self.render_to_response(context)
My ListView (errors):
class TaskListView(ListView):
model = Task
template_name = 'customerportal/tasks.html'
def get_queryset(self):
self.project = get_object_or_404(Project, slug=self.kwargs['customer_portal'])
return Task.objects.filter(project=self.project.id)
URLs:
path('<slug:slug>/', ProjectDetailView.as_view(), name='customer_portal'),
path('<slug:customer_portal>/tasks/', TaskListView.as_view(), name='tasks'),
I've confirmed that I'm passing the right slug by printing it. The slug parameter is from a parent directory as seen in the urls.py above. I'm guessing ListView doesn't work this way? If not is there a way I could maintain this structure, or do I have to switch back to a function based view in order to get this to work?
Thanks.
there is 2 things to sort out:
your error message says that there is a path that looks similar to this:
path('customer/<slug:customer_portal>/tasks/', TaskListView.as_view(), name='tasks'),
but your paths do not match that pattern of the error message - maybe you edited the paths after the error appeared.
the error type "... arguments '('',)' ..." always means that the parameter in your {% url ... %} statement is empty. In your case that would mean object.slug is empty
Please check what you handover to the template as object.slug

i am not able to render my urls in my template it gives me error rendering

NoReverseMatch at /
Reverse for 'Jersey' with no arguments not found. 1 pattern(s) tried: ['Jersey/(?P[^/]+)/$']
Below is the code to my views.py
class JerseyView(TemplateView):
#paginate_by=3
template_name='Ecommerce/Jersey.html'
def get_context_data(self, **kwargs):
et =super(JerseyView, self).get_context_data(**kwargs)
et['United']= Item.objects.filter(category="3").filter(subcategory="9")
et['Chelsea']= Item.objects.filter(category="3").filter(subcategory="10")
return et
below is the code for my urls.py
path('Jersey/<slug>/', JerseyView.as_view(), name="Jersey" ),
I called This link in my Navbar as
<a class="dropdown-item" href="{% url 'Ecommerce:Jersey' %}">Men's Clothing</a>
when I click on it it gives me the error as NoReverseMatch at / Reverse for 'Jersey' with no arguments not found. 1 pattern(s) tried: ['Jersey/(?P[^/]+)/$']
I don't know if there's something i am missing out because i have checked my spelling and still getting the same error
By using {% url 'Ecommerce:Jersey' %}, you're trying to access Jersey/<slug> path without giving any argument. So Django router expect a argument on this path (slug).
You need to provide it, (only you knows what slug goes there...) like this :
{% url 'Ecommerce:Jersey' Jersey.slug %}
is this slug dynamically change or not? if it is then first you should correct your url like this: 'Jersey/<slug:slug>/' and in href tag, get slug from context you passed in views.py like what user BriseBalloches said. but if your slug is a fixed parameter, you can just write it in href tag. suppose your slug parameter is country then your href tag should work with href="Jersey/country" or href="{% url 'Ecommerce:Jersey'country %}"
these href tags will generate http://127.0.0.1:8000/Jersey/country

Django - reverse not working and I don't know why

I've used reverse before and it's been fine. But now, I don't know why it's not working. It might be because I'm trying to reverse to a class based view and I've never done that before.
Here's my code -- where am I messing it up?
views.py:
class DocumentRequestDetail(NavMixin, TitleMixin, SelectedBrokerage, DetailView):
model = DocumentRequest
mod_nav = 'brokerage_nav.html'
context_object_name = 'doc'
subtitle = 'Document Request Details'
def MarkDocRequestComplete(request, bpk, pk):
d = DocumentRequest.objects.get(pk= pk)
d.is_complete = True
d.save()
return reverse('doc_request_detail', args=[bpk, pk]) #<--- the offending line
urls.py
from django.conf.urls import include, url
from django.views.generic.list import ListView
from brokerage.views import *
urlpatterns = [
url(r'^(?P<pk>[0-9]+)/detail/$', BrokerageDetail.as_view(), name="brokerage_detail"),
url(r'^(?P<pk>[0-9]+)/edit/$', BrokerageEdit.as_view(), name="brokerage_edit"),
url(r'^(?P<bpk>[0-9]+)/doc-request/all/$', DocumentRequestList.as_view(), name="doc_request_list"),
url(r'^(?P<bpk>[0-9]+)/doc-request/(?P<pk>[0-9]+)/$', DocumentRequestDetail.as_view(), name="doc_request_detail"),
url(r'^(?P<bpk>[0-9]+)/mark-doc-request-complete/(?P<pk>[0-9]+)/$', MarkDocRequestComplete, name="mark_doc_request_complete"),
]
HTML Link that calls MarkDocRequestComplete:
<a href="{% url 'brokerage:mark_doc_request_complete' brokerage.pk doc.pk %}" class='btn btn-lg btn-wide btn-success'>
<i class='ti-check'></i>
Mark Complete
</a>
Error When Clicking HTML Link:
Reverse for 'doc_request_detail' with arguments '(u'1', u'19')' and keyword arguments '{}' not found. 0 pattern(s) tried: []
I don't get it... what am I doing wrong?
Edit I should say that, in the error, the 1 and 19 are the correct values for bpk and pk.
Edit 2 Added full URLs.py
The reason your url tag isn't working, is because you are namespacing it by adding brokerage: to it), when there is no namespace setup in your urls. See the documentation on how to properly setup namespaces.
The correct tag should be:
{% url 'mark_doc_request_complete' bpk=brokerage.pk pk=doc.pk %}
You have to change:
return reverse('doc_request_detail', args=[bpk, pk])
to
return reverse('doc_request_detail', kwargs={'bpk': bpk, 'pk': pk})
You must also change your template tag from:
<a href="{% url 'brokerage:mark_doc_request_complete' brokerage.pk doc.pk %}" class='btn btn-lg btn-wide btn-success'>
to:
<a href="{% url 'brokerage:mark_doc_request_complete' bpk=brokerage.pk pk=doc.pk %}" class='btn btn-lg btn-wide btn-success'>
The reason for these changes is because you have names in your regular expression groups.

Dynamically Create Django URL Slug in Function Based View

I have been banging my head against the wall for hours on this and its probably incredibly simple.
I need to generate two url slugs from one model. One is actually called slug and is a SlugField which is for the Product title, and the other is a category which is a ForeignKey.
Ideally what I would like to have is
url(r'^products/(?P<category>[^\.]+)/(?P<slug>[^\.]+)/$', tool_detail, name='tool_detail'),
But, the category part of the URL keeps giving generating an "invalid literal for int(), with base 10: 'category' - well, this is one of the errors, I tried many different combinations.
Model
...
slug = models.SlugField()
category = models.ForeignKey(Category)
...
View
def tool_detail(request, slug):
tool = get_object_or_404(Tool, slug=slug)
part = get_object_or_404(Part)
return render(request, 'tool_detail.html', {'tool': tool, 'part': part})
Template
<a href="{% url 'tool_detail' t.category slug=t.slug %}" ... </a>
URL
url(r'^products/tools/(?P<slug>[^\.]+)/$', tool_detail, name='tool_detail'),
Ugh...see how /tools/ is hardcoded?
Thank you for your help.
URL
# query by primary key.
url(r'^products/(?P<category>[0-9]+)/(?P<slug>[^\.]+)/$', tool_detail, name='tool_detail'),
# query by the name.
url(r'^products/(?P<category>[\w]+)/(?P<slug>[^\.]+)/$', tool_detail, name='tool_detail'),
View
def tool_detail(request, **kwargs):
tool = get_object_or_404(Tool, slug=kwargs.get('slug'))
part = get_object_or_404(Part)
return render(request, 'tool_detail.html', {'tool': tool, 'part': part})
Should work it isn't tested.
In url only pass on parameter slug, but on url tag you pass two paramter. Only modify like as
Templates
<a href="{% url 'tool_detail' t.slug %}" ... </a>
If slug is int we can change url
url(r'^products/tools/(?P<slug>[0-9]+)/$', tool_detail, name='tool_detail'),
Some example about how to pass dynamic parameter on url tag
https://docs.djangoproject.com/en/1.9/intro/tutorial04/

multiple Id arg django

I have an issue with my web-app django.
In example, user can add an artist, and with this artist, he can (list, delete, play) music.
When the user click on the artist, the URL is 'music/1/' where the artist ID is 1, and music is listed.
When user want delete a music, the URL is 'delmusic/1/' where the music ID is 1.
delmusic function works, but returns an error PageNotFound with this http URL :
'http://host.local/appli/delmusic/1/webgui.views.music'
My urls.py :
url(r'^music/(\d+)/$', 'webgui.views.music'),
url(r'^delmusic/(\d+)/$','webgui.views.delmusic'),
My music template :
<a href="{% url 'webgui.views.delmusic' music.id %}"style="margin-bottom: 3px" type="button">
My view :
def music(request, id):
listmusic = Music.objects.filter(artist=id)
return render(request, 'music.html', {'listmusic': listmusic})
def delmusic(request, id):
music = Music.objects.get(id=id)
music.delete()
return redirect('webgui.views.music')
I think there is confusion with music.id and arist.id, but I don't know..
Maybe you will have an idea ?
You have a slight issue with your urls.py - the 2nd argument points to the views function, but is not used as a reference in the templates, for that you need to do:
url(r'^music/(\d+)/$', 'webgui.views.music', name='music'),
url(r'^delmusic/(\d+)/$','webgui.views.delmusic', name='delmusic'),
and then in the template
<a href="{% url 'delmusic' music.id %}" style="margin-bottom: 3px" type="button">
or if you had a namespace defined for your app in django_settings/urls.py:
<a href="{% url '<APPNAMESPACE>:delmusic' music.id %}" style="margin-bottom: 3px" type="button">
and then at then in views.py do
from django.core.urlresolvers import reverse
def delmusic(request, id):
music = Music.objects.get(id=id)
artist_id = music.artist.id
music.delete()
return redirect(reverse('music', args=[artist_id]))