I am working on a photography website and i have created a rest api for blog but i am facing trouble how to display the api on template.
My project structure
enter image description here
This is my view.py of Blog
from rest_framework.response import Response
from rest_framework import permissions
from rest_framework.views import APIView
from rest_framework.generics import ListAPIView, RetrieveAPIView
from blog.models import BlogPost
from blog.serializers import BlogPostSerializer
from rest_framework.renderers import TemplateHTMLRenderer
class BlogPostListView(ListAPIView):
queryset = BlogPost.objects.order_by('-date_created')
serializer_class = BlogPostSerializer
lookup_field = 'slug'
permission_classes = (permissions.AllowAny, )
class BlogPostDetailView(RetrieveAPIView):
queryset = BlogPost.objects.order_by('-date_created')
serializer_class = BlogPostSerializer
lookup_field = 'slug'
permission_classes = (permissions.AllowAny, )
class BlogPostFeaturedView(ListAPIView):
queryset = BlogPost.objects.all().filter(featured=True)
serializer_class = BlogPostSerializer
lookup_field = 'slug'
permission_classes = (permissions.AllowAny, )
class BlogPostCategoryView(APIView):
serializer_class = BlogPostSerializer
permission_classes = (permissions.AllowAny, )
def post(self, request, format=None):
data = self.request.data
category = data['category']
queryset = BlogPost.objects.order_by('-date_created').filter(category__iexact=category)
serializer = BlogPostSerializer(queryset, many=True)
return Response(serializer.data)
This is urls.py of Blog
from django.urls import path
from .views import BlogPostListView, BlogPostDetailView, BlogPostFeaturedView, BlogPostCategoryView
urlpatterns = [
path('', BlogPostListView.as_view(), name='bl'),
path('featured', BlogPostFeaturedView.as_view()),
path('category', BlogPostCategoryView.as_view()),
path('<slug>', BlogPostDetailView.as_view()),
]
This urls.py of application
from django.contrib import admin
from django.urls import path, include
from django.views.generic import TemplateView
from portfolio import urls, views
from blog import urls
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.index, name = 'index'),
path('portfolio/', include('portfolio.urls')),
path('gallery/', views.gallery, name = 'gallery'),
path('shop/', views.shop, name = 'shop'),
path('photo/<str:pk>', views.viewPhoto, name = 'photo'),
path('add/', views.addPhoto, name = 'add'),
path('api-auth/', include('rest_framework.urls')),
path('summernote/', include('django_summernote.urls')),
path('blog/', include('blog.urls')),
]
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Rest api for Blog is working, how do use the rest api to display on blog.html??
enter image description here
Related
I need to get just one product object in my VeiwSet based on a given slug, I looked into the docs, but I can't find any solution to this problem. I need to get the slug from the url path aswell, but I don't know how to do it too. Obviously the code below doesn't work.
product/serializers.py
from rest_framework import serializers
from .models import Product
class ProductSerializer(serializers.ModelSerializer):
image = serializers.ImageField(required=True)
class Meta:
model = Product
fields = ("name", "description", "slug", "id", "price", "stock", "image", "category")
product/views.py
from django.http.response import JsonResponse
from rest_framework import serializers, viewsets
from rest_framework.response import Response
from django.http import JsonResponse
from .serializers import ProductSerializer
from .models import Product
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all().order_by('name')
serializer_class = ProductSerializer
class ProductDetailViewSet(viewsets.ViewSet, slug):
queryset = Product.objects.filter(slug=slug)
serializer_class = ProductSerializer
product/urls.py
from rest_framework import routers, urlpatterns
from django.urls import path, include
from .views import ProductViewSet, ProductDetailiewSet
router = routers.DefaultRouter()
router.register(r'', ProductViewSet)
urlpatterns = [
path('<str:slug>/',),
path('', include(router.urls))
]
ViewSets allows you to combine ListView and DetailView into one view.
So you don't need two different views to handle the both actions.
Now if you want to use slug in the url instead of the id by default, you just have to specify lookup_field in the serializer and the view like this :
serializers.py
class ProductSerializer(serializers.ModelSerializer):
image = serializers.ImageField(required=True)
class Meta:
model = Product
fields = ("name", "description", "slug", "id", "price", "stock", "image", "category")
lookup_field = 'slug'
extra_kwargs = {
'url': {'lookup_field': 'slug'}
}
views.py
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all().order_by('name')
serializer_class = ProductSerializer
lookup_field = 'slug'
urls.py
router = routers.DefaultRouter()
router.register(r'', ProductViewSet)
urlpatterns = [
url(r'', include(router.urls)),
]
Now you can query http://localhost:8000/ for products list and http://localhost:8000/product_slug for product detail with product_slug as slug.
More about Django ViewSets and Routers
In my app I want a user to upload an image and the image's file name will become same as the title of the form.
For example,
user uploads image xyz.jpg, while `title = newfile. After that the image will now be newfile.jpg.
This is my code below:
#forms
class PostForm(forms.modelForm):
class Meta:
model = Post
fields = ['title', 'cover']
#urls
from django.urls import path
from .views import HomePageView, CreatePostView
urlpatterns = [
path('', HomePageView.as_view(), name='home'),
path('post/', CreatePostView.as_view(), name='add_post')
]
#views
from django.shortcuts import render
from django.views.generic import ListView, CreateView
from django.urls import reverse_lazy
from .forms import PostForm
from .models import Post
class HomePageView(ListView):
model = Post
template_name = 'home.html'
class CreatePostView(CreateView): # new
model = Post
form_class = PostForm
template_name = 'post.html'
success_url = reverse_lazy('home')
views.py
from django.shortcuts import render
from rest_framework import viewsets
from django.http import HttpResponse
from .serializers import TodoSerializer
from .serializers import UserSerializer
from .models import Todo
from .models import User
class TodoView(viewsets.ModelViewSet):
serializer_class = TodoSerializer
queryset = Todo.objects.all()
def get_object(request):
return "Added";
class UserView(viewsets.ModelViewSet):
serializer_class = UserSerializer
queryset = User.objects.all()
def get_object(request):
print("request", request)
return "Registered";
class LoginView(viewsets.ModelViewSet):
#serializer_class = UserSerializer
#queryset = User.objects.all()
#print("queryset = ",queryset[len(queryset)-1].email_id)
#print("serializer_class = ",serializer_class)
def get_object(self,request):
return HttpResponse("request")
# Create your views here.
urls.py
from django.contrib import admin
from django.urls import path, include
from rest_framework import routers
from todo import views
router = routers.DefaultRouter()
router.register(r'users', views.UserView)
router.register(r'todos', views.TodoView)
router.register(r'login', views.LoginView)
print("In url file")
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include(router.urls)),
]
This is my views.py file and urls.py file.
I have a model created for user, with fields- email_id and password
CRUD operations are implemented automatically, so how do I validate data passed from the login form in frontend
Please tell me what's wrong in the code. I am not able to do the login part.
I am using django 2.2.2 . I am trying to include path('api/', include('music.urls')),into my root url but I get an exception thrown from resolvers.py file.
Here is my music/urls.py
urls.py
from django.urls import path
from . import views
app_name = 'music'
urlpatterns = [
path('songs/', ListSongsView.as_view(), name = 'songs-all'),
]
here is my root url file
urls.py
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('music.urls')),
]
views.py
from django.shortcuts import render
from rest_framework import generics
from .models import Songs
from serializers import SongSerializer
# Create your views here.
class ListSongsView(generics.ListApiView):
queryset = Songs.objects.all()
serializer_class = SongsSerializer
models.py
from django.db import models
# Create your models here.
class Songs(models.Model):
title = models.CharField(max_length=255, null = False)
artist = models.CharField(max_length=50, null= False)
def __str__(self):
return "{} - {}".format(self.title, self.artist)
and my stacktrace
File "/home/brianonchari/Documents/django/drf/myapi/lib/python3.5/site-
packages/django/urls/resolvers.py", line 588, in url_patterns
raise ImproperlyConfigured(msg.format(name=self.urlconf_name))
django.core.exceptions.ImproperlyConfigured: The included URLconf 'rest.urls' does not
appear to have any patterns in it. If you see valid patterns in the file then the issue is
probably caused by a circular import.
music/urls.py
from django.urls import path
from .views import ListSongsView
app_name = 'music'
urlpatterns = [
path('songs/', ListSongsView.as_view(), name='songs-all'),
]
root urls.py:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('music.urls')),
]
music/views.py:
from django.shortcuts import render
from rest_framework import generics
from .models import Songs
from .serializers import SongSerializer
# Create your views here.
class ListSongsView(generics.ListAPIView):
queryset = Songs.objects.all()
serializer_class = SongSerializer
music/models.py:
from django.db import models
# Create your models here.
class Songs(models.Model):
title = models.CharField(max_length=255, null=False)
artist = models.CharField(max_length=50, null=False)
def __str__(self):
return "{} - {}".format(self.title, self.artist)
music/serializers.py:
from rest_framework import serializers
from .models import Songs
class SongSerializer(serializers.ModelSerializer):
class Meta:
model = Songs
fields = ('title', 'artist')
run your migration for Songs model:
python manage.py makemigrations
python manage.py migrate
How do you use Django Rest Framework to create an API when the data model has a composite key consisting of two fields? Background: I am trying to make a REST api for a data model (sample data row below- first two entries make the composite key). I am able call upon my data with date field but am getting errors when I try to use the second string field to return a single record.
'2015-05-06','INTC','31.93','32.79','32.50','32.22','31737537'
I am trying to make the api url structure like so:
localhost/api/v1/yyyy-mm-dd/'char'
localhost/api/v1/2015-05-07/AAPL
serializers.py
from rest_framework import serializers
from .models import Stocksusa, Optionsusa
from rest_framework.reverse import reverse
class StocksUsaSerializer(serializers.HyperlinkedModelSerializer):
url = serializers.SerializerMethodField('get_stock_usa_url')
def get_stock_usa_url(self, obj):
values = [obj.Trade_Date, obj.Ticker]
composite_key_url = "http://0.0.0.0:9978/api/v1/stocksusa/{}/{}".format(*values)
return composite_key_url
class Meta:
model = Stocksusa
fields = ('Trade_Date', 'Ticker', 'PxMin', 'PxMax', 'PxOpen', 'PxClose', 'Volume', 'url')
views.py
from django.shortcuts import render
from rest_framework import authentication, permissions, viewsets, filters
from .models import Stocksusa
from .serializers import StocksUsaSerializer
from django.contrib.auth import get_user_model
User = get_user_model()
class DefaultsMixin(object):
authentication_classes = (
authentication.BasicAuthentication,
authentication.TokenAuthentication,
)
permission_classes = (
permissions.IsAuthenticated,
)
paginate_by = 25
paginate_by_param = 'page_size'
max_paginate_by = 100
filter_backends = (
filters.DjangoFilterBackend,
filters.SearchFilter,
filters.OrderingFilter,
)
class StocksUsaViewSet(DefaultsMixin, viewsets.ReadOnlyModelViewSet):
queryset = Stocksusa.objects.all()
serializer_class = StocksUsaSerializer
app/urls.py
from rest_framework.routers import DefaultRouter
from . import views
router = DefaultRouter(trailing_slash=False)
router = DefaultRouter()
router.register(r'stocksusa', views.StocksUsaViewSet)
urls.py
from django.conf.urls import patterns, include, url
from django.contrib import admin
from django.conf.urls import include, url
from rest_framework.authtoken.views import obtain_auth_token
from FinDataUsa.urls import router
from FinDataUsa.views import StocksUsaViewSet as stockview
urlpatterns = patterns('',
url(r'^api/token/', obtain_auth_token, name='api-token'),
url(r'^api/v1/', include(router.urls)),
url(r'^api/v2/', include(router.urls)),
url(r'^admin/', include(admin.site.urls)),
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
url(r'^docs/', include('rest_framework_swagger.urls')),
)
The problem lies into the fact that the DefaultRouter uses the id lookup_field of your model for getting the object you want: For example this works:
GET localhost/api/v1/stocksusa/1
In order to provide extra parameters you need to hand-craft the urls like this:
url(r'(?P<year>\d{4})-(?P<month>\d{1,2})-(?P<day>\d{1,2})/(?P<code>\w+)$',
StocksUsaViewSet.as_view(),
name='stocks_detail'
),
The year month day code parameters are passed into your view with the kwargs dictionary:
self.kwargs['year']
self.kwargs['month']
self.kwargs['day']
self.kwargs['code']
On your get_object method you need to do something like that:
def get_object(self, queryset=None):
try:
date= datetime.date(
year=int(self.kwargs['year']),
month=int(self.kwargs['month']),
day=int(self.kwargs['day']),
)
except ValueError:
raise Http404
stock= get_object_or_404(Stocksusa, Ticker=self.kwargs['code'], Trade_Date=date)
return stock
Then you will have access to your object: