How to Implement Non-endpoint API Functions? - django

This is a pretty high level question but I have been unable to find anything that explains it elsewhere:
I have a django class-based view with endpoints (GET, POST) but I have another method that's not an endpoint but I would like to include as it's used in the GET/POST methods. What would be the best practice for implementing this?
For example:
class users(APIView):
def get(self, request):
# get method
helperFunction()
def post(self, request):
# post method
helperFunction()
def helperFunction():
# not an endpoint
Would this be the right way to do something like this? Should helperFunction() be standalone function outside of a class? Or should non-endpoint methods be in a separate class?
Apologies for the lack of specificity.

pick the location based on the data the function uses.
If it should process data that is relevant only for the class
instance, then yes it belongs to the class
If it should process data that is class type specific, add it as a static method in the class, and feed it with the
concrete instance you need to be processed
If it should process data that is common for a set of
classes, they you can either create an abstract class, put it
there and inherit all classes that use the function from it, or make
it external(see last option)
If it has a general purpose- like time formatting for example, throw it in the global space. Now ideally you would like
to have a separate file where all shit piles, it makes the code base
easier to maintain. In reality however it may be better to keep it
in the file where your class is(provided the other classes that use
it are in the same file)

Related

django class view access response

in function view:
def view(request):
# do something with request
response = render(request, 'view.html')
# do something with response
return response
but now I have a View class:
class ArticleDeleteView(View):
pass
# or even something more complicated
class ArticleDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
pass
which function shall I overwrite to access to the response?
sorry that it may seems a silly question to you, but I looked through the docs and failed to find an answer.
thanks for all suggestions in comment. here's why I need to access to the response. Conditional Django Middleware (or how to exclude the Admin System)
I am building a specific type of 'middleware', for certain class based view, they are not actually middleware since they are not called for each request. I need to access to the response in order to do something before and after the response then return it, therefore I much would like to know which function generate response.
The easiest answer is: you don't. The View classes tend to be uncomplicated enough to be easily rewritten as a custom view which inherently gives you access to the response.
However if you insist I guess one of the functions you could override is the following: as_view, dispatch or setup as the request function goes through all of them. Sadly I couldn't find any mention of the one that was intended for that purpose.

If you have external tasks that gather information about a model should it live in the model as a method?

For example we have a method that fetches additional information about a model from third party APIs. Is it okay to put this as a method on the model or should it live outside?
class Entity(models.Model):
name = ...
location = ...
def fetch_location(self):
# fetch the location from another server and store it.
self.location = "result"
If the data is related to the instance than it can be the right place to put it. Only if you get a lot of these you might want to wrap them in a different class for your own readability (i.e. knowing what is internal and what is external from the instance perspective).
The way I generally do it:
Manager: anything pertaining a group of Model instances
Model: anything pertaining a single Model Instance
Well, if you think in terms of Object Oriented Programming, the answer is "yes":
If "the object can do something", than it should be included as a member function (aka method).
But: If several different classes would need the same functionality (e.g. an "Entity Owner" would like to fetch the location by himself without calling my_entity.fetch_location), you should consider a (abstract) class above both classes which implements the behaviour.
If you have to call the method without an existing instance (which seems not to be the case in your example), you might consider writing the method outside of a class or you add the #staticmethod decorator which allows you to call Entity.fetch_location (remember to omit self in this case since there is no self if there is no instance.) I would prefer the staticmethod over a global method because the caller will always know, which class it relates to.
#staticmethod
def fetch_location():
# fetch the location from another server and store it.
self.location = "result"

Secure-by-default django ORM layer---how?

I'm running a Django shop where we serve each our clients an object graph which is completely separate from the graphs of all the other clients. The data is moderately sensitive, so I don't want any of it to leak from one client to another, nor for one client to delete or alter another client's data.
I would like to structure my code such that I by default write code which adheres to the security requirements (No hard guarantees necessary), but lets me override them when I know I need to.
My main fear is that in a Twig.objects.get(...), I forget to add client=request.client, and likewise for Leaf.objects.get where I have to check that twig__client=request.client. This quickly becomes error-prone and complicated.
What are some good ways to get around my own forgetfulness? How do I make this a thing I don't have to think about?
One candidate solution I have in mind is this:
Set the default object manager as DANGER = models.Manager() on my abstract base class(es).
Have a method ok(request) on said base classes which applies .filter(leaf__twig__branch__trunk__root__client=request.client) as applicable.
use MyModel.ok(request) instead of MyModel.objects wherever feasible.
Can this be improved upon? One not so nice issue is when a view calls a model method, e.g. branch.get_twigs_with_fruit, I now have to either pass a request for it to run through ok or I have to invoke DANGER. I like neither :-\
Is there some way of getting access to the current request? I think that might mitigate the situation...
Ill explain a different problem I had however I think the solution might be something to look into.
Once I was working on a project to visualize data where I needed to have a really big table which will store all the data for all visualizations. That turned out to be a big problem because I would have to do things like Model.objects.filter(visualization=5) which was just not very elegant and not efficient.
To make things simpler and more efficient I ended up creating dynamic models on the fly. Essentially I would create a separate table in the db on the fly and then store a data only for that one visualization in that. My code is something like:
def get_model_class(table_name):
class ModelBase(ModelBase):
def __new__(cls, name, bases, attrs):
name = '{}_{}'.format(name, table_name)
return super(ModelBase, cls).__new__(cls, name, bases, attrs)
class Data(models.Model):
# fields here
__metaclass__ = ModelBase
class Meta(object):
db_table = table_name
return Data
dynamic_model = get_model_class('foo')
This was useful for my purposes because it allowed queries to be much faster but getting back to your issue I think something like this can be useful because this will make sure that each client's data is separate not only via a foreign key, but is actually separated in the db.
Using this method is pretty straight forward except before using the model, you have to call the function to get it for each client. To make things more efficient you can cache/memoize the results of the function call so that it does not have to recompute the same thing more than once.

Mimic remote API or extend existing django model

I am in a process of designing a client for a REST-ful web-service.
What is the best way to go about representing the remote resource locally in my django application?
For example if the API exposes resources such as:
List of Cars
Car Detail
Car Search
Dealership summary
So far I have thought of two different approaches to take:
Try to wrangle the django's models.Model to mimic the native feel of it. So I could try to get some class called Car to have methods like Car.objects.all() and such. This kind of breaks down on Car Search resources.
Implement a Data Access Layer class, with custom methods like:
Car.get_all()
Car.get(id)
CarSearch.search("blah")
So I will be creating some custom looking classes.
Has anyone encoutered a similar problem? Perhaps working with some external API's (i.e. twitter?)
Any advice is welcome.
PS: Please let me know if some part of question is confusing, as I had trouble putting it in precise terms.
This looks like the perfect place for a custom manager. Managers are the preferred method for "table-level" functionality, as opposed to "row-level" functionality that belongs in the model class. Basically, you'd define a manager like this:
class CarAPIManager(models.Manager):
def get_detail(self, id):
return self.get(id=id)
def search(self, term):
return self.filter(model_name__icontains=term)
This could be used either as the default manager -- e.g., in your model definition:
class Car(models.Model):
...
objects = CarAPIManager()
# usage
>>> Car.objects.search(...)
or you could just make it an additional manager, as a property of the class:
class Car(models.Model):
...
api = CarAPIManager()
# usage
>>> Car.api.search(...)

Can a django template know whether the view it is invoked from has the #login_required decorator?

Let's say that I have a system that has some pages that are public (both non-authenticated users and logged-in users can view) and others which only logged-in users can view.
I want the template to show slightly different content for each of these two classes of pages. The #login_required view decorator is always used on views which only logged-in users can view. However, my template would need to know whether this decorator is used on the view from which the template was invoked from.
Please keep in mind that I do not care whether the user is logged in or not for the public pages. What I care about is whether a page can be viewed by the general public, and the absence of a #login_required decorator will tell me that.
Can anyone throw me a hint on how the template would know whether a particular decorator is being used on the view from which the template invoked from?
Yes, it is possible, but not terribly straightforward. The complicating factor is that Django's login_required decorator actually passes through 2 levels of indirection (one dynamic function and one other decorator), to end up at django.contrib.auth.decorators._CheckLogin, which is a class with a __call__ method.
Let's say you have a non-django, garden-variety decorated function that looks like this:
def my_decorator(func):
def inner():
return func()
return inner
#my_decorator
def foo():
print foo.func_name
# results in: inner
Checking to see if the function foo has been wrapped can be as simple as checking the function object's name. You can do this inside the function. The name will actually be the name of the last wrapper function. For more complicated cases, you can use the inspect module to walk up the outer frames from the current frame if you're looking for something in particular.
In the case of Django, however, the fact that the decorator is actually an instance of the _CheckLogin class means that the function is not really a function, and therefore has no func_name property: trying the above code will raise an Exception.
Looking at the source code for django.contrib.auth.decorators._CheckLogin, however, shows that the _CheckLogin instance will have a login_url property. This is a pretty straightforward thing to test for:
#login_required
def my_view(request):
is_private = hasattr(my_view, 'login_url')
Because _CheckLogin is also used to implement the other auth decorators, this approach will also work for permission_required, etc. I've never actually had a need to use this, however, so I really can't comment on what you should look for if you have multiple decorators around a single view... an exercise left to the reader, I guess (inspect the frame stack?).
As unrequested editorial advice, however, I would say checking the function itself to see if it was wrapped like this strikes me as a bit fiddly. You can probably imagine all sorts of unpredictable behaviour waiting to happen when a new developer comes to the project as slaps on some other decorator. In fact, you're also exposed to changes in the django framework itself... a security risk waiting to happen.
I would recommend Van Gale's approach for that reason as something that is explicit, and therefore a much more robust implementation.
I would pass an extra context variable into the template.
So, the view that has #login_required would pass a variable like private: True and the other views would pass private: False
Why does your template need to know this? If the #login_required decorator is used, the view itself prevents people who aren't logged in from ever reaching the page and therefore never seeing the template to begin with.
Templates are hierarchical so why not have a #login_required version and a "no #login_required" version, both of which inherit from the same parent?
This would keep the templates a lot cleaner and easier to maintain.