Is there a function that is called when you visit a view in django - python-3.x

Is there a function that is called when a user visits a view (specifically a DetailView) in django. I am trying to count the number of views a particular page has (like StackOverflow), and I want to know if there is a function that I can utilise.
If this is useful, here is the DetailView:
class DetailQuestionView(DetailView):
model = Question
template_name = 'questions/questions-part/question-detail.html'

In all the generic class based views the dispatch method is the entry point of the view logic, i.e. if the view is used dispatch will be called. Also the HTTP method in lowercase i.e. get, post methods are also called depending on the requests method. Therefore you can override either of these two to suit your needs:
class DetailQuestionView(DetailView):
model = Question
template_name = 'questions/questions-part/question-detail.html'
def dispatch(self, request, *args, **kwargs):
# Your code
return super().dispatch(request, *args, **kwargs)

Nevermind, you can use the get method of the DetailView.

Related

Pyramid routing to class methods

From the pyramid documentation, there exists an attr argument on configurator's add_view that states:
The attr value allows you to vary the method attribute used
to obtain the response. For example, if your view was a
class, and the class has a method named index and you
wanted to use this method instead of the class' __call__
method to return the response, you'd say attr="index" in the
view configuration for the view.
With this in mind, I'd like to route all requests under /myrequest to the class MyRequest. Given the following class:
#view_defaults(renderer='json')
class MyHandler(object):
def __init__(self, request):
self.request = request
def start(self):
return {'success': True}
def end(self):
return {'success': True}
It would seem the way to do this would be in the configuration, add these lines:
config.add_view(MyHandler, '/myrequest', attr='start')
config.add_view(MyHandler, '/myrequest', attr='end')
and so on, for all the methods I want routed under MyHandler. Unfortunately this doesn't work. The correct way to do this appears to be:
config.add_route('myroutestart', '/myroute/start')
config.add_route('myrouteend', '/myroute/end')
config.add_view(MyHandler, attr='start', route_name='myroutestart')
config.add_view(MyHandler, attr='end', route_name='myrouteend')
This seems like an awful lot of boilerplate. Is there a way to bring this down to 1 line per route? Or more ideally, 1 line per class?
Example #4 in the Route and View Examples from The Pyramid Community Cookbook v0.2, Pyramid for Pylons Users, offers the following.
# Pyramid
config.add_route("help", "/help/{action}")
#view_config(route_name="help", match_param="action=help", ...)
def help(self): # In some arbitrary class.
...
Although this cookbook recipe mentions pyramid_handlers as one option to do this, the article "Outgrowing Pyramid Handlers" by one of the maintainers of Pyramid encourages the use of Pyramid's configuration.

Can we make either of the serializer fields compulsory in the serializer class itself?

I have a serializer class, which I want to primarily use to fetch request data and use it to save details in different models. I want to have in request body either one or both the parameters. I can handle it in my views.py, though I want to know is there a way we can have that either or both check inside the serializer class itself?
Thanks in advance :)
#serializers.py
class ScanUpdateSerializer(serializers.Serializer):
assets = serializers.ListField(child=serializers.DictField())
issues = serializers.ListField(child=serializers.DictField())
If you want to make either of the two fields compulsory, you could use the validate method to check and enforce it.
E.g.
from rest_framework.exceptions import ValidationError
class ScanUpdateSerializer(serializers.Serializer):
assets = serializers.ListField(child=serializers.DictField())
issues = serializers.ListField(child=serializers.DictField())
def validate(self, attrs):
if not ("assets" in self.initial_data or "issues" in self.initial_data):
raise ValidationError("Either assets or issues need to be set.")
return attrs
I dont know exactly what you want to do, but it seems the case for overwriting the methods def create(self, validated_data) and/or def update(self, instance, validated_data)
You can consult the documentation here: https://www.django-rest-framework.org/api-guide/serializers/#saving-instances

Inheriting __init_subclass__-parameters

Let's say I have a class that requires some arguments via __init_subclass__:
class AbstractCar:
def __init__(self):
self.engine = self.engine_class()
def __init_subclass__(cls, *, engine_class, **kwargs):
super().__init_subclass__(**kwargs)
cls.engine_class = engine_class
class I4Engine:
pass
class V6Engine:
pass
class Compact(AbstractCar, engine_class=I4Engine):
pass
class SUV(AbstractCar, engine_class=V6Engine):
pass
Now I want to derive another class from one of those derived classes:
class RedCompact(Compact):
pass
The above does not work, because it expects me to re-provide the engine_class parameter. Now, I understand perfectly, why that happens. It is because the Compact inherits __init_subclass__ from AbstractCar, which is then called when RedCompact inherits from Compact and is subsequently missing the expected argument.
I find this behavior rather non-intuitive. After all, Compact specifies all the required arguments for AbstractClass and should be usable as a fully realized class. Am I completely wrong to expect this behavior? Is there some other mechanism that allows me to achieve this kind of behavior?
I already have two solutions but I find both lacking. The first one adds a new __init_subclass__ to Compact:
class Compact(AbstractCar, engine_class=I4Engine):
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(engine_class=I4Engine, **kwargs)
This works but it shifts responsibility for the correct working of the AbstractCar class from the writer of that class to the user. Also, it violates DRY as the engine specification is now in two places that must be kept in sync.
My second solution overrides __init_subclass__ in derived classes:
class AbstractCar:
def __init__(self):
self.engine = self.engine_class()
def __init_subclass__(cls, * , engine_class, **kwargs):
super().__init_subclass__(**kwargs)
cls.engine_class=engine_class
#classmethod
def evil_black_magic(cls, **kwargs):
AbstractCar.__init_subclass__(engine_class=engine_class, **kwargs)
if '__init_subclass__' not in cls.__dict__:
cls.__init_subclass__ = evil_black_magic
While this works fine for now, it is purest black magic and bound to cause trouble down the road. I feel like this cannot be the solution to my problem.
Indeed—the way this works in Python is counter-intuitive—I agree with you on your reasoning.
The way to go to fix it is to have some logic in the metaclass. Which is a pity, since avoiding the need for metaclasses is exactly what __init_subclass__ was created for.
Even with metaclasses it would not be an easy thing—one would have to annotate the parameters given to __init_subclass__ somewhere in the class hierarchy, and then insert those back when creating new subclasses.
On second thought, that can work from within __init_subclass__ itself. That is: when __init_subclass__ "perceives" it did not receive a parameter that should have been mandatory, it checks for it in the classes in the mro (mro "method resolution order"—a sequence with all base classes, in order).
In this specific case, it can just check for the attribute itself—if it is already defined for at least one class in the mro, just leave it as is, otherwise raises.
If the code in __init_subclass__ should do something more complex than simply annotating the parameter as passed, then, besides that, the parameter should be stored in an attribute in the new class, so that the same check can be performed downstream.
In short, for your code:
class AbstractCar:
def __init__(self):
self.engine = self.engine_class()
def __init_subclass__(cls, *, engine_class=None, **kwargs):
super().__init_subclass__(**kwargs)
if engine_class:
cls.engine_class = engine_class
return
for base in cls.__mro__[1:]:
if getattr(base, "engine_class", False):
return
raise TypeError("parameter 'engine_class' must be supplied as a class named argument")
I think this is a nice solution. It could be made more general with a decorator meant specifically for __init_subclass__ that could store the parameters in a named class attribute and perform this check automatically.
(I wrote the code for such a decorator, but having all the corner cases for named and unamed parameters, even using the inspect model can make things ugly)

python tornado how to get id of a edge

I have a web application that runs on flask web framework. Flask couldn't answer application requirements anymore. So we have decided to migrate tornado.
I need to handle below two request.
/entry GET Method
/entry/id GET Method
When first request called it must return authenticated entry.
When second request called it must return the entry whose entry_id
is id
Is there a different nice solution to handle above request except my solution. The solution i have found it creates cyclomatic complexity.
def get(self):
id = self.request.path.split('/')[-1]
if id is None:
#return authenticated user
else:
#return the user whose entry_id is id
Note: I am looking a solution like this:
#rest_user.route('/user', methods=['GET'])
#some code
#rest_user.route('/user/<user_id>', methods=['GET'])
#some code
The analogous arrangement in Tornado uses two handler classes (perhaps with a common base class for shared methods):
class AuthedUserHandler(RequestHandler):
def get(self):
...
class UserHandler(RequestHandler):
def get(self, user_id):
...
app = Application([
('/user', AuthedUserHandler),
('/user/(.*)', UserHandler),
])

django-rest-framework: independent GET and PUT in same URL but different generics view

I'm using django-rest-framework and I need to map in the URL file two generic views with the same url (iḿ already using URLs but not Routes):
I need to allow GET, PUT and DELETE verbs in just one url (like /api/places/222) and allow everyone to get every field with the related Entity Place but just allow to update (PUT) one field using the same url.
Place Entity:
- id (not required in PUT)
- name (required always)
- date (not required in PUT but required in POST)
URL
url(r'^api/places/(?P<pk>\d+)/?$', PlacesDetail.as_view(), name='places-detail'),
I tried to use RetrieveDestroyAPIView and UpdateAPIView, but I'm unable to use just one URL.
I suggest you to create a few serializers that satisfy your needs.
Then override the get_serializer method of your view so that the view switches serializers according to an HTTP request method.
This is a quick untested example:
class PlacesDetail(RetrieveUpdateDestroyAPIView):
def get_serializer_class(self):
if self.request.method == 'POST':
serializer_class = FirstSerializer
elif self.request.method == 'PUT':
serializer_class = SecondSerializer
return serializer_class
...
Look at the base class method's comment:
def get_serializer_class(self):
"""
Return the class to use for the serializer.
Defaults to using `self.serializer_class`.
You may want to override this if you need to provide different
serializations depending on the incoming request.
(Eg. admins get full serialization, others get basic serialization)
"""
...

Resources