How do I test a class based view with given url parameters?
The django documentation seems rather lacking when talking about class Based View testing.
It's not very clear what your question is. If you use the test client, e.g. response = self.client.get('/my-url/param1/param2/', then it doesn't matter whether the view is class-based or function-based.
Related
I am confused which one to use in which scenario in Django view
official documentation
If you are using Django-Restframework i would prefer ModelViewset for built-in list,retrive,get,post,delete method. But if the options are API View or Function based view or Generic Viewset, i will choose Generic Viewset as this gives shortcuts that map closely to database models. Adds commonly required behavior for standard list and detail views. Gives some attributes like, the serializer_class, also gives pagination_class, filter_backend, etc which are very powerful.
I am new to Django Rest Framework. Using serializer and views a simple CRUD is easy. When the logics increase, it is quite confusing where to write logics in serializer or views.
Some developers do prefer "Thick serializer and thin views" and some developers "Thick views and thin serializer".
Maybe this is not a big issue and I think it is up to the developer whether to write more on views or serializer, but as a newbie what will be your suggestion to follow? Should I write more on views or serializer?
There are many answers on Django View Template but can not find a satisfying answer for Django Rest Framework.
Thoughts of experienced developers will be highly appreciated. Thank you.
Personally I prefer to have the business logic separated from both view and serializer. I usually create a new class with the business logic which can be used in both serializer and view based on necessity. Basically I treat it as a service. Reason for that is:
Makes the code cleaner(no thick and thin stuff).
Writing tests for those business logic is easier.
You can use that this business logic service in both view and serializer, depending on your need.
while testing APIs, you can mock those buiness logic if needed.
Reuse any logic in multiple places.
An example would be like this:
class BusinessLogicService(object):
def __init__(self, request):
self.request = request
def do_some_logical_ops(self, data_required_one, data_required_two):
# do processing
return processed_data
Example usage in serializer:
class SomeSerializer(serializer.Serialize):
...
def create(self, validated_data):
business_logic_data = BusinessLogicService(self.request).do_some_logical_ops(**validated_data)
return Model.objects.create(**business_logic_data)
I've asked a similar question about this before. Actually, it depends on what logic you are going to adapt. After doing further research, I have come up with some approaches. Here are my suggestions:
If you want to add some logic before doing serializer validation, it is better to include that in your view (eg. override your views create method). An example to this case would be; your POST body does not contain a value that is needed by the serializer hence is not valid yet, so add that in your view's create function.
If you are doing some custom authentication logic, such as parsing a custom token in your http header, do it in your view as well, because serializer has nothing to do with it. Moreover, you can create your own authentication decorator for that.
If you want to add logic which is directly related to the representation of your data, such as an adaptation of a timestamp from UTC to some other, you can add in your serializer as it is directly related to your object representation. You can use SerializerMethodField etc. to do that.
I try to segregate it on the basis of requirements of the context. Like:
If I'm supposed to deal with the request object(like current user), I try to implement that in view.
If I need to deal with querying models to create a view I would switch to serializer.
It may also depend upon how I'm planning to maintain the code (If I have huge number of views in a single file, I will try to avoid implementing logical stuffs as much as possible).
I want to test a Backbone.js view. All rather generic view methods (get template, get model data, render HTML) are stored in a baseview most of my views extend.
Question 1: Since the two – the view to test and the baseview - are separated, does this mean I don't need to test a view's render method because baseview's test should cover this? Or should I test every view's render method, even when this falls back to methods defined on the baseview, to test how the two play together?
Question 2: I am not sure how the baseview can be tested in isolation. If another view extends it, a template name needs to be set for the baseview to work. Should I just mock the template or treat this view like an abstract class that can't be tested in isolation?
Disclaimer: testing is an art, I don't think there's an obvious "best" answer here. But here's what I would do:
I would test everything: test the base view and all the inheriting views. After all, how do you know that your inheriting views are sharing the same render method as the base view? As your project evolves, you may find that the views you inherit from change—but you probably want to make sure that all your views always render!
I would test the base view as its own instantiated object, even if that's not how you're using it in your application. If a template needs to be set for the base view to work, set a template! I don't think you need to "mock" the template—perhaps you can just use underscore's _.template function?
I am now using Class Based View in my Django application and it helps me a lot to develop faster.
I still have a question about the best way to implement the following:
I have some information in my database I need to always have in almost every template I have (except the template where user is not logged in).
What is the good method to make this using Django ? Is it okay to create a class based view with a custom query in the .get() method?
Thank you :)
There are various different ways to do this.
If you are consistently using class-based views everywhere, you could create a common base class with a custom get_context_data method that adds your specific data to the context dictionary.
But the more usual ways of solving this problem are nothing to do with class-based views, but apply to all sorts of views. They are custom template tags and context processors.
For me, a context processor is probably the best bet: as long as you ensure that your template is rendered with RequestContext (which it will be if you use any view that inherits from TemplateView) then your extra data will always be added to the template context.
I'm converting some django views to be class based, and so far loving the flexibility.
Most of my views subclass from a parent view ClubView. Each subclassed view that needs to handle a post() method override needs to have access to the corresponding club value.
This value is in the URL, so the request variable has it. However, is there a way for me to grab this value, and fetch the corresponding club object outside of the post() method? like a pre-post() method or something. Mainly because I don't want to copy/paste club = Club.objects.get(...
A more general question -- in what order do all the methods execute in? Django's documentation on this seems lacking.
This DjangoProject page on Generic Display Views seems to be the most helpful, imo.
It covers both ListView and DetailView and explains in detail the methods executed in a class-based display view -- Here's an example of DetailView methods called:
setup()
dispatch()
http_method_not_allowed()
get_template_names()
get_slug_field()
get_queryset()
get_object()
get_context_object_name()
get_context_data()
get()
render_to_response()
Actually, you're really doing it upside down. Instead of a central ClubView, it's more flexible to have one view class for each of the individual actions/pages. E.g., you might have something like this:
class ClubListView(ListView):
model = Club
class ClubDetailView(DetailView)
model = Club
# etc...
This way you only need to override specific functionality unique to each of those actions, by defining a particular method on the view class which does what you need. E.g. you need to filter the possible Clubs in the ClubListView dynamically, based on something from the request? Just override the ClubListView.get_queryset method to apply the appropriate filter.
If there is some really peculiar behaviour that needs to be applied to all the views, it depends on what this behaviour really is about: if it's related to this specific model, it should probably best be defined in the model itself, or perhaps its manager; and if it's really something specific to the views, you should write and extend a mixin along with the actual view class.
dispatch is called before post - or, for that matter, get depending on the request. Overriding it should let you set extra information.
The docs lack detail - I didn't really get it until I read the source. But the source is nicely readable except for being spread across multiple files.
You could write a get_club method in your parent class. You can then use this in your subclasses, and you don't have to repeat the logic.