I'm working on a Python/Django project. I have to use the YearArchiveView base class, so I have this:
class ArchiveView(YearArchiveView):
queryset = ArticlePage.objects.all()
make_object_list = True
date_field = 'date'
template_name='btcmag/pages/archives_list.html'
allow_future = False
context_object_name = 'articles'
def extract_month(self, article):
'extracts the starting date from an entity'
return article.date.month
def extract_year(self, article):
'extracts the starting date from an entity'
return article.date.year
Instead of having queryset = ArticlePage.objects.all(), I would like to have a function returning the correct Queryset. Something like:
queryset = getQuerySet()
At the same time I have to pass in some parameters.
I tried defining the function within the class, calling it with self and alone, but I get that the function or self are not defined.
Where do I have to define the function/method?
How can I pass it to queryset?
Instead of having queryset set, in Django views you can overwrite/use the get_queryset method:
class ArchiveView(YearArchiveView):
def get_queryset(self):
...magic here...
return custom_queryset
Related
I am doing join operation using select_related() and filtering records using below code
class ActiveclientViewSet(viewsets.ModelViewSet):
queryset = Ruledefinitions.objects.select_related('pmdclinicalruleid').filter(pmdclinicalruleid__effectivedate__lt = timezone.now(),pmdclinicalruleid__retireddate__gt = timezone.now())
serializer_class = RuledefinitionsSerializer
In the above code, is it possible to check whether the first item from queryset has rulename field value as empty and if it is empty i need to return remaining queryset items in json response if not empty return all items as json response.
What's wrong with checking the first element ?
class ActiveclientViewSet(viewsets.ModelViewSet):
queryset = Ruledefinitions.objects.select_related('pmdclinicalruleid')
serializer_class = RuledefinitionsSerializer
def get_queryset(self):
now = timezone.now
queryset = super().get_queryset().filter(
pmdclinicalruleid__effectivedate__lt=now,
pmdclinicalruleid__retireddate__gt=now,
)
first_item = queryset.first()
if first_item is not None and not first_item.rulename:
queryset = queryset[1:]
return queryset
Your filter on timezone.now() is only executed once: when your classe is defined. So any call to this method should not be in the classe definition, but called every request.
In your actual implementation, now would be called as soon as you start the server. Two weeks later, the filter would still be at the same date.
I want to implement a Django Rest Framework view that returns the dependencies tree of a model instance object. This is the code for such view:
class RoomTypeDependencies(viewsets.ViewSet):
def list(self, request, pk):
room_type = models.RoomType.objects.get(pk=pk)
dependency_tree = self.get_object_dependencies(room_type)
return Response(dependency_tree)
def get_object_dependencies(self, instance):
fields = instance.__class__._meta.get_fields()
dependencies_to_return = []
for field in fields:
print(field.name)
if field.__class__.__name__ == 'ManyToOneRel':
dependency_to_return = []
dependent_instances = getattr(instance, field.name)
for dependent_instance in dependent_instances:
dependency_to_return.append(self.get_object_dependencies(dependent_instance))
dependencies_to_return.append({field.__class__.__name__: dependency_to_return})
return Response({str(instance): dependencies_to_return})
Everything seems to work, but I expected getattr(instance, field.name) to return the dependent instances corresponding to the reverse relationship, just like using model_object_instance.reverse_relationshio_name pattern, but it returns a RelatedManager object instead. The problem in my case is that I have the reverse relationship name in a string variable (field.name).
I have a view to list a certain model (lets call it class A), like this:
class BaseListView(ListView, MultipleObjectMixin):
http_method_names = ['get']
order_field = None
def get_paginate_by(self, queryset):
session_manager = SessionManager(self.request.session)
return session_manager.paginate_by.get()
def get_context_data(self, **kwargs):
context = super(BaseListView, self).get_context_data(**kwargs)
session_manager = SessionManager(self.request.session)
session_manager.paginate_by.set_to(context)
return context
This view did just what was needed, till now. Now I have to compare the list of objects it retrieves with another list of objects (class B).
The objects of class A and B both have a primary key with their name.
I want to check if any of the objects from class A has the same name (primary key) as any of the objects in class B. In case there is an instance of A in B I would like to add a certain parameter or something like is_in_B=True.
I need this so that I can represent these instances of A in a different way in the template.
How could I do this?
This is what I have come up with by myself for the moment:
class AListView(BaseListView):
model = "A"
def get_queryset(self):
queryset = super(AListView, self). get_query_set()
all_objects_A = A.objects.all()
all_objects_B = B.objects.all()
# modify queryset to indicate which instances of A are present in B
# No idea how to do this
return queryset
I'm not really sure this is an appropiate approach.
Also, how am I supposed to modify the queryset returned by my class so that I can indicate which instances of class A share the same name as any of the instances of class B?
You can annotate your queryset with a conditional expression to achieve this:
from django.db.models import Case, When, Value
def get_queryset(self):
# This gives you the queryset of A objects
queryset = super(AListView, self).get_queryset()
# List of primary keys of B objects
all_objects_B = B.objects.all().values_list('pk',flat=True)
# modify queryset to indicate which instances of A are present in B
return queryset.annotate(
is_in_b=Case(When(pk__in=all_objects_B, then=Value(True)),
default=Value(False))
)
)
Your queryset objects will now have an is_in_b property.
This will work fine if your list of B objects is small. If it is large then I am not sure it is very efficient, and you may need to develop this further to see whether the check (is A in B) can be done directly in the database (possibly requiring raw SQL).
Here is my tastypie code snippet.
I have a Resource and in post_list method , an instance of Mysample is getting created there.
I want to call a method of Mysample Instance , Please help me how to do that,
please find the comment in code where I need to call the method of Mysample instance
class MysampleResource(ModelResource):
intfeild1 = fields.IntegerField('intfeild1_id', null=True)
intfeild2 = fields.IntegerField('intfeild1_id')
class Meta:
always_return_data = True
queryset = Mysample.objects.all()
allowed_methods = ['get','post','put','delete',]
authentication = SessionAuthentication()
authorization = MysampleAuthorization()
def post_list(self, request, **kwargs):
result = super(MysampleResource, self).post_list(request, **kwargs)
#here I want to call a method of Mysample Instance.
return result
Please help me , I'm begginer, so could you please give suggestion on which method to override and where should I need to do that.
You just need to add your method in your resource:
def test_method(self,param*):
#Do your stuff
return result
and within post_list you can call it like:
self.test_method(param*)
Note: The method declaration include 2 params but in python "self" is passed on as an implicit param so that when you call your method you don't pass on the self object.
= could be more than just one parameter in that case use "," in order to separate them.
If we apply all the previous concepts your code should look like:
class MysampleResource(ModelResource):
intfeild1 = fields.IntegerField('intfeild1_id', null=True)
intfeild2 = fields.IntegerField('intfeild1_id')
class Meta:
always_return_data = True
queryset = Mysample.objects.all()
allowed_methods = ['get','post','put','delete',]
authentication = SessionAuthentication()
authorization = MysampleAuthorization()
def post_list(self, request, **kwargs):
result = super(MysampleResource, self).post_list(request, **kwargs)
#Let's say that you want to pass resquest as your param to your method
method_result=self.test_method(request)
return result
def test_method(self,request):
#Do your stuff
return result
I want to be able to sort by several custom methods in Django Admin. This question provides solution for one method only.
I tried to modify it:
from django.db import models
class CustomerAdmin(admin.ModelAdmin):
list_display = ('number_of_orders','number_of_somevalue') # added field
def queryset(self, request):
qs = super(CustomerAdmin, self).queryset(request)
qs = qs.annotate(models.Count('order'))
qs = qs.annotate(models.Count('somevalue')) # added line
return qs
def number_of_orders(self, obj):
return obj.order__count
number_of_orders.admin_order_field = 'order__count'
def number_of_somevalue(self, obj): # added method
return obj.somevalue__count
number_of_somevalue.admin_order_field = 'somevalue__count'
and it works incorrectly. It seems that it multiplies the count values instead of counting them separately.
Example:
I have 2 orders and 2 somevalues, but in the panel I see 4 orders and 4 somevalues.
Adding another method with yet another value makes it 8 (2*2*2).
How can I fix it?
You can try this to sort by many custom methods (Tested):
from django.db.models import Count
class CustomerAdmin(admin.ModelAdmin):
# The list display must contain the functions that calculate values
list_display = ('number_of_orders','number_of_somevalue') # added field
# Overwrite queryset in model admin
def queryset(self, request):
qs = super(CustomerAdmin, self).queryset(request)
# The query have to return multiple annotation, for this use distinct=True in the Count function
qs = qs.annotate(number_orders = Count('order', distinct=True)).annotate(number_somevalue = Count('somevalue',distinct=True))
return qs
# This function return the new field calculated in queryset (number_orders)
def number_of_orders(self, obj):
return obj.number_orders
number_of_orders.admin_order_field = 'numberorders' # sortable new column
# And this one will return the another field calculated (number_somevalue)
def number_of_somevalue(self, obj): # added method
return obj.number_somevalue
number_of_somevalue.admin_order_field = 'number_somevalue'# sortable new column