I would like to filter the Post objects also with the slug, how should one go about this?
The model looks as follows:
class Post(models.Model):
slug = models.SlugField()
title = models.CharField(max_length=100)
post_json = models.CharField(max_length=100000, blank=True, null=True)
author = models.ForeignKey(User, on_delete=models.CASCADE)
and the view looks like this.
def load_post_json(request):
obj = Post.objects.filter(author_id=request.user.id)
data = list(obj.values())
return JsonResponse({'posts': data})
In the url you can capture the slug:
# app/urls.py
from django.urls import path
from app.views import load_post_json
urlpatterns = [
# …
path('post/<slug:slug>/', load_post_json, name='post_json'),
# …
]
Then in your view, you can filter in the slug:
# app/views.py
from django.contrib.auth.decorators import login_required
#login_required
def load_post_json(request, slug):
obj = Post.objects.filter(author_id=request.user.id, slug=slug)
data = list(obj.values())
return JsonResponse({'posts': data})
That being said, it might be better to use the Django REST framework to define an API. This has tooling for serializers, etc. and thus makes it more convenient to define sets of views to obtain a list of items, create new ones, etc.
Note: You can limit views to a view to authenticated users with the
#login_required decorator [Django-doc].
You mean you want to filter by slug too?
If you submit it as a query parameter, simply write:
def load_post_json(request):
slug_name= request.data.get('slug_name')
obj = Post.objects.filter(author_id=request.user.id, slug=slug_name)
data = list(obj.values())
return JsonResponse({'posts': data})
If you want to extract it from the URL,capture it on urlpatterns in urls.py file:
urlpatterns = [
# …
path('post/<slug_name:slug_name>/', load_post_json),
# …
]
then, get it as a function parameter in your load_post_json function:
def load_post_json(request, slug_name):
...
Here another alternative way,
# app/urls.py
from django.urls import path
from app.views import load_post_json
urlpatterns = [
# …
path('post/', load_post_json, name='post_json'),
# …
]
and the views.py
# app/views.py
from django.contrib.auth.decorators import login_required
#login_required
def load_post_json(request):
slug = request.GET.get('slug', None)
obj = Post.objects.filter(author_id=request.user.id, slug=slug)
data = list(obj.values())
return JsonResponse({'posts': data})
and the url endpoint,
/post/?slug=<your slug here>
Related
i need to add action decorator from rest_framework.decorators to view on generics
views.py
class AnswerDetailView(generics.RetrieveUpdateDestroyAPIView):
permission_classes = [IsOwnerOrAdminOnly]
queryset = Answer.objects.all()
serializer_class = AnswerSerializer
#action(['POST'], detail=True)
def like(self, request, pk=None):
answer = self.get_object()
author = request.user
serializer = AnswerReviewSerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
try:
answer_review = AnswerReview.objects.get(answer=answer, author=author)
answer_review.delete()
message = 'disliked'
except AnswerReview.DoesNotExist:
AnswerReview.objects.create(answer=answer, author=author)
message = 'liked'
return Response(message, status=200)
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('answers/', views.AnswerCreateView.as_view()),
path('answers/<int:pk>/', views.AnswerDetailView.as_view()),
path('comments/', views.CommentCreateView.as_view()),
path('comments/<int:pk>/', views.CommentDetailView.as_view()),
path('answers/<int:pk>/like/', views.AnswerDetailView.like),
]
i've tried on ModelViewSet and it works but how can i do it on generics?
also i need my urls for like button look like this:
urlpatterns = [
path('answers/<int:pk>/like/', <view>),
]
#action doesn't work with GenericAPIView. it's only working with ViewSet. I will suggest you should use GenericViewSet.
Models.py
from django.db import models
# Create your models here.
class reviewData(models.Model):
building_name = models.CharField(max_length=50)
review_content = models.TextField()
star_num = models.FloatField()
class buildingData(models.Model):
building_name = models.CharField(max_length=50)
building_loc = models.CharField(max_length=50)
building_call = models.CharField(max_length=20)
views.py
# Create your views here.
from django.shortcuts import render
from rest_framework.response import Response
from .models import reviewData
from .models import buildingData
from rest_framework.views import APIView
from .serializers import ReviewSerializer
class BuildingInfoAPI(APIView):
def get(request):
queryset = buildingData.objects.all()
serializer = ReviewSerializer(queryset, many=True)
return Response(serializer.data)
class ReviewListAPI(APIView):
def get(request):
queryset = reviewData.objects.all()
serializer = ReviewSerializer(queryset, many=True)
return Response(serializer.data)
urls.py
from django.contrib import admin
from django.urls import path
from crawling_data.views import ReviewListAPI
from crawling_data.views import BuildingInfoAPI
urlpatterns = [
path('admin/', admin.site.urls),
path('api/buildingdata/', BuildingInfoAPI.as_view()),
#path('api/buildingdata/(I want to put building name here)', ReviewListAPI.as_view())
]
I am making review api.
I want to use building name as url path to bring reviews for specific buildings
For example, there are a, b, c reviews
a, b reviews are for aaabuilding
c reviews are for xxxbuilding
api/buildingdata/aaabuilding (only shows aaabuilding review)
{
building_name = aaabuilding
review_content = a
star_num = 5
building_name = aaabuilding
review_content = b
star_num = 3
}
api/buildingdata/xxxbuilding (only shows xxxbuilding review)
{
building_name = xxxbuilding
review_content = c
star_num = 4
}
I've searched some dynamic url posts, but they were not that i want.
Is there any way to bring building name into url from db?
In urls.py
path('api/buildingdata/<str:building>/', BuildingInfoAPI.as_view()),
And in views.py
class BuildingInfoAPI(APIView):
def get(request, building):
queryset = buildingData.objects.filter(building_name__contains=building)
serializer = ReviewSerializer(queryset, many=True)
return Response(serializer.data)
Hope this will solve the issue
I suggets you take a look at the django documentation, this is pretty well explained there, here is a useful link
In your urls.py, you should put:
from django.contrib import admin
from django.urls import path
from crawling_data.views import ReviewListAPI
from crawling_data.views import BuildingInfoAPI
urlpatterns = [
path('admin/', admin.site.urls),
path('api/buildingdata/', BuildingInfoAPI.as_view()),
# added <str:building> to url
path('api/buildingdata/<str:building>', ReviewListAPI.as_view())
]
And in your views.py:
# Create your views here.
from django.shortcuts import render
from rest_framework.response import Response
from .models import reviewData
from .models import buildingData
from rest_framework.views import APIView
from .serializers import ReviewSerializer
class BuildingInfoAPI(APIView):
def get(request):
queryset = buildingData.objects.all()
serializer = ReviewSerializer(queryset, many=True)
return Response(serializer.data)
class ReviewListAPI(APIView):
# added another argument, retrieved from url
def get(request, building):
# changed .all() to .filter()
queryset = reviewData.objects.filter(building_name = building)
serializer = ReviewSerializer(queryset, many=True)
return Response(serializer.data)
I'm a beginner in python-django coding. Currently I am trying to complete the challenge on https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Authentication but I am facing
LoanedBooksByAllUserListView is missing the permission_required attribute. Define LoanedBooksByAllUserListView.permission_required, or override LoanedBooksByAllUserListView.get_permission_required().
In urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
path('books/', views.BookListView.as_view(), name='books'),
path('book/<int:pk>', views.BookDetailView.as_view(), name='book-detail'),
path('authors/', views.AuthorListView.as_view(), name='authors'),
path('author/<int:pk>', views.AuthorDetailView.as_view(), name='author-detail'),
path('mybooks/', views.LoanedBooksByUserListView.as_view(), name='my-borrowed'),
path('borrowed/', views.LoanedBooksByAllUserListView.as_view(), name='all-borrowed'),
]
In views.py
from django.shortcuts import render
# Create your views here.
from .models import Book, Author, BookInstance, Genre
def index(request):
"""View function for home page of site."""
# Generate counts of some of the main objects
num_books = Book.objects.all().count()
num_instances = BookInstance.objects.all().count()
# Available books (status = 'a')
num_instances_available = BookInstance.objects.filter(status__exact='a').count()
# The 'all()' is implied by default.
num_authors = Author.objects.count()
# Number of visits to this view, as counted in the session variable.
num_visits = request.session.get('num_visits', 0)
request.session['num_visits'] = num_visits + 1
context = {
'num_books': num_books,
'num_instances': num_instances,
'num_instances_available': num_instances_available,
'num_authors': num_authors,
'num_visits': num_visits,
}
# Render the HTML template index.html with the data in the context variable.
return render(request, 'index.html', context=context)
from django.views import generic
class BookListView(generic.ListView):
model = Book
paginate_by = 5
class BookDetailView(generic.DetailView):
model = Book
class AuthorListView(generic.ListView):
model = Author
paginate_by = 5
class AuthorDetailView(generic.DetailView):
model = Author
from django.contrib.auth.mixins import LoginRequiredMixin
class LoanedBooksByUserListView(LoginRequiredMixin,generic.ListView):
"""Generic class-based view listing books on loan to current user."""
model = BookInstance
template_name ='catalog/bookinstance_list_borrowed_user.html'
paginate_by = 10
def get_queryset(self):
return BookInstance.objects.filter(borrower=self.request.user).filter(status__exact='o').order_by('due_back')
from django.contrib.auth.mixins import PermissionRequiredMixin
class LoanedBooksByAllUserListView(PermissionRequiredMixin,generic.ListView):
model = BookInstance
template_name ='catalog/allbookinstancelistborrowed.html'
paginate_by = 10
def get_queryset(self):
return BookInstance.objects.filter(status__exact='o').order_by('due_back')
I am new in Django and python. Now I am trying to do web API with Django and python. I can get the get request but when I request the post method, this error is shown
"non_field_errors": [
"No data provided"
]
View.py=>
from rest_framework.generics import get_object_or_404
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import Allowance
from .serializers import AllowanceSerializer
# Create your views here.
class AllowanceAPIView(APIView):
def get(self,request,pk=None):
if pk:
allowance=get_object_or_404(Allowance.objects.all(),pk=pk)
serializer = AllowanceSerializer(allowance)
return Response({serializer.data})
allowance=Allowance.objects.all()
serializer = AllowanceSerializer(allowance,many=True)
return Response({"allowance":serializer.data})
def post(self,request):
allowance = request.data.get('allowance')
serializer = AllowanceSerializer(data=allowance)
if serializer.is_valid(raise_exception=True):
allowance_saved=serializer.save()
return Response({"success":"Allowance '{}' created successfully".format(allowance_saved.AllowID)})
def put(self,request,pk):
save_allowance = get_object_or_404(Allowance.objects.all(),pk=pk)
data = request.data.get('allowance')
serializer = AllowanceSerializer(instance=save_allowance,data=data,partial=True)
if serializer.is_valid(raise_exception = True):
allowance_saved=serializer.save()
return Response({"sucess": "Allowance '{}' updated successfully".format(allowance_saved.AllowID)})
def delete(self,request,pk):
#Get object with this pk
allowance = get_object_or_404(Allowance.objects.all(),pk=pk)
allowance.delete()
return Response({"message":"Allowance with id '{}' has been deleted.".format(pk)},status=204)
urls.py inside app =>
from django.conf.urls import url
from .views import AllowanceAPIView
urlpatterns = [
url(r'^$', AllowanceAPIView.as_view(), name='post-listcreate'),
url(r'^(?P<pk>\d+)/$', AllowanceAPIView.as_view(), name='post-listcreate')
]
urls.py inside project =>
from django.conf.urls import url, include
from django.contrib import admin
from rest_framework_jwt.views import obtain_jwt_token
urlpatterns = [
url(r'^admin/', admin.site.urls),
# url(r'^api/auth/login/$', obtain_jwt_token, name='api-login'),
url(r'^api/allowances_mas/', include('tmswebapi.urls')),
]
sample API request=>
{
"AllowID": "Allow1",
"AllowDesc": "Allow1 Description",
"AllowAmt": "11.00",
"AllowType": "MEAL",
"Created_DT": "2019-06-18T18:09:00Z",
"Created_Usr": "Admin",
"LastModified_Usr": "",
"LastModified_DT": "2019-06-18T18:09:00Z"
}
Serializer =>
from rest_framework import serializers
import datetime
from .models import Allowance
class AllowanceSerializer(serializers.ModelSerializer):
class Meta:
model=Allowance
fields = "__all__"
def create(self,validated_data):
return Allowance.objects.create(**validated_data)
def update(self,instance,calidated_data):
instance.AllowDesc = validated_data.get('AllowDesc',instance.AllowDesc)
instance.AllowAmt = validated_data.get('AllowAmt',instance.AllowAmt)
instance.AllowType = validated_data.get('AllowType',instance.AllowType)
instance.LastModified_Usr = "Admin"
instance.LastModified_DT = datetime.datetime.now()
instance.save()
return instance
Is it because of urls or because of data format?
It's returning error from on of if serializer.is_valid(raise_exception = True): lines.
It means data is None somewhere.
Debug your code to make sure data variable has data
def post(self,request):
allowance = request.data
serializer = AllowanceSerializer(data=allowance)
if serializer.is_valid(raise_exception=True):
allowance_saved=serializer.save()
return Response({"success":"Allowance '{}' created successfully".format(allowance_saved.AllowID)})
Now try this
I have a django model that looks like this:
class AcademicProgramsManager(models.Manager):
def get_by_natural_key(self, acad_program_id, program_title, required_credits):
return self.get(acad_program_id = acad_program_id, program_title = program_title, required_credits = required_credits)
class AcademicPrograms(models.Model):
objects = AcademicProgramsManager()
acad_program_id = models.IntegerField(primary_key=True)
acad_program_category = models.ForeignKey(AcademicProgramCategories)
acad_program_type = models.ForeignKey(AcademicProgramTypes)
acad_program_code = models.CharField(max_length=25)
program_title = models.CharField(max_length=64)
required_credits = models.IntegerField()
min_gpa = models.FloatField()
description = models.CharField(max_length=1000)
def natural_key(self):
return (self.acad_program_id, self.program_title, self.required_credits)
class StudentAcademicPrograms(models.Model):
student = models.ForeignKey(Students)
academic_program = models.ForeignKey(AcademicPrograms)
credits_completed = models.IntegerField()
academic_program_gpa = models.FloatField()
primary_program = models.BooleanField()
This is my serializers.py file:
from studentapp.models import AcademicPrograms, AcademicProgramsManager, StudentAcademicPrograms
from rest_framework import serializers
class StudentAcademicProgramsSerializer(serializers.ModelSerializer):
class Meta:
model = StudentAcademicPrograms
fields = ('credits_completed','academic_program_gpa','primary_program')
class AcademicProgramsSerializer(serializers.ModelSerializer):
studentacademicprograms = StudentAcademicProgramsSerializer(many = True)
class Meta:
model = AcademicPrograms
fields = ('acad_program_id','program_title','required_credits','studentacademicprograms')
My api.py file looks like this:
from studentapp.models import AcademicPrograms, AcademicProgramsManager, StudentAcademicPrograms
from studentapp.serializers import StudentAcademicProgramsSerializer, AcademicProgramsSerializer
from django.http import Http404
from rest_framework.views import APIView
from rest_framework.response import Response
class AcademicProgramsList(APIView):
def get(self, request, format=None):
academicprograms = AcademicPrograms.objects.all()
serialized_academicprograms = AcademicProgramsSerializer(academicprograms, many=True)
return Response(serialized_academicprograms.data)
class AcademicProgramsDetail(APIView):
def get_onjects(self, pk):
try:
return AcademicPrograms.object.get(pk=pk)
except AcademicPrograms.DoesNotExist:
raise Http404
def get(self, request, pk, format=None):
academicprogram = self.get_object(pk)
serialized_academicprogram = AcademicProgramsSerializer(academicprogram)
return Response(serialized_academicprogram.data)
and finally my urls:
from django.conf.urls import patterns, include, url
from rest_framework.urlpatterns import format_suffix_patterns
from studentapp import api
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
# Examples:
# url(r'^$', 'texascompletes.views.home', name='home'),
# url(r'^blog/', include('blog.urls')),
#API:
url(r'^api/studentacademicprograms/$', api.AcademicProgramsList.as_view()),
url(r'^api/studentacademicprograms/(?P<pk>[0-9]+)/$', api.AcademicProgramsDetail.as_view()),
url(r'^admin/', include(admin.site.urls)),
)
urlpatterns = format_suffix_patterns(urlpatterns)
I am getting the following error when i give my api/studentacademicprograms
'AcademicPrograms' object has no attribute 'studentacademicprograms'
Where am i going wrong?
Try setting the source to the attribute/method name on the model. For example:
studentacademicprograms = StudentAcademicProgramsSerializer(
many=True,
source='studentacademicprograms_set')
The example given in the Django Rest Framework Serializer relations docs sets a related name on the models which matches the attribute name in the serializer (the default). If the names don't match you need to specify them model's source method/attribute to use.