django-restframework serialize display - python

when user goes to http://127.0.0.1:8000/movies/, I don't want to show the Showtimes
but when user goes to http://127.0.0.1:8000/movies/1/ , show it .
I want to ask if there is method to do this??
The method I use now is write 2 ModelSerializer to display it.
Please guide me . Thank you!!
This is my original code (not the 2 ModelSerializer method)
urls.py:
urlpatterns = patterns(
'',
url(r'^movies/$', MovieList.as_view(), name='movie-list'),
url(r'^movies/(?P<pk>[0-9]+)/$', MovieDetail.as_view(), name='movie-detail'),
This is my views.py :
class MovieMixin(object):
queryset = Movie.objects.all()
serializer_class = MovieSerializer
class MovieFilter(django_filters.FilterSet):
class Meta:
model = Movie
fields = ['which_run',]
class MovieList(MovieMixin, generics.ListAPIView):
filter_class = MovieFilter
class MovieDetail(MovieMixin, generics.RetrieveAPIView):
pass
This is my serializes.py
class MovieSerializer(serializers.ModelSerializer):
class Meta:
model = Movie
fields = ('id', 'title','Showtimes',)

You can do this with two serializers, by swapping out the serializer in the get_serializer_class method on the serializer. This will work with all generic views, including ViewSet instances. In your case, you can also just override serializer_class on the detail view with the custom serializer.
class MovieMixin(object):
queryset = Movie.objects.all()
class MovieList(MovieMixin, generics.ListAPIView):
filter_class = MovieFilter
serializer_class = MovieSerializer
class MovieDetail(MovieMixin, generics.RetrieveAPIView):
serializer_class = MovieDetailSerializer
There are also plugins that allow you to do this, the most notable being the one included with drf-extensions.
These will both require a new serializer that will handle just the detail view representation.
class MovieSerializer(serializers.ModelSerializer):
class Meta:
model = Movie
fields = ('id', 'title', )
class MovieDetailSerializer(MovieSerializer):
class Meta(MovieSerializer.Meta:
fields = MovieSerializer.Meta.fields + ('Showtimes', )
This will allow you to have two different serialized responses for the list view and the detail view.

Related

How to serialize object field in django rest framework

I have Profile model, which is auth model. And I have Blog model. I want to serialize model as it will give me {author: {user_name:.., photo: photo_path}, blog_title:some_title, ..}. Shortly, I want use author field as inner serialiser. I have already ProfileSerialiser and BlogSerializer. Here's my BlogList serializer:
class BlogListSerializer(serializers.ModelSerializer):
author = MiniProfileSerializer()
class Meta:
model = Blog
fields = ['title', 'content', 'like_count', 'author']
read_only_fields = ['views', 'author', 'like_count']
And MiniProfileSerializer:
class MiniProfileSerializer(serializers.ModelSerializer):
class Meta:
model = Profile
fields = ['user_name', 'image']
and view:
class BlogListAPIView(generics.ListCreateAPIView):
serializer_class = BlogListSerializer
queryset = Blog.published.all()
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
Django REST Framework does not support writing to a nested serializer out of the box. You can check out DRF Writeable Nested, or write your own custom behavior on create by overwriting create() in the BlogListSerializer.
EDIT: Here's some more docs on the topic: https://www.django-rest-framework.org/api-guide/relations/#writable-nested-serializers

'CityListViewSet' should either include a `serializer_class` attribute, or override the `get_serializer_class()` method

I am assuming by the error in the title, once more here for clarity
'CityListViewSet' should either include a `serializer_class` attribute,
or override the `get_serializer_class()` method.
that my serializer isn't connected to my view, which in my code it should be. I'm not really sure where the bug is in this one. I wonder if any of you have seen something similar?
Here is the code.
Router:
router.register(r'city-list', CityListViewSet, base_name='city-list')
view:
class CityListViewSet(viewsets.ReadOnlyModelViewSet):
queryset = Venue.objects.values('city').distinct()
serializer = CitySerializer(queryset, many=True)
ordering_fields = ('city',)
ordering = ('city',)
serializer:
class CitySerializer(serializers.ModelSerializer):
class Meta:
model = City
fields =('city',)
what is it that would be causing such an assertion error with the code seemly wired up correctly?
The exception says it itself. You need a serializer_class attribute. You have serializer.
Add this code snippet to your views.py file
class CityListViewSet(viewsets.ReadOnlyModelViewSet): # (viewsets.ModelViewSet)
serializer_class = CitySerializer
queryset = City.objects.values('city').distinct()
serializer = CitySerializer(queryset, many=True)
ordering_fields = ('city',)
ordering = ('city',)
error says you define a serializer attribute, you need to correct with writing
serializer_class attribute in your code,
serializer_class = yourCreatedSerializer
serializer = CitySerializer(queryset, many=True)
The above line should be replaced with
serializer_class = CitySerializer(queryset, many=True)
Here you used a different model name:
view:
class CityListViewSet(viewsets.ReadOnlyModelViewSet): #(viewsets.ModelViewSet)
queryset = City.objects.values('city').distinct()
serializer = CitySerializer(queryset, many=True)
ordering_fields = ('city',)
ordering = ('city',)
import -> from .serializers import TaskSerializers,CitySerializer
serializer:
class CitySerializer(serializers.ModelSerializer):
class Meta:
model = City
fields =('city',)
i got this error when declared post method in view and trying to send post data without serialize, if you are doing the request from javascript i solved it using JSON.stringify()
you have to override the user just add
from django.contrib.auth.models import User
from rest_framework.permissions import IsAdminUser
and in createViewList
permission_classes = [IsAdminUser]
Rename this to
serializer = CitySerializer(queryset, many=True)
This
serializer_class = yourCreatedSerializer
Your job is done

Need help implementing a base serializer in DJango

I am trying to implement a base serializer and I am following the "http://www.django-rest-framework.org/api-guide/serializers/#baseserializer".
My urls.py:
url(r'^auth/myuser/(?P<pk>[0-9]+)/profile/$', UserProfileViewSet.as_view({'patch':'update'}), name='user-profile'),
Views.py:
class UserProfileViewSet(viewsets.ModelViewSet):
queryset = CustomUser.objects.all()
serializer_class = UserProfileSerializer
def get(self,request,pk,*args,**kwargs):
user_instance = CustomUser.objects.get(pk=pk)
dashboard_data = UserProfileSerializer(user_instance)
content = {'result': dashboard_data}
return Response(content)
Serializers.py:
class UserProfileSerializer(serializers.BaseSerializer):
def to_representation(self,obj):
return{
'email':obj.email,
'first_name':obj.first_name,
'last_name':obj.last_name,
'date_of_birth':obj.date_of_birth,
'gender':obj.get_gender_display(),
'location':obj.location,
'calling_code':obj.callingcode,
'phone_primary':obj.phone_primary,
'phone_secondary':obj.phone_secondary,
'website':obj.website
}
But I am getting the error "User object is not JSON serializable", and I don't find any attributes of the User obj that are not serializable.
I already found some answers on SO, but I don't find any similar steps in the django rest framework api guide. So looking for a solution that is in sync with the api-guide.
Serializer:
It seems what you need is a ModelSerializer
The ModelSerializer class provides a shortcut that lets you automatically create a Serializer class with fields that correspond to the Model fields.
class UserProfileSerializer(serializers.ModelSerializer):
class Meta:
model = CustomerUser
fields = '__all__'
I have set fields attribute to __all__ to indicate that all the fields in the model are serialized. But, you can also specify which fields to include exaclty:
fields = ('email', 'first_name', 'last_name',) # etc.
ViewSet:
The second point is about the ModelViewSet where you don't really need to implement the get method because it is already implemented for you. You just need to declare the queryset and the serializer_class just like you have already done:
class UserProfileViewSet(viewsets.ModelViewSet):
queryset = CustomUser.objects.all()
serializer_class = UserProfileSerializer
I guess you'll have to render the response in JSON format before returning it.
class JSONResponse(HttpResponse):
"""
An HttpResponse that renders its content into JSON.
"""
def __init__(self, data, **kwargs):
content = JSONRenderer().render(data)
kwargs['content_type'] = 'application/json'
super(JSONResponse, self).__init__(content, **kwargs)
class UserProfileViewSet(viewsets.ModelViewSet):
queryset = CustomUser.objects.all()
serializer_class = UserProfileSerializer
def get(self,request,pk,*args,**kwargs):
user_instance = CustomUser.objects.get(pk=pk)
dashboard_data = UserProfileSerializer(user_instance)
content = {'result': dashboard_data}
return JSONResponse(content, status=200)
You'll need following imports for this,
from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import JSONParser
If this doesn't work just try passing dashboard_data to the JSONResponse function

ForiegnKey field serializer in Django Rest framework

Before posting this question I've read few questions on SOF. but they are from 2012 and very confusing as well.
for e.g Django Rest Framework - Get related model field in serializer
my question is very straight forward
models.py
class User(models.Model):
username = models.CharField(max_length=100,unique=True)
password = models.CharField(max_length=100,null=False,blank=False)
class Car(models.Model):
user = models.ForeignKey(User)
car_name = models.CharField(max_length=100,null=True,blank=True)
serializers.py
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('username','password' )
class CarSerializer(serializers.ModelSerializer):
#user = ?? what should I write or is there any better approach for serializing Car objects
class Meta:
model = Car
fields = ('user','car_name')
views.py
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
class CarViewSet(viewsets.ModelViewSet):
queryset = Car.objects.all()
serializer_class = CarSerializer
Please suggest all possible approaches.
1 more query. which one is better ModelSerializer or HyperlinkModelSerializer. as I saw different different answers containing these two.
You just need to do:
class CarSerializer(serializers.ModelSerializer):
user = UserSerializer()
class Meta:
model = Car
fields = ('user','car_name')
that is all.
Also, you should take a look to the kindnesses of serializers.Field and serializers.SerializerMethodField, you can play with them and customize your response data as much as you wish.
As to the question around HyperlinkedModelSerializer-ModelSerializer, very clear here:
The HyperlinkedModelSerializer has the following differences from ModelSerializer:
It does not include the pk field by default.
It includes a url field, using HyperlinkedIdentityField.
Relationships use HyperlinkedRelatedField, instead of PrimaryKeyRelatedField.
Hope that helps.

Model multiple field-lookup in Django 1.5

I have a model
class ModelName(models.Model):
type = models.ForeignKey(AnotherModel)
slug = models.SlugField(editable=False)
class Meta:
unique_together = (('type', 'slug'),)
#models.permalink
def get_absolute_url(self):
return ('model_detail', (), {'type': self.type.slug, 'slug': self.slug})
and urls
urlpatterns = patterns('',
url(r'^(?P<type>[-\w]+)/(?P<slug>[-\w]+)/$', ModelDetailView.as_view(), name='detail'),
)
and a DetailView
class ModelDetailView(DetailView):
model = MyModel
template_name = 'detail.html'
but I get the exception MultipleObjectsReturned because the slug isn't unique. I want the urls to be /type/slug/, so the model can contain two records with same slug, but different types, so urls could be /1/slug/ and /2/slug/ with different results. How can I tell the model to use both type and slug as lookup instead of just the slug?
You don't have to 'tell the model' to use the type and string fields -- it's the class based view you have to override.
I suggest you override the get_queryset method, to restrict the queryset to objects of the correct type. An alternative would be to override the get_object method.
class ModelDetailView(DetailView):
model = MyModel
template_name = 'detail.html'
def get_queryset(self):
"""
Restrict queryset to objects of the correct type
"""
return MyModel.objects.filter(type_id=self.kwargs['type'])
See the Django docs on dynamic filtering for more details.

Categories