The new Django 2.0 update broke my way of reversing url and printing it to the template. Using regular expression, it would work fine but when using the new simplified way, it returns an error.
NoReverseMatch at /blog/archive/
Reverse for 'article' with keyword arguments '{'id': 1}' not found. 1 pattern(s) tried: ['blog/article/<int:id>/$']
Here is what I use to print the url,
<h3 class="item-title">{{ article.title }}</h3>
Here is the url pattern,
url(r'^blog/article/<int:id>/$', views.article, name='article'),
and here is the article function,
def article(request, id):
try:
article = Article.objects.get(id=id)
except ObjectDoesNotExist:
article = None
context = {
'article': article,
'error': None,
}
if not article:
context['error'] = 'Oops! It seems that the article you requested does not exist!'
return render(request, 'blog/article.html', context)
I haven't found a solution to this yet. Hopefully this post will help others.
In Django 2.0, url() is an alias for re_path() and still uses regular expressions.
Use path() for the simplified syntax.
from django.urls import path
urlpatterns = [
path(r'^blog/article/<int:id>/$', views.article, name='article'),
]
Related
I am working on a django project(Django v2.0) which has users from different groups, this group is set up within the user profile. I would like to make the website more personal and have the user's group at the start of the website's url (added in through a slug), after they login.
Ideally once they login they would then be redirected to the right page with that slug at the beginning of the url. Within the login page I access the user's group, this group is called and will from now on be referred to as troop, to minimise confusion with Django groups. Here's my login class post view where I retrieve this:
def post(self, request):
def normal_user(user):
return user.groups.filter(name='Normal_User').exists()
username = request.POST['username']
password = request.POST['password']
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
if normal_user(user):
redirecting_url = 'accounts:home'
elif user.is_superuser:
redirecting_url = 'admin:index'
slug = user.userprofile.troop
return redirect(redirecting_url, slug=slug)
else:
form = AuthenticationForm()
error = True
args = {'form': form, 'error': error}
return render(request, self.template_name, args)
In this case I am trying to access the url "account" which I have called "home" and is in my app "accounts".
My home function in views.py in the app accounts has this code:
def home(request, slug):
args = {'user': request.user}
return render(request, 'accounts/home.html', args)
I do not want to do anything with the slug except display it in the url.
My template view looks like this:
<div class="container">
<br>
<h2><strong>Your Progress:</strong></h2><br>
<h3>
<strong>50% progress</strong>
<div class="progress">
<div class="progress-bar bg-danger progress-bar-striped progress-bar-
animated" role="progressbar" style="width:50%" aria-valuenow="50" aria-
valuemin="0" aria-valuemax="100">50%</div> </div>
</div></h3>
<br><br>
{% endblock %}
I also have a link to 'home' within my navbar and I link it in the similar fashion than the link above, using {% url 'accounts:home' slug = instance.slug %}
I'm currently having the following error:
"NoReverseMatch at /BC/account/
Reverse for 'home' with keyword arguments '{'slug': ''}' not found. 1 pattern(s) tried: ['(?P[-a-zA-Z0-9_]+)/account/$']"
The slug in this case is 'BC'.
My urls.py look like this:
In the root folder:
main_urls = [
path('leaders/admin/', admin.site.urls),
path('account/', include('accounts.urls', namespace='accounts'))
]
urlpatterns = [
path('', include('home.urls', namespace='home_page')),
path('login/', include('login.urls', namespace='login')),
path('<slug:slug>/', include(main_urls))
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
And my urls.py in my accounts app looks something like this:
app_name="accounts"
urlpatterns = [
path('', views.home, name="home")
]
Sorry for the long description, but I've been reading every possible site/video I could find on Django slugs and have not been able to find anything which works yet. Could someone please help me with this problem?
Your regular expression for your url requires the slug to be at least one character long. However, the exception you're getting suggests that the troop name (which is used as the slug named argument) is empty:
Reverse for 'home' with keyword arguments '{'slug': ''}'
If the user isn't required to have a troop, in which case you want to just redirect him to /accounts/ instead of /troop/accounts, I suggest you add a separate URL for just accounts/$, or tweak the regular expression to allow an empty troop.
After poking around my code I found something which works. This is as it seems to be that I should be able to have views which take in a slug argument whilst still working if the slug is empty. To fix this all I did was change the slug part in my view function definitions to **kwargs.
Then I added a varaiable which accessed what the slug was and passed that through my templates for when I have a link.
For example:
def home(request, **kwargs):
slug = request.user.userprofile.troop
args = {'slug_arg': slug}
return render(request, 'accounts/home.html', args)
My links in my templates then look like this: {% url 'accounts:home' slug=slug_arg %}
Edit
I have found that the problem was that during my rendering, I should be able to pass through the slug, and in this case slug=instance.slug was not working and was sometimes coming up as being empty. However if I have it at slug=request.user.userprofile.troop then this works without having to accept an argument from the view.
In having said such, I am unable to do this for the admin site as I do not know how to access the views.py for the admin and thus add the parameter to take in the slug.
I tried get the id from my database and make something like /article/1/. 1 is the id of my article but it didn't work.
views.py
def article(request, article_id):
return render_to_response('article.html', {{'article': Articles.objects.get(id=article_id)}})
my urls.py
from django.urls import path, re_path
from . import views
urlpatterns = [
path('showall/', views.articles, name='articles'),
path('<int:article_id>/', views.articles, name='article'),
]
I get the error:
TypeError at /article/1/ articles() got an unexpected keyword argument 'article_id'
I also include image of my datebase
Datebase
It looks as if you are using views.articles for the article detail view:
path('<int:article_id>/', views.articles, name='article'),
You should use views.article instead:
path('<int:article_id>/', views.article, name='article'),
Note that there are a few improvements/fixes you can make to your article view:
Use get_object_or_404 so that you don't get a server error when the article does not exist in the database
Use render instead of the obsolete render_to_response
The context dictionary should be a dictionary {...}. You currently have double curly brackets {{...}}
Putting that together you get:
from django.shortcuts import get_object_or_404, render
def article(request, article_id):
article = get_object_or_404(Article, id=article_id)
return render(request, 'article.html', {'article': article})
Your views.py defines an article function while your urls.py makes use of an articles (note the plural) function. Is this a typo, or is there any articles function in views.py that does not support an optional article_id parameter?
You are using views.articles in article/id/ url which most likely you have used for article/showAll/ url. Use this instead:
path('<int:article_id>/', views.article, name='article')
There are a few posts related to my problem. However, none seems to solve the following issue:
I have defined urls in myapp/urls.py:
app_name = "myapp"
urlpatterns=[
url(r'^$', views.index, name="index"),
url(r'^adduser/$', views.addUser, name="adduser"),
]
and corresponding views in myapp/views.py:
def index(request, status_msg=None, error_msg=None):
return HttpResponse(render(request, "myapp/index.html",
context={"error_message":error_msg, "status_message":status_msg}))
def addUser(request):
try:
uname=request.POST["user_name"]
except KeyError:
url = reverse("myapp:index", args=(None, "No user name specified."))
return HttpResponseRedirect(url)
# ... adding user to db ...
url = reverse("myapp:index", args=("Added user '%s'"%uname,))
return HttpResponseRedirect(url)
Either variant of passing arguments to index() from the redirect in addUser() yields an error of the kind
Reverse for 'index' with arguments '(None, u'No user name specified.')' not found. 1 pattern(s) tried: [u'myapp/$']
I don't get what I'm doing wrong here. Seems the index view is found but not recognized to allow any arguments aside the request?
Using kwargs instead of args does not help, either.
Any suggestions are highly appreciated. Thanks already!
Your URL doesn't seem to support arguments (i.e captured groups in the regex). Therefore you should be using just:
reverse("myapp:index")
Check the docs for the reverse() function here.
Can't figure out how to solve this error
Here is the urls.py snippet:
urlpatterns = [
...
url(r'^delete_tidbit/', views.delete_tidbit, name='delete'),
...
]
The view:
def delete_tidbit(request, pk):
tidbit = Tidbit.objects.get(pk=pk)
tidbit.delete()
return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
And the portion of the template that raises this error:
<a href="{% url 'delete' tidbit.pk %}">
The issue is here:
url(r'^delete_tidbit/', views.delete_tidbit, name='delete'),
This URL doesn't accept an argument, where as you are trying to give it one.
Try this instead:
url(r'^delete_tidbit/(?P<pk>.*)', views.delete_tidbit, name='delete'),
But beware: you are accepting GET requests to delete items in your database, any crawler coming across those links may try to follow them and inadvertently delete your data. Consider using a GET that delivers a form to be POSTed to ensure an actual user is doing the action.
This seems to be a "classic" problem :
NoReverseMatch at /tr/showroom/
Reverse for 'project-list' with arguments '()' and keyword arguments '{}' not found. 0 pattern(s) tried: []
But the problem is, when I check the different topic on the internet and then my files, I don't get it.
So it's working perfectly on the native language. It happens when I try to change the language on this showroom page only.
Every page that have been copy with the commad cms copy works fine except this one.
Well, here is the model :
def get_slug(self):
return self.safe_translation_getter(
'slug',
language_code=get_language(),
any_language=False)
def get_absolute_url(self, current_app=None):
"""
Warning: Due to the use of django application instance namespace
(for handle multi instance of an application)we add the possibility
to use it with the reverse.
So if get_absolute_url is call without app instance it may failed (
for example in django_admin)
"""
lang = get_language()
if self.has_translation(lang):
kwargs = {'slug': self.get_slug()}
return reverse('djangocms_showroom:project-detail',
kwargs=kwargs,
current_app=current_app)
return reverse('djangocms_showroom:project-list', current_app=current_app)
def get_full_url(self, site_id=None):
return self._make_full_url(self.get_absolute_url(), site_id)
def _make_full_url(self, url, site_id=None):
if site_id is None:
site = Site.objects.get_current()
else:
site = Site.objects.get(pk=site_id)
return get_full_url(url, site)
The url :
from django.conf.urls import patterns, url
from .views import (ProjectListView, ProjectDetailView)
urlpatterns = patterns(
'',
url(r'^$', ProjectListView.as_view(), name='project-list'),
url(r'^project/(?P<slug>\w[-\w]*)/$', ProjectDetailView.as_view(), name='project-detail'),
)
And the html error :
Error during template rendering
In template /var/www/webapps/blippar_website/app/blippar/templates/djangocms_showroom/project_list.html, error at line 14
Which is :
<form id="projects-filter" action="{% url 'djangocms_showroom:project-list' %}">
Well, I am not very good yet with django and django-cms, if someone has any clue, it would be marvellous !