Distinct not working in DRF sqlite database - django

Distinct not working.I am using sqlite in backend
class getPatient(generics.ListAPIView):
def list(self, request):
queryset = Patient.objects.all().distinct()
serializer = PatientSerializer(queryset, many=True)
return Response({'patient': serializer.data})
I tried :
queryset = Patient.objects.distinct("name").all()
queryset = Patient.objects.values('name').distinct()
queryset = Patient.objects.all().distinct()
Nothing worked

I think it is not possible to use order_by and distinct in sqlite database together since in documentation here it is mentioned for example that those works only in PostgreSQL.

I have to mention that backend sqlite doesn't support distinct. Consider changing for postgresql as the most supported for django backends.
First you have to order objects by the field if you want to distinct.
I have included you the documentation and example.
By default, a QuerySet will not eliminate duplicate rows. In practice, this is rarely a problem, because simple queries such as Blog.objects.all() don’t introduce the possibility of duplicate result rows.
django distinct
Try out, by putting one of your model field. ex. "name".
class getPatient(generics.ListAPIView):
def list(self, request):
queryset = Patient.objects.order_by('name_field').distinct('name_field')
serializer = PatientSerializer(queryset, many=True)
return Response({'patient': serializer.data})

Related

Django REST Framework, display specific foreign key data objects

I'll get straight to my point
Here is my API output:
In pictures, I need to display objects that have primary_placeholder set to True.
I can't find answer on how to do it, I've tried searching in REST Api documentation but nothing seems to work, it always displays every single picture
serializers.py:
views.py
Models.py (Theese two that I'm currently working with)
Does anyone know what is the easiest and fastest way to do it? I have absolutely no idea and I've been trying figure it out for about 2 days now.
Database currently has no pictures with primary_placeholder set to True if anyone is confused
If want to show product pictures with primary_placeholder=True, we can use prefetch_related with Prefetch, please read this.
In your case above, i suggest:
views.py
from django.db import models
from your_app.models import Product, ProductPictures
class ProductList(APIView):
def get(self, request, format=None):
products = Product.objects.all().prefetch_related(
models.Prefetch(
"pictures",
queryset=ProductPictures.objects.filter(primary_placeholder=True)
)
)
serializer = ProductSerializer(products, many=True)
return Response(serializer.data)
Another suggest: In model ProductPictures field model, better if change the field name to product.
Good luck.
write a serializer method field and filter products in it.
class ProductSerializer(serializers.ModelSerializer):
filtered_pictures = serializers.MethodField()
class Meta:
model = Product
fields = ['brand','model','prize','filtered_pictures']
def get_filtered_pictures(self,obj):
if obj.pictures.exists():
queryset = obj.pictures.filter(primary_placeholder=True)
return ProductPictureSerializer(queryset, many=True).data
else:
return None

prefetch_related and Prefetch object issue, filtering thru reverse Foreign Key

I have 2 models, company and Product.
class Product(Meta):
company = models.ForeignKey(Company, related_name='products', on_delete=models.CASCADE)
form the database I'm trying to get the Company data and the corresponding products.
From the products I want to get only the name and to be ordered descending by updated_at, created_at.
I'm working with Prefetch object and prefetch_related and definitively I have multiple misunderstandings how they work.
def get_queryset(self):
qs = Company.objects.prefetch_related(
Prefetch('products', queryset=Product.objects.only('name').order_by('-updated_at', '-created_at'))).get()
return qs
The error that I receive is:
get() returned more than one Company
Because I closed the prefetch_related method/function with ))) :
I thought get() will act over the Company object and get it using the pk/slug from the url(as get do by default in DetailView). Seems that is not the case.
I'm already using 'products' the related name in the Prefetch object, why in queryset is necessary to tell again the model queryset=Product.objects.... ?
I was looking at the following example in django documentation:
Question.objects.prefetch_related(Prefetch('choice_set')).get().choice_set.all()
If there is 'choice_set' in Prefetch object why is called at the end choice_set.all() ?
Isn't Django attached to the quesryset in prefetch_related the products to the queryset (question.choice_set) ?
I think my problem is that I don't understand the order of execution, and I'm confused how methods are chained, even if are closed by ')'
queryset.get() will only work if the queryset has a single object. If it contains zero or more than one objects, you'll get an error.
You should return a queryset from the get_queryset object. In the class based view, the code that filters on the pk/slug is in get_object.
The prefetch_related method is useful if you want to fetch the products for multiple countries. The way that the Django docs use get() is confusing in my opinion - if the queryset has a single item then prefetch_related is over-complicated.
If you have a single company, then there is no advantage, and the code will be simpler if you fetch the countries separately, e.g. in get_context_data.
def get_context_data(self, **kwargs):
context = super(MyView, self).get_context_data(**kwargs)
context['products'] = Product.objects.filter(company=self.object).Product.objects.only('name').order_by('-updated_at', '-created_at')))
return context
I've removed the only('name') call. It's an optimisation that you probably don't need.
If you really want to use prefetch_related, then remove the get().
qs = Company.objects.prefetch_related(
Prefetch('products', queryset=Product.objects.order_by('-updated_at', '-created_at')))
By specifying the queryset above, you are able to change the order (you could filter it if you like). If you don't want to customize the queryset you can simply do:
Company.objects.prefetch_related('products')
When you use Question.objects.prefetch_related(...), the queryset is still a list of questions. You need to call choice_set.all() on the individual instances to access their choices. This won't cause any additional queries, because Django has already prefetched the choices.
queryset = Question.objects.prefetch_related(Prefetch('choice_set'))
for question in queryset:
print(question) # the question
print(question.choice_set.all()) # the related choices

Passing a cursor to a Serializer in django-rest-framework?

I'm using Django 1.8 with django-rest-framework v3.2.2. I have a query that involves raw SQL:
#api_view(['GET'])
def total_spending(request, format=None):
code = request.query_params.get('code', None)
query = 'SELECT * FROM vw_presentation_summary WHERE code=%s"
cursor = connection.cursor()
cursor.execute(query, tuple([code]))
cursor.close()
My question is how to take this cursor and turn it into a data object that I can pass to django-rest-framework's Response.
Right now I'm doing it manually, which works OK:
def dictfetchall(cursor):
"Returns all rows from a cursor as a dict"
desc = cursor.description
return [
dict(zip([col[0] for col in desc], row))
for row in cursor.fetchall()
]
def total_spending(request, format=None):
...
return Response(dictfetchall(cursor))
But would it be better to use a Serializer somehow? I'm not clear if Serializers do anything useful other than define the fields you want to return.
Unless you're dealing with some complicated (including nested) representation of your model objects, a serializer is overkill if you're only going to use it for serializing objects. As you've already noticed, all of your fields can be natively serialized without any extra steps.
Serializers are great for shaping your output (renaming fields, grouping them with nested serializers) and doing it consistently. This is especially true when working with Django models, because Django doesn't natively serialize model objects down to Python dictionaries, it prefers the actual model object.
The power of a serializer comes in the deserialization, where it can map fields across models and build out relations for you. It can also do validation across all of these relations, which is something that would usually take a while to do manually.

django rest framework search filter all fields

I have a base model view set which i can handle order, pagination and search functionalities.
When i have proper filter backends, i can set ordering_fields, search_fields but my question is that:
like i can set ordering_fields = '__all__' isn't it possible to set search_fields for all?
I've looked for deep inside filtering mechanism and came here:
def filter_queryset(self, request, queryset, view):
search_fields = getattr(view, 'search_fields', None)
if not search_fields:
return queryset
orm_lookups = [self.construct_search(six.text_type(search_field))
for search_field in search_fields]
for search_term in self.get_search_terms(request):
or_queries = [models.Q(**{orm_lookup: search_term})
for orm_lookup in orm_lookups]
queryset = queryset.filter(reduce(operator.or_, or_queries))
return queryset
drf fails on generate search_fields if it is set search_fields='__all__'
Is there any other way to provide search by all functionality?
Not possible and it's not a good idea anyway..
One reason is because there can be different types of searching query (__istartswith, __iexact, etc.), which you can set up for each field name.
You can also have different field types which won't necessary support text-base search.
More important - it will result in much slower queries, while you keep adding new fields into the model. It's always better to be explicit, so you know which fields are actually searched upon.
If your searching feature relies on multiple fields, maybe you should consider haystack or look for any other dedicated searching engine.

Django REST Framework - Combining and paginating multiple models

I am working with Django REST Framework and trying to combine two models, Tweet and Article into a single list - Feed. I want Feed to be a list API view that lists Tweet and Article object chronologically, which I've done so far. This is the code that I have...
class FeedViewSet(viewsets.ModelViewSet):
permission_classes = (AllowAny,)
serializer_class = FeedSerializer
paginate_by = 10
def list(self, request, *args, **kwargs):
results_list = list(chain(NewsArticle.objects.all(),
Tweet.objects.all()))
sorted_list = sorted(results_list, key=lambda instance: instance.date_added)
results = list()
for entry in sorted_list:
item_type = entry.__class__.__name__.lower()
if isinstance(entry, Tweet):
serializer = TweetSerializer(entry)
if isinstance(entry, Article):
serializer = ArticleSerializer(entry)
data_dict = {'item': item_type, 'data': serializer.data}
results.append(data_dict)
feed_ser = FeedSerializer(results, many=True)
return Response(feed_ser.data)
This works to the point I can access the data at the API endpoint I set up, however the pagination isn't working with this setup - all items are returned with no options for pagination.
I have followed this solution but I've tried both methods and I have no luck with pagination on either.
EDIT: I know an obvious solution would be to build a base class that they inherit from, and query that table/object, but unfortunately this isn't an option.
Thanks for the help!
Your code doesn't work for pagination because you are not calling the method list from the parent class. That is where the pagination is made, based on your queryset ( look here
at list method in ListModelMixin)
If you want pagination, I see two options:
-- either you implement it yourself, based on the way it is implemented in DRF (link above)
-- or you move all the code that builds your queryset (results) in the get_queryset method and let the framework do the pagination.
Good luck.