mattbroach / djangorestmultiplemodels Goto Github PK
View Code? Open in Web Editor NEWView (and mixin) for serializing multiple models or querysets in Django Rest Framework
License: MIT License
View (and mixin) for serializing multiple models or querysets in Django Rest Framework
License: MIT License
Actually i want to send extra argument with the serializer.
Eg.
serializer = PollDetailSerializer(context={"user_id": request.user.user_id})
I have a viewset that returns 2 models in a querylist, both with a booking_date
Date field.
class MyAPIView(FlatMultipleModelAPIView):
sorting_fields = ['-booking_date']
querylist = [
{'queryset': ModelA.objects.all(), 'serializer_class': ModelASerializer},
{'queryset': ModelB.objects.all(), 'serializer_class': ModelBSerializer},
]
I want the resulting list to be ordered by this date field with newest at the top and going in descending order, like this:
[
{
"type": "ModelA",
"booking_date": "25/12/2021"
},
{
"type": "ModelB",
"booking_date": "23/12/2021"
},
{
"type": "ModelA",
"booking_date": "21/12/2021"
}
]
Is such a feature achievable using DjangoRestMultipleModels
where I can order my querylist by a date field? Ordinarily I would leverage Django's .order_by("-booking_date)"
to achieve this for a single model viewset. Using sorting_fields
seems to only return my querylist alphabetically.
Can i paginate all results queryset? without per queryset pagination .
I just noticed it's kind of api view tool.
Hi, nice job! Question regarding naming - is there any particular reason to write 'queryList' using Camel?
djangorestframework==3.3.1
I really appreciate your work on this package: it is invaluable for my site.
One thing that would make it even better is support for django-filter (https://django-filter.readthedocs.io). This is a popular package that is recommended by DRF.
If I can assist with this, please let me know.
https://django-rest-multiple-models.readthedocs.io/en/latest/flat-options.html
from drf_multiple_model.views import FlatMultipleModelAPIView
class TextAPIView(FlatMultipleModelAPIView):
querylist = [
{
'querylist': Play.objects.all(),
'serializer_class': PlaySerializer,
'label': 'drama',
},
{
'querylist': Poem.objects.filter(style='Sonnet'),
'serializer_class': PoemSerializer,
'label': 'sonnet'
},
....
]
When I follow the above, I get an error ['All items in the MyDemoAPI querylist attribute should contain a queryset
key']
It refers to MultipleModelAPIViewSet whereas the current name of the object is ObjectMultipleModelAPIViewSet.
I keep on Getting this error when using MultipleModelAPIView:
AssertionError:
base_name
argument not specified, and could not automatically determine the name from the viewset, as it does not have a.queryset
attribute.
Code:
#views.py
class CombinedSet(MultipleModelAPIView):
flat = True
queryList = (
(Foo.objects.all(), FooSerializer),
(Bar.objects.all(), BarSerializer),
)
#serializers.py
class OtherSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Other
class FooSerializer(serializers.HyperlinkedModelSerializer):
other = OtherSerializer(many=True, read_only=True)
class Meta:
model = Foo
class BarSerializer(serializers.HyperlinkedModelSerializer):
other = OtherSerializer(many=True, read_only=True)
class Meta:
model = Bar
#models.py
class Other(models.Model):
title = models.CharField(max_length=255)
image = models.ImageField('image')
def __unicode__(self):
return self.title
class Generic(models.Model):
title = models.CharField(max_length=255)
other= models.ManyToManyField(Other, related_name='other', blank=True)
def __unicode__(self):
return self.title
class Foo(Generic):
foo = models.IntegerField(default=0)
class Bar(Generic):
bar = models.CharField(max_length=50)
I have a nested relationship defined as here: http://www.django-rest-framework.org/api-guide/relations/#nested-relationships
When i use MultipleModelAPIView i'm getting TypeError: GenericRelatedObjectManager object is not JSON serializable, but the same serializers works fine in the generics.ListAPIView, and viewsets.ModelViewSet
Any idea?
Hi! Thanks for application)
GeoFeatureModelSerializer from rest_framework_gis + FlatMultipleModelAPIViewSet
from rest_framework import serializers
class DataSerializer(serializers.ModelSerializer):
class Meta:
model = Data
fields = ('__all__')
from rest_framework_gis.serializers import GeoFeatureModelSerializer
class PoiSerializer(GeoFeatureModelSerializer):
class Meta:
model = Poi
geo_field = "geom"
fields = ('__all__')
def to_representation(self, instance):
ret = super(PoiSerializer, self).to_representation(instance)
if ret.get('geometry'):
ret['geometry'].update({'crs': {"type": "name", "properties": {"name": "EPSG:404000"}}})
return ret
class TextAPIView(FlatMultipleModelAPIViewSet):
querylist = [
{'queryset': Poi.objects.all(), 'serializer_class': PoiSerializer}, # GeoFeatureModelSerializer - internal server error
{'queryset': Data.objects.all(), 'serializer_class': dataSerializer}, # ModelSerializer - works ok
]
fails
Traceback (most recent call last):
File "/home/admin/gis/env/lib/python3.6/site-packages/django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File "/home/admin/gis/env/lib/python3.6/site-packages/django/core/handlers/base.py", line 115, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/home/admin/gis/env/lib/python3.6/site-packages/django/core/handlers/base.py", line 113, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/admin/gis/env/lib/python3.6/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "/home/admin/gis/env/lib/python3.6/site-packages/rest_framework/viewsets.py", line 125, in view
return self.dispatch(request, *args, **kwargs)
File "/home/admin/gis/env/lib/python3.6/site-packages/rest_framework/views.py", line 509, in dispatch
response = self.handle_exception(exc)
File "/home/admin/gis/env/lib/python3.6/site-packages/rest_framework/views.py", line 469, in handle_exception
self.raise_uncaught_exception(exc)
File "/home/admin/gis/env/lib/python3.6/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
raise exc
File "/home/admin/gis/env/lib/python3.6/site-packages/rest_framework/views.py", line 506, in dispatch
response = handler(request, *args, **kwargs)
File "/home/admin/gis/env/lib/python3.6/site-packages/drf_multiple_model/mixins.py", line 117, in list
results = self.add_to_results(data, label, results)
File "/home/admin/gis/env/lib/python3.6/site-packages/drf_multiple_model/mixins.py", line 216, in add_to_results
datum.update({'type': label})
AttributeError: 'str' object has no attribute 'update'
it's a django-rest-framework-gis' serializer problem?
Is it possible to have DRF style pagination with flat=True option?
Sample response:
{
"count": 20,
"next": next_link,
"previous": prev_link,
"results": [
...
]
}
Hi @MattBroach ! I was trying to implement PageNumberPagination
support, and it seems to me at this point that for flat views it's better to paginate the whole data, instead of paginating each queryset separately. First I was trying to make some kind of distribution, i.e. if page size is set to 10 and there are 2 querysets, paginate each of them by 5. But this has quite a lot of flaws. For instance, if one of querysets is empty, this just reduces result amount by the portion of data that queryset was supposed to occupy. I saw from the doc, that previous version used to paginate over the whole data set, can you clarify why this was changed? Also, how about different types of pagination for Flat/Object views?
First of all thanks for the work. I really like the poject.
So my question is
Is there any way to return something else than a list with a 200 succes code? something like HttpResponseBadRequest
or HttpResponseForbidden
The most I could do was to raise Http404
but nothing else.
Example:
{
"Play" : {"genre": "Comedy", "title": "A Midsummer Night"s Dream", "pages": 350},
"Poem" : [
{"title": "Shall I compare thee to a summer"s day", "stanzas": 1},
{"title": "As a decrepit father takes delight", "stanzas": 1},
....
],
}
So far I've managed to achieve it by adding a many=[True|False]
argument, and modifying the serializer call, but I wonder if there is another (already existing) way.
nevermind
How can I extend this to add a new field based on which return the results?
For eg. before calling queryList_sort function, I would like to call a custom queryList_merge function.
Hi, is there a possibility of setting limit to the querysets, and then including in the response result count of the each queryset in the list, when flat
is set to False
?
Here's an example showing that:
[
{
'play' : [
{'genre': 'Comedy', 'title': "A Midsummer Night's Dream", 'pages': 350},
{'genre': 'Tragedy', 'title': "Romeo and Juliet", 'pages': 300}
],
count: 20
},
{
'poem' : [
{'title': 'Shall I compare thee to a summer's day?', 'stanzas': 1},
{'title': 'As a decrepit father takes delight', 'stanzas': 1}
],
count: 14
}
]
(In that example, the results are limited to be maximum 2 from the each queryset.)
It would be very useful to have such feature because I want to make in front-end part of the site, to check whether each type has more results to be shown. I doubt it can be made based on pagination (since that is still not supported for this response type; but it would be really great if it becomes possible to be used with PageNumerPagination
simultaneously on the each queryset) so I proposed this way of returning only a result count - the same what LimitOffsetPagination
partly does, but it shouldn't cause a hassle to get that information.
I'm using Python 3.6.3, Django 1.11.6, DRF 3.7.7, version 2.0.1 of this library, and FlatMultipleModelAPIViewSet.
The issue I'm having is:
AssertionError at <URI>
<ViewSet>.get_queryset() returned None
...
Exception Location: <Path>/rest_framework/permissions.py in _queryset, line 126
This is in the code here:
class FlatMultipleModelAPIViewSet(FlatMultipleModelMixin, GenericViewSet):
def get_queryset(self):
return None
And it's running up against this check:
if hasattr(view, 'get_queryset'):
queryset = view.get_queryset()
assert queryset is not None, (
'{}.get_queryset() returned None'.format(view.__class__.__name__)
)
return queryset
Hi, we're using Django Rest Multiple Models to combine several model types into a single API call (the specific use case is an Gallery, where the different models are Images, Panoramas and Videos)
Unfortunately due to the use case of a gallery, there are typically thousands of entries in the database. Pagination is especially useful for filtering down the number of requests.
However, as noted in the documentation pagination is not implemented in a way that can be used to enhance performance, only API usability. Unfortunately this means our request times can be quite large.
I'm wondering, do you have any plans to implement this in a way that could improve performance?
See comment on #1 - because querysets are all forced to be re-evaluated, it's now impossible to cache the DB queries which is essential for some users (e.g. me :) )
For example, when the field value is null it would give the following error on this line: unorderable types: NoneType() < str()
. In my case I'm using DateTimeField
type as the sorting field, which can contain None
sometimes.
Also, it would be very useful once it has a support for specifying multiple sorting fields.
I think it would actually be a very nice API and is a use-case that I currently have.
It would just do what a normal ModelViewset would do to each object individually.
So for example in the object based viewset, you could just apply the appropriate serializer to each list of objects that is in the request.
You know the appropriate serializer, because you are currently using it already to create the same lists when querying the current API.
This behavior would be unambiguous, wouldn't it? And seems pretty intuitive to me, personally.
I was wondering if you know a quick way to implement Django Rest SearchFilter?
In case with TemplateHTMLRenderer temlate do not have results array for use.
class MyList(MultipleModelAPIView):
flat = True
filter_backends = [filters.OrderingFilter]
serializer_class = MyListSerializer
renderer_classes = [JSONRenderer, TemplateHTMLRenderer, BrowsableAPIRenderer]
template_name = 'accounts/my/index.html'
add_model_type = False
def get_queryList(self):
queryList = [
( Record.objects.filter(author = self.request.user), MyListSerializer, 'community')
]
return queryList
When using the standardized format, I am getting the error that
FileViewset has no attribute 'get_extra_actions'
I have tried routing the view using 'as_view' in the router.register function, but that only receives further issues. Viewset appears as:
`class FileViewset(ObjectMultipleModelAPIView):
querylist = (
{'queryset': UploadedFile.objects.filter(id__in=list(EntryFile.objects.all().values_list('entry_id', flat=True))),
'serializer_class':FileSerializer},
{'queryset': FileLink.objects.all(),
'serializer_class':FileLinkSerializer}
)
#for the router
router.register(r'file', FileViewset, basename='files')
That is, can I create a new "Dog" by POSTing to /animals/ ?
Or does the package only serialize and list multiple models in response to a GET request?
Hey thanks for sharing this great app.
I just stumbled upon this repo while trying to implement the same functionality. It works great, but I couldn't get sorting to work the way I wanted.
So I have models A
and B
- both share a created datetime
field. I'd like the FlatMultipleModelAPIView
to return the results from multiple models sorted by the shared datetime
field. The issue is, it only sorts results per page while pagination is enabled.
That is, say I have 20 records for model A
created Today, and 20 records for model B
that were created yesterday, and the page limit is 20. I expect that the first page shows all 20 records of model B
, and the second page shows the records of model A
. However, the result I get for the first page is 10 records of each model, sorted by the date created.
Any way to work around this issue?
drf-yasg package when /swagger is loaded for FlatMultipleModelAPIView , this says AssertionError as 'ViewSet' should either include a serializer_class
attribute, or override the get_serializer_class()
method.
As django-rest-multiple-models needs querylist and not queryset.. So serializer_class cannot be specified
Edit: Figured out that there's get_queryList
method...
Hello. Is there a way to add post method in MultipleAPIView? I really like this project but I need to method for my project. I try to add post and create method in MultipleAPIView class as :
class MultipleModelAPIView(MultipleModelMixin, GenericAPIView):
def get_queryset(self):
return
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
# here is my part
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
def perform_create(self, serializer):
serializer.save()
def get_success_headers(self, data):
try:
return {'Location': data[api_settings.URL_FIELD_NAME]}
except (TypeError, KeyError):
return {}
But it would have a bug ask about serializer_class :
should either include a serializer_class
attribute, or override the get_serializer_class()
method.
Does it have a better way to add post method?
First of all kudos for such a great project. It has helped speed up the dev time a lot.
One of the common use cases which occurs is sorting based on different fields. For ex, the api endpoint may be something like:
GET /blogs?sort_field={sorting_field}
Now in the above example, there can be different values of the sorting criteria like sort by published date or sort by number of upvotes and so on. How best can we do this.
DataViewSet.get_queryset() returned None when using ObjectMultipleModelAPIViewSet.
basename given, even router converted to path function. But still same issue
Getting this issue in django 3.0.14 and django-rest-multiple-models==2.1.3.
Can I get some help here?
Longer lists of results take longer, despite pages being the same size (20 items).
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.