I'm fairly new to python and I'm trying to build a URL pattern that takes two fields as parameters. This is part of my model:
CATEGORY_CHOICES = (
('M', 'Music'),
('G', 'Games'),
('T', 'TV'),
('F', 'Film'),
('O', 'Misc'),
)
category = models.CharField(max_length = 1, choices = CATEGORY_CHOICES)
slug = models.SlugField(unique=True, max_length=255)
What I want to achieve is to be able to call a such as: thisblog.com/music/this-post where /music is the category and /this-post is the slug.
I had an attempt but I can't figure out how to do it properly:
urlpatterns = patterns('',
url(r'^admin/', include(admin.site.urls)),
url(r'^$', 'blog.views.index'),
url(r'^(?P<category>[\w\-]+)/(?P<slug>[\w\-]+)/$', blog_post, name = 'blog_post'),
)
This gives me a 'NoReverseMatch at /' error.
Any help is greatly appreciated :)
UPDATE:
In my html template I have a link:
<p><a class="btn btn-default" href="{{post.get_absolute_url}}" role="button">Read more »</a></p>
get_absolute_url is defined as:
def get_absolute_url(self):
return reverse ('blog.views.post', args = [self.slug])
You have two errors in your get_absolute_url method. Firstly, you need to use the URL's name attribute since you have defined it. And secondly, you need to provide both parameters: category as well as slug.
So it should be:
return reverse('blog_post', args=[self.category, self.slug])
If you are using class based views then something like this would work:
# views.py
class ViewPost(DetailView):
model = Post # change this to the model
def get_queryset(self):
queryset = super(ViewQuizListByCategory, self).get_queryset()
return queryset.filter(category=self.kwargs['category'])
# urls.py
from .views import ViewPost
...
url(r'^(?P<category>[\w\-]+)/(?P<slug>[\w\-]+)/$',
ViewPost.as_view(),
name='blog_post'),
...
The template will be post_detail.html and would be placed as <project_root>/post/templates/post/post_detail.html
Related
The problem is I can't type http://localhost:8000/1 to see spesific ViedoLibrary in my database. Can anyone help me to find the solution?
urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.index, name='index'),
path('main/', views.main, name='main'),
path('create_view/', views.create_view, name='create_view'),
path('list_view/', views.list_view, name='list_view'),
path('<id>', views.detail_view),
]
views.py
def detail_view(request, id):
context = {}
context['data'] = VideoLibrary.objects.get(shop_id=id)
return render(request, 'app/detail_view.html', context)
models.py
class VideoLibrary(models.Model):
shop_id = models.AutoField(primary_key=True, unique=True)
shop_name = models.CharField(max_length=264)
adress = models.TextField(max_length=264, default='')
Also if I type id=id in views.py the next error pops up : Cannot resolve keyword 'id' into field. Choices are: adress, attendance, equipment, films, genre, income, shop_id, shop_name, staff.
This are all my classes in models.py but there are also adress, shop_id and shop_name that are from specific model
Updated.
You have overriden the id field of your model that is why it won't work with id=id since the latter is actually shop_id. Change it accordingly and it should work.
The id error is telling you that you cannot use id as a field and giving you the list of available model fields you can use for filtering. See this answer for more details. Error: Cannot resolve keyword 'id' into field
Update 2
Your views:
from . models import VideoLibrary
def videoLibrary(request):
context = {}
context['data'] = VideoLibrary.objects.all()
return render(request, 'appname/list_view.html', context)
def detail_view(request, id):
context = {}
context['data'] = VideoLibrary.objects.get(shop_id=id)
return render(request, 'appname/detail_view.html', context)
Your urls.py:
urlpatterns = [
path('admin/', admin.site.urls),
path('videos/', views.videoLibrary, name='list_view'),
path('videos/<int:id>', views.detail_view),
]
Now, if you enter http://127.0.0.1:8000/videos this gives you the list view. And http://127.0.0.1:8000/videos/1 gives you VideoLibrary with id 1.
Urls.py:
app_name = 'main'
urlpatterns = [
path('',include(router.urls)),
path('player_id=<str:player>%season_id=<str:season>',views.MatchesList.as_view())
]
Views.py
class MatchesList(generics.ListAPIView):
serializer_class = MatchesSerializer
permissions = (IsAuthenticated)
def get_queryset(self):
player = self.kwargs['player']
season = self.kwargs['season']
if season is None:
queryset = Matches.objects.filter(player=player).all()
else:
queryset = Matches.objects.filter(player=player,season=season).all()
return queryset
Is there any way to request without the parameter 'season'? Something like that:
app_name = 'main'
urlpatterns = [
path('',include(router.urls)),
path('player_id=<str:player>',views.MatchesList.as_view())
]
Sure. In DRF you can/should use filtering for this.
In urls.py you'll have something like this:
path('matches/<str:player_id>/', views.MatchesList.as_view())
And your URL will look like:
https://yourhost.com/matches/42/?season=spring
For season you'll have to implement a filter (there is a bunch of ways to do it). Filters are optional — if you'll not pass the ?season=something part of the URL, it just will not be applied.
I am trying to get all the post, posted in the same category. So my url looking like this, '..../category/Sports' where sports is a category. But if I enter this url, I got page, not found. I have also a html file called category. I also made makemigrations and migrate a several times
My views.py file:
from .models import Post, Category
..............
def CatView(request, cats):
posts = Post.objects.filter(category=cats)
return render(request,'category.html',{"cats":cats, 'posts':posts})
urls.py file:
from django.urls import path
from .views import *
urlpatterns = [
path('',HomeView.as_view(), name='home'),
path('article/<int:pk>', ArticleDetailView.as_view(), name='article_detail'),
path('add-post/', Addblogview.as_view(), name='add_post'),
path('add-category/', AddCategoryview.as_view(), name='add_category'),
path('article/edit/<int:pk>', UpdatethePost.as_view(), name='add_task'),
path('article/delete/<int:pk>', DeleteThePost.as_view(), name='delete_task'),
path('category/<int:cats>', CatView, name='category'),
]
If I change <str:cats> I ended up with ValueError Field 'id' expected a number but got 'Sports'
My models.py file:
from django.db import models
from django.contrib.auth.models import User
from django.urls import reverse
from datetime import datetime, date
class Category(models.Model):
name = models.CharField(max_length=255, default='uncategorized')
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('article_detail',args=str(self.id))
class Post(models.Model):
title = models.CharField(max_length=255)
title_tag=models.CharField(max_length=255)
author = models.ForeignKey(User,on_delete=models.CASCADE)
body = models.TextField()
post_date = models.DateField(auto_now_add= True)
category = models.ForeignKey(Category,on_delete=models.CASCADE)
def __str__(self):
return self.title + "|" + str(self.author)
def get_absolute_url(self):
return reverse('article_detail',args=str(self.id))
My category.html:
{{cats}}
You haven't set a primary key for Category, so the primary key becomes the numeric ID of the row, and the ForeignKey in Post needs to match that. You really want to set primary_key=True when you create the name field in Category.
Maybe you should just add a slash to the end of your URL in urls.py and try again? :)
Simplified version of forum app in Django. What I want to do is have an url in the form of forum/forum_slug/thread_slug/. I have no idea how to define and pass the custom forum_slug to urlpatterns.
# models.py
class Forum(models.Model):
title = models.CharField(max_length=60)
slug = models.CharField(max_length=60)
# ...
def threads(self):
_threads = Thread.objects.filter(forum=self)
return _threads
class Thread(models.Model):
title = models.CharField(max_length=60)
slug = models.CharField(max_length=60)
forum = models.ForeignKey(Forum)
# ...
def get_absolute_url(self):
return '/%s/%s' % (self.forum.slug, self.slug)
class Post(models.Model):
title = models.CharField('Title', max_length=60)
thread = models.ForeignKey(Thread)
# ...
# ******************************************************
# views.py
# ******************************************************
class ForumDetail(MetadataMixin, DetailView):
model = Forum
context_object_name = 'forum'
template_name = 'forum/forum.html'
name='forum'
# meta...
class ThreadDetail(MetadataMixin, DetailView):
model = Thread
context_object_name = 'thread'
template_name = 'forum/thread.html'
name = 'thread'
# meta...
# ******************************************************
# urls.py
# ******************************************************
urlpatterns = patterns('',
url(r'^$',
'forum.views.index',
name='index'
),
url(r'^(?P<slug>[a-zA-Z0-9-]+)/?$',
ForumDetail.as_view()),
# here it comes
url(r'^(?P<forum_slug>[a-zA-Z0-9-]+/?P<slug>[a-zA-Z0-9-]+)/?$',
ThreadDetail.as_view()),
)
I assume that you want URL pattern for slugs. Below is the example you can try.
# URL example: /forum/this-is-a-forum-1/this-is-a-thread-1/
url(r'^forum/(?P<forum_slug>[\w-]+)/(?P<thread_slug>[\w-]+)$', ThreadDetail.as_view()),
Hope this helps.
#rayy: Thanks. No, this is not what I was looking for -- I simply do not know how to define forum_slug in it. That's what I was asking for. :-) Well, I figured out kinda more verbose solution but, frankly, I do not like it:
# models.py
from django.core.urlresolvers import reverse
class Thread(models.Model):
#... like before
def get_absolute_url(self):
return reverse('thread_url', (), {'forum_slug': self.forum.slug, 'slug': self.slug})
# urls.py
urlpatterns = patterns('',
# ...
url(r'^(?P<forum_slug>[\w-]+)/(?P<slug>[\w-]+)/$', ThreadDetail.as_view(), name='thread_url'),)
# index.html / forum.html (in a loop)
{{thread.title}}
I have a model with some fields and I want to add a LinkColumn to a detail page. I have a working version, but I want to move to django-tables2
The problem is that the link column doesnt show any link, just a "-"
The model
class Events(models.Model):
id = models.IntegerField(primary_key=True)
date = models.DateField(null=True, blank=True)
time = models.TimeField(null=True, blank=True)
The Table. Here I tried with args=[A('id')] and args=[A('pk')]
class EventsTable(tables.Table):
time = tables.TemplateColumn("{{value|time:'H:i'}}", verbose_name='Time UTC')
detail_link = tables.LinkColumn('detail', args=[A('id')], verbose_name='Detail')
class Meta:
model = Events
attrs = {"class": "paleblue"}
fields = ("date", "time", "detail_link")
mi url pattern is
urlpatterns = patterns('',
url(r'^$', views.index, name='index'),
url(r'^(?P<event_id>\d+)/$', views.detail, name='detail'),
)
and the view
def index(request):
table = EventsTable(Events.objects.all(), order_by=('-date', '-time'))
RequestConfig(request, paginate={"per_page": PAGE_LIMIT}).configure(table)
return render(request, "db_interface/events.html", {"table": table})
EDIT:
Changing the detail_link to
detail_link = tables.LinkColumn('detail', args=[A('id')], verbose_name='Detail', empty_values=())
now I got a NoReverseMatch Exception
Reverse for 'detail' with arguments '(5075,)' and keyword arguments '{}' not found
the number 5075 is the id of the first event. I dont know if for any reason is not passing the argument as an int ?
Try:
detail_link = tables.LinkColumn('detail', args=[A('id')], verbose_name='Detail', empty_values=())
According to the docs, render methods are only called if the value for a cell is determined to be not an empty value. Since the Event model does not have a detail_link field, there's no value given to it.