How do I nest url calls in django? For example, if I have two models defined as
class Post(models.Model):
title = models.CharField(max_length=50)
body = models.TextField()
created = models.DateTimeField(auto_now_add=True, editable=False)
def __unicode__(self):
return self.title
#property
def comments(self):
return self.comment_set.all()
class Comment(models.Model):
comment = models.TextField()
post = models.ForeignKey(Post)
created = models.DateTimeField(auto_now_add=True)
With the following url files
root url
urlpatterns = patterns('',
url(r'^post/', include('post.urls')),
)
post url
urlpatterns = patterns('',
url(r'^$', views.PostList.as_view()),
url(r'^(?P<pk>[0-9]+)/$', views.PostDetail.as_view()),
url(r'^(?P<pk>[0-9]+)/comments/$', include('comment.urls')),
)
comment url
urlpatterns = patterns('',
url(r'^$', CommentList.as_view()),
url(r'^(?P<pk>[0-9]+)/$', CommentDetail.as_view()),
)
But when I go to /post/2/comments/1, I am given a Page not found error stating
Using the URLconf defined in advanced_rest.urls, Django tried these URL patterns, in this order:
^post/ ^$
^post/ ^(?P<pk>[0-9]+)/$
^post/ ^(?P<pk>[0-9]+)/comments/$
The current URL, post/2/comments/1, didn't match any of these.
This is not a problem though when I visit /post/2/comments Is this not allowed by django to have nested URL calls like this?
I think is probably because you're finishing the regex with the dollar sign $. Try this line without the dollar sign:
...
url(r'^(?P<pk>[0-9]+)/comments/', include('comment.urls')),
...
Hope it helps!
You have a $ at the end of r'^(?P<pk>[0-9]+)/comments/$'.
That means Django will only match with that URL when there is nothing after that.
So any longer URLs currently won't be considered. Therefore, you need to update the regular expression to:
url(r'^(?P<pk>[0-9]+)/comments/', include('comment.urls')),
Above Django 2.0 you can use simply...
urlpatterns = [
path('<pk>/comments/', include('comment.urls')),
]
Related
So, I would like top stop ursing urlpatterns and just use router. But instead of using ID of an object I'm using UUID instead and I'm using it with urlpatterns and dont't find some way to use it with routers.
this is my current model:
class Board(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=200, blank=False, null=False)
this is my core app urls.py:
...
router = DefaultRouter()
router.register(r'boards', BoardViewSet)
router.register(r'y', yViewSet)
router.register(r'z', zViewSet, basename='z')
urlpatterns = [
path('', include(router.urls)),
path('board-list/<uuid:pk>/', BoardViewSet.as_view({'get': 'list'}), name='boards'),
]
and this is the project urls.py:
from django.contrib import admin
from django.urls import path, include
from core.urls import router as api_router
routes = []
routes.extend(api_router.urls)
urlpatterns = [
path('api/', include((routes, 'board_microservice'), namespace='v1')),
path('admin/', admin.site.urls),
]
the application usage is ok, but I have some troubles with test.
i.e:
this works well:
url = reverse('v1:board-list')
response = api_client().get(
url
)
and it isn't working:
board = baker.make(Board)
url = reverse('v1:board-list', kwargs={"pk": board.id})
response = api_client().get(url)
I receive
django.urls.exceptions.NoReverseMatch: Reverse for 'board-list' with keyword arguments
and I think I can replace urlpatterns by router to solve it and turns it more simple
There is any way to do it with router?
You haven't shared your view, but it seems you are using a ModelViewSet and you seem to be looking for the retrieve endpoint rather than list (judging from using a pk). If so then you want to use -detail instead of -list:
url = reverse('v1:board-detail', kwargs={"pk": board.id})
Board_list is not what you want to call... Try board_get instead.
Board list takes no argument. But get does.. To get a particular board.
Hi I am trying to create a blog using the Django webframework.
I get the error,
No URL to redirect to. Either provide a url or define a get_absolute_url method on the Model.
The urls.py is given below,
from django.urls import path
from .views import (
BlogListView,
BlogDetailView,
BlogCreateView,
BlogUpdateView,
)
urlpatterns = [
path('post/<int:pk>/edit', BlogUpdateView.as_view(), name='post_edit'),
path('post/new/', BlogCreateView.as_view(), name='post_new'),
path('post/<int:pk>/', BlogDetailView.as_view(), name='post_detail'),
path('', BlogListView.as_view(), name='home'),
]
The models.py is given below,
from django.db import models
from django.urls import reverse
# Create your models here.
MAX_LENGTH = 500
class Post(models.Model):
title = models.CharField(max_length=MAX_LENGTH)
author = models.ForeignKey('auth.User', on_delete=models.CASCADE,)
body = models.TextField()
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post_detail', args=[str(self.id)])
Where am I going wrong?
From your indentation it looks as if your methods on the Post class are instead in the global scope. They should have the same indendation as the title, author and body field (i.e. 4 spaces/1 tab).
For some reason Django is not appending a slash at the end of variables that contain numeric characters:
test_A -- works (goes to test_A/)
test_1 -- does not (doesn't append the / at the end - giving me a 404)
I do have middleware installed and APPEND_SLASH = True.
Any thoughts? Thanks!
url.conf:
from django.conf.urls import patterns, url
from dashboard import views
urlpatterns = patterns('',
url(r'^$', views.index, name='index'),
url(r'^environment/(?P<environment_name_url>\w+)/$', views.environment, name='environment'),)
models.py:
from django.db import models
class Environment(models.Model):
name = models.CharField(max_length=128, unique=True)
def __str__(self):
return self.name
views.py:
def environment(request, environment_name_url):
environment_name = environment_name_url.replace('_', ' ')
context_dict = {'environment_name': environment_name}
try:
environment = Environment.objects.get(name=environment_name)
pages = Page.objects.filter(environment=environment)
context_dict['pages'] = pages
context_dict['environment'] = environment
except Environment.DoesNotExist:
pass
return render(request, 'dashboard/environment.html', context_dict)
Error:
Using the URLconf defined in dashboard_project.urls, Django tried these URL patterns, in this order:
1. ^admin/
2. ^dashboard/ ^$ [name='index']
3. ^dashboard/ ^environment/(?P<environment_name_url>\w+)/$ [name='environment']
4. media/(?P<path>.*)
The current URL, dashboard/environment/test_1, didn't match any of these.
You have to extend your regular expressions. The problem is not that the slash is not appended, the problem is that none of the urls matches (with or without the slash).
Simple solution, to include the dot you should update your regular expression to also allow a dot:
url(r'^environment/(?P<environment_name_url>[\w\.]-)/$', views.environment, name='environment'),)
Your could improve it further to also allow a dash:
url(r'^environment/(?P<environment_name_url>[\w\.-]+)/$', views.environment, name='environment'),)
The latter would even allow /test-1.1_10/
I currently cannot log into my admin in Django, I get a 404 page.
Page not found (404)
Request Method: GET
Request URL: http://127.0.0.1:8000/admin
No Blog entry found matching the query
UPDATE #3
Last Updated: Dec 17, 10 AM
Status: Still unresolved, could use some help
I've updated the error message at the top of this post, and yes, the error message is short.
I've included the url.py for the actual project, in addition to the app called blog.
Fixed the migrations being out of sync
There is no longer an error in the Terminal
The problem might lie somewhere in models, views or urls.py
THE SUSPECTS
This code snippet relates to "startproject takehome"
urls.py
from django.conf.urls import patterns, include, url
from django.contrib import admin
urlpatterns = patterns(
'',
url(r'^admin/', include(admin.site.urls)),
url(r'^markdown/', include("django_markdown.urls")),
url(r'^', include('blog.urls')),
)
settings.py
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'blog',
'django_markdown',
)
These three code snippets relate to the app called "Blog"
Urls.py
from django.conf.urls import patterns, url
from . import views
urlpatterns = patterns(
'',
url(r'^$', views.BlogIndex.as_view(), name="list"),
url(r'^(?P<slug>\S+)$', views.BlogDetail.as_view(), name="detailed"),
)
Models.py
from django.db import models
from django.core.urlresolvers import reverse
# Create your models here.
class FullArticleQuerySet(models.QuerySet):
def published(self):
return self.filter(publish=True)
class FullArticle(models.Model):
title = models.CharField(max_length=150)
author = models.CharField(max_length=150)
slug = models.SlugField(max_length=200, unique=True)
pubDate = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
category = models.CharField(max_length=150)
heroImage = models.CharField(max_length=250, blank=True)
relatedImage = models.CharField(max_length=250, blank=True)
body = models.TextField()
publish = models.BooleanField(default=True)
gameRank = models.CharField(max_length=150, blank=True, null=True)
objects = FullArticleQuerySet.as_manager()
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("FullArticle_detailed", kwargs={"slug": self.slug})
# def random(self):
# return self.get_queryset().order_by('?').values('title','author','heroImage','body').first()
class Meta:
verbose_name = "Blog entry"
verbose_name_plural = "Blog Entries"
ordering = ["-pubDate"]
views.py
from django.views import generic
from . import models
# Create your views here.
class BlogIndex(generic.ListView):
queryset = models.FullArticle.objects.published()
template_name = "list.html"
# paginate_by = 2
class BlogDetail(generic.DetailView):
model = models.FullArticle
template_name = "detailed.html"
# random = models.FullArticle.objects.order_by('?').values('title','author','heroImage','body').first()
There is definitely a problem with your schema as a result of migrations. There are a few things you can try.
Edit: Since I don't see the field order in your current models.py, it is probably best to go with option 1.
Option 1: Flush and resync your database. (Or even better, delete your database and resync - easy if using SQLite3). Find db.sqlite3 in your blog/ directory and delete it. Warning: You will lose all data if you do this. Once that is done, run ./manage.py syncdb and don't worry about migrations (especially if running Django 1.7, which you are).
Option 2: Remove the field causing the error (if possible), run a migration, then add it back and re-run the migration.
Option 3: Find all orders and delete whichever two are not unique, then re-run the migration.
Update: ok the migration problem has been moved out of the way.
Update 2: ok so it isn´t lacking the admin url pattern
What is the case with your importing the blog urls in your main urls.py? You match everything that falls through the patterns r'^admin/' and r'^markdown/' as a blog entry.
Now your request is "/admin", and because of the lacking of a "/" (slash) at the end, in stead of being matched against the first pattern, it is matched against the last one: r'^(?P\S+)$'. So now it looks for blog entry with a slug called "admin", and fails to find one, and hence returns 404 with a very clear discription. (next time don´t hesitate to include that in the question :)
I expect also that requesting "/admin/" will result in an admin page, because it would get matched against r'^admin/', because of the trailing /
better practice is to avoid conflicts between main urls and app specific urls by sub-url'ing your blogposts somewhat like this:
url(r'^blog/', include('blog.urls', namespace="blog")),
https://docs.djangoproject.com/en/dev/intro/tutorial03/#namespacing-url-names
before update:
Maybe you tried to make the order field unique after having non-unique values in it. Have you tried removing the whole database and rebuilding it? That would be my first suggestion.
It seems like there are some quirks in sqlite, I never use it basically. I would suggest also to try using something more mature like postgresql or mysql.
I think I done everything correct but I don't know why it doesn't work. When I try to reach a page I get error "Page not found (404)".
So, this all products page works 127.0.0.1:8000/products/ but when I try to visit single product page 127.0.0.1:8000/products/audi I get error that it's not found...
So, maybe you what's wrong here?
Thank you.
Page not found (404)
Request Method: GET
Request URL: http://link/products/audi
Using the URLconf defined in ecommerce.urls, Django tried these URL patterns, in this order:
^static/(?P<path>.*)$
^media/(?P<path>.*)$
^admin/doc/
^admin/
^products/ ^$ [name='products']
^products/ ^$(?P<slug>.*)/$
^contact/ [name='contact_us']
The current URL, products/audi, didn't match any of these.
Main project urls.py:
from django.conf import settings
from django.conf.urls import patterns, include, url
# Uncomment the next two lines to enable the admin:
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
(r'^static/(?P<path>.*)$', 'django.views.static.serve', {
'document_root': settings.STATIC_ROOT
}),
(r'^media/(?P<path>.*)$', 'django.views.static.serve', {
'document_root': settings.MEDIA_ROOT
}),
url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
url(r'^admin/', include(admin.site.urls)),
url(r'^products/', include('products.urls')),
url(r'^contact/', 'contact.views.contact_us', name='contact_us'),
)
Products app urls.py:
from django.conf import settings
from django.conf.urls import patterns, include, url
urlpatterns = patterns('products.views',
url(r'^$', 'all_products', name='products'),
url(r'^$(?P<slug>.*)/$', 'single_product'),
)
views.py
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render_to_response, RequestContext, get_object_or_404
from .models import Product
def all_products(request):
products = Product.objects.filter(active=True)
return render_to_response('products/all.html', locals(), context_instance=RequestContext(request))
def single_product(request, slug):
product = get_object_or_404(Product, slug=slug)
return render_to_response('products/single.html', locals(), context_instance=RequestContext(request))
models.py
from django.db import models
# Create your models here.
class Product(models.Model):
title = models.CharField(max_length=220)
description = models.CharField(max_length=3000, null=True, blank=True)
price = models.DecimalField(max_digits=1000, decimal_places=2, null=True, blank=True)
slug = models.SlugField()
active = models.BooleanField(default=True)
timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)
updated = models.DateTimeField(auto_now=True, auto_now_add=False)
def __unicode__(self):
return self.title
class Meta:
ordering = ['title',]
class ProductImage(models.Model):
product = models.ForeignKey(Product)
description = models.CharField(max_length=3000, null=True, blank=True)
image = models.ImageField(upload_to='product/images/')
timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)
updated = models.DateTimeField(auto_now=True, auto_now_add=False)
def __unicode__(self):
return self.image
Your URL pattern has an extra $ at the beginning, so it can never match anything:
url(r'^$(?P<slug>.*)/$', 'single_product')
This should be:
url(r'^(?P<slug>.*)/$', 'single_product')
This still requires a trailing slash, which is the normal pattern. With that corrected, your URL should be /products/audi/. You don't show the context in which that URL is created, but this is one example of why it's a good idea to use Django's url reversal to build URLs if at all possible. That would look something like this, in Python code (for instance, possibly in a get_absolute_url method on the model:
reverse('single_product', kwargs={'slug': someproduct.slug})
Or like this, in a template:
Django 1.5:
{% url 'single_product' someproduct.slug %}
Django 1.4 and earlier:
{% url single_product someproduct.slug %}
You have a typo:
url(r'^$(?P<slug>.*)/$', 'single_product'),
Note this $ just after ^, in regexp it states for a string end. Replace with
url(r'^(?P<slug>.*)/$', 'single_product'),