I recently started learning Django. I want to display one news item, but when I open on the link I get an error message:
Cannot resolve keyword 'slug' into field. Choices are: NewsTitles, NewsContent, NewsSlug
Request Method: GET
Request URL: http://127.0.0.1:8000/news/nam-gravida-purus-non/
Django Version: 4.0
Exception Type: FieldError
views.py
from django.views.generic import DetailView
from .models import News
class GetNews(DetailView):
model = News
slug_url_kwarg = 'NewsSlug'
template_name = 'news/single_news.html'
context_object_name = 'single_news'
allow_empty = False
urls.py
from django.urls import path
from .views import GetNews
urlpatterns = [
path('news/<str:NewsSlug>/', GetNews.as_view(), name='news'),
]
models.py
from django.db import models
from django.urls import reverse_lazy
class News(models.Model):
NewsTitles = models.CharField(max_length=120)
NewsContent = models.TextField(max_length=255)
NewsSlug = models.SlugField(max_length=255)
def __str__(self):
return self.NewsTitles
def get_absolute_url(self):
return reverse_lazy('news', kwargs={'NewsSlug': self.NewsSlug})
What am I doing wrong?
First of all do not call your slug "NewSlug" with uppercase but all lower case "newslug" or even better "new_slug", the name itself should be more descriptive as well.
Finally you need to tell your view which field to use, you can define that with the following attribute :
slug_field = "NewSlug"
Note : Attribute of a class should not be camel case but snake case
Related
I really need some help here, please.
I think my code is right but when i call python manage-py runserver an error appears.
• models.py
from django.db import models
from django.urls import reverse
class Product(models.Model):
title = models.CharField(max_length=255)
image = models.URLField(max_length=255)
price = models.DecimalField(max_digits=12, decimal_places=2)
product_id = models.SlugField(max_length=255, unique=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("api:detail", kwargs={"product_id": self.product_id})
views.py
from django.views.generic import ListView, DetailView
from .models import Product
class ProductListView(ListView):
model = Product
class ProductDetailView(DetailView):
model = Product
urls.py
from django.urls import path
from .views import ProductListView, ProductDetailView
app_name = "api"
urlpatterns = [
path('', ProductListView.as_view(), name='list'),
path('<slug:product_id>/', ProductDetailView.as_view(), name='detail'),
]
error log
in get_object raise AttributeError( AttributeError: Generic detail
view ProductDetailView must be called with either an object pk or a
slug in the URLconf.
Since your model has the slug field named differently you would need to set a few class attributes in your view namely slug_url_kwarg and slug_field:
class ProductDetailView(DetailView):
model = Product
slug_url_kwarg = 'product_id'
slug_field = 'product_id'
DetailView has SingleObjectMixin as one of it's ancestors which handles getting the object and has these attributes.
I'm very new to Django and a bit overwhelmed by the documentation. I think my problem is pretty simple but everything i've found just confused me more.
I am building a little news app with a model NewsItem:
from django.db import models
from django.utils import timezone
# Create your models here.
class NewsItem(models.Model):
title = models.CharField(max_length=50)
newsText = models.TextField()
dateEntered = models.DateTimeField('date entered')
datePublished = models.DateTimeField('date published', blank=True, null=True)
user = models.CharField(max_length=30) #temporary field. will be changed to user foreign key
def __str__(self):
return self.title
def publish(self):
if (self.datePublished == None):
self.datePublished = timezone.now()
def published(self):
return self.datePublished != None
two views (technically 3) index and detail
from django.http import HttpResponseRedirect
from django.shortcuts import render, get_object_or_404
from django.urls import reverse
from django.views import generic
from .models import NewsItem
# Create your views here.
class IndexView(generic.ListView):
template_name = 'news/index.html'
context_object_name = 'latestNewsList'
def get_queryset(self):
return NewsItem.objects.order_by('-datePublished')[:5]
#todo
class DetailView(generic.DetailView):
model = NewsItem
template_name = 'news/detail.html'
def publish(request, itemId):
newsItem = get_object_or_404(NewsItem, pk=itemId)
newsItem.publish()
newsItem.save()
return HttpResponseRedirect(reverse('news:detail', args=(newsItem.id,)))
and an urlconf like this
from django.urls import path
from . import views
urlpatterns = [
path('', views.IndexView.as_view(), name='index'),
path('<int:pk>/', views.DetailView.as_view(), name='detail'),
path('<int:itemId>/publish', views.publish, name='publish'),
]
In the detail view i have a link Publish which just triggers the function views.publish. This view is supposed to redirect back to the detail view.
What i'm trying to do now is to display a little message (like article successfully published) in detail view when it was redirected by the publish view. But i have no idea what would be a good aproach
I could just render the details template in the publish view, but then it would still say news/publish in the URL instead of news/detail
Thanks in advance for your help
Have a look at the messages framework. You could add a success message before redirecting, which will be displayed on the next page.
from django.shortcuts import redirect
from django.contrib import messages
def publish(request, itemId):
newsItem = get_object_or_404(NewsItem, pk=itemId)
newsItem.publish()
newsItem.save()
messages.success(request, "The post has been published")
return redirect('news:detail', newsItem.id)
Note that I've simplified the return statement to use redirect(...) instead of HttpResponseRedirect(reverse(...)).
I'm creating a simple blog application and I am trying to convert django rest api. But, I got this error
TypeError at /user/api/ hasattr(): attribute name must be string
Exception Type: TypeError at /user/api/
Exception Value: hasattr(): attribute name must be string
this is my models.py file
from django.conf import settings
from django.db import models
from django.urls import reverse
class BlogPost(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE)
blog_title=models.CharField(max_length=200)
blog_description=models.TextField()
blog_pub=models.DateTimeField(auto_now_add=True)
blog_update=models.DateTimeField(auto_now=True)
def __str__(self):
return self.blog_title
def get_absolute_url(self):
return reverse('blog:blog_post', kwargs={'pk': self.pk})
this is my serializers.py file
from rest_framework import serializers
from blog.models import BlogPost
class BlogPostSerializer(serializers.ModelSerializer):
class Meta:
fields=(
'author',
'blog_title',
'blog_description',
),
model=BlogPost
This is views.py file
from blog.models import BlogPost
from .serializers import BlogPostSerializer
from rest_framework import generics
from . import serializers
from . import serializers
class BlogPostListAPI(generics.ListCreateAPIView):
queryset=BlogPost.objects.all()
serializer_class=BlogPostSerializer
class BlogPostListAPIDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = BlogPost.objects.all()
serializer_class = serializers.BlogPostSerializer
this is urls.py file
from django.urls import path,include
from .views import SignUpForm, UserProfiles
from .api.views import *
urlpatterns = [
path('signup/', SignUpForm.as_view(), name='signup'),
path('profile/', UserProfiles.as_view(), name='profile'),
path('api/', BlogPostListAPI.as_view(), name='asad'),
path('api/<int:pk>', BlogPostListAPIDetail.as_view()),
]
this is screenshot
As #MaNKuR pointed out in a comment to the question, you have an additional comma in your serializer definition at the end of Meta.fields:
class BlogPostSerializer(serializers.ModelSerializer):
class Meta:
fields=(
'author',
'blog_title',
'blog_description',
),
Because of this, Meta.fields is now a "tuple of tuple of strings" instead of just a "tuple of strings".
When iterating over fields, instead of the expected three string elements
1. 'author'
2. 'blog_title'
3. 'blog_description'
you get only one element that is not a string
1. ('author', 'blog_title', 'blog_description')
Hence, the internal code of the Serializer complains that it did not get a string like it is supposed to get.
I have a very strange error when using Django Rest Framework. When ever I use the RetrieveAPIView and the data is found I get a error, when data is not found I get the normal window showing the JSON of
{
"detail": "Not found."
}
urls.py
from django.conf.urls import url, include
from django.contrib import admin
from items.views import ItemRetrieveView
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^api/(?P<pk>\d+)/$', ItemRetrieveView.as_view()),
]
seriliazers.py
from rest_framework import serializers
from .models import Item
class ItemSerializer(serializers.ModelSerializer):
class Meta:
model = Item
fields = ('pk','name','desc','created')
view.py- When I change RetrieveAPIViews to RetrieveUpdateDestroyAPIView I always get 'str' object is not callable even when data does not exist.
from django.shortcuts import render
from rest_framework import generics
from .models import Item
from .serializers import ItemSerializer
class ItemRetrieveView(generics.RetrieveAPIView):
lookup_field = 'pk'
queryset = Item.objects.all()
serializer_class = 'ItemSerializer'
model.py
from django.db import models
class Item(models.Model):
name = models.CharField(max_length = 30)
created = models.DateField(auto_now_add = True)
desc = models.CharField(max_length = 30)
def __str__(self):
return '%s' % (self.name)
serializer_class = 'ItemSerializer'
replace 'ItemSerializer' with ItemSerializer, class is expected other than string
serializer_class - The serializer class that should be used for validating and deserializing input, and for serializing output. Typically, you must either set this attribute, or override the get_serializer_class() method.
get_serializer_class(self)
Returns the class that should be used for the serializer. Defaults to returning the serializer_class attribute.
You can either returns class ItemSerializer or override get_serializer_class(self) like:
def get_serializer_class(self):
return ItemSerializer
You are assigning string value to serializer_class. In your code change
serializer_class = 'ItemSerializer'
to
serializer_class = ItemSerializer
I'm a amature django web developer. I have a problam with Django. this error is "cats() got an unexpected keyword argument 'pk'".
please see my codes and help me.
Request Method: GET
Request URL: http://127.0.0.1:8000/1
Django Version: 1.6.5
Exception Type: TypeError
Exception Value:
cats() got an unexpected keyword argument 'pk'
Exception Location: /usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py in get_response, line 112
Python Executable: /usr/bin/python
Python Version: 2.7.6
models.py
from django.db import models
from taggit.managers import TaggableManager
class Category(models.Model):
title = models.CharField(max_length=40)
def __unicode__(self):
return self.title
class Post (models.Model):
title = models.CharField(max_length=150)
body = models.TextField()
date = models.DateTimeField()
tags = TaggableManager ()
cats = models.ManyToManyField(Category)
def __unicode__ (self):
return self.title
urls.py
from django.conf.urls import include, url, patterns
from django.views.generic import ListView, DetailView
from blog.models import Post, Category
urlpatterns = patterns('blog.views',
url(r'^$',ListView.as_view(
queryset = Post.objects.all().order_by("-date")[:2],
template_name="index.html")),
url(r'^(?P<pk>\d+)$', 'cats', name='cats'),
)
views.py
from blog.models import Post,Category
from django.shortcuts import render_to_response
from django.template import RequestContext
def cats(request):
queryset = Post.objects.all().order_by("-date")
navitem = Category.objects.all().order_by("title")
return render_to_response('post.html',{'queryset':queryset,'navitem':navitem},context_instance=RequestContext(request))
The problem is in this line in urls.py:
url(r'^(?P<pk>\d+)$', 'cats', name='cats')
You are sending to the view an argument that it doesn't need.
You can include the pk argument in the view parameters, like this:
def cats(request, pk):
or this:
def cats(request, pk=None):
Or, even better, you can use a different pattern in your URL, without capturing it (because you are not using that pk value at all in your view, you don't need to create a variable for it), like this:
url(r'^(\d+)$', 'cats', name='cats')