I am learning Django out of pure passion and I seem to have trouble understanding some core principles of Django that really give me headackes and i tried searching online and reading the docs but i don't seem to fully understand. I'll just simply shoot the questions and try to be clear . I apologise for anything stupid I say . I am just trying to get my knowledge straight.
1. What is a "request"?
OK, so I am thinking of a GET request for a webpage but online i see python code like self.request.user.is_superuser and i am thinking of an User object fetched and displayed to the template to which i can apply User methods. It is clearly more to this request than i already know.
2. CBV's built in methods. The get methods. How do they execute? In what order.
I noticed programmers override these methods sometime . If i redefine more than one method in a CBV i start getting weird behaviour.
For example if i declare and redefine 2 methods in a Detail View get_object() and get_queryset() which of them will be executed first after calling the view? Being a method it should be called somehow in order to execute but i don't know the order how these methods are called for a CBV if there is more than one. Probably i should only define one of them, not both.
3. Queryset. Is it a list?
I have an ideea what querysets are and that you can apply filters to them but what do they return? Do they return objects of the model i am querying?.
OK so, if i have a DetailView CBV and override the get_queryset() method will this return on object and pass it to my template?. Here I am using a filter but what if am not using a filter. What will the CBV return? Will it return the entire set of objects?
class UserDetailView(LoginRequiredMixin,DetailView):
context_object_name='user_detail'
model=models.User
template_name='basicapp/user_detail.html'
def get_queryset(self, *args, **kwargs):
qs = super().get_queryset(*args, **kwargs)
if not self.request.user.is_superuser:
qs = qs.filter(pk=self.request.user.pk)
return qs
4. Can you kindly recommend a Udemy course, video course or book where querysets, CBV methods and ORM are explained clearly?
Preferably video cause it makes so much difference when i see the code working
The thing is I understood how the MVT mechanism works but these class built in methods and overriding them gives me a lot of problems . I never encountered them before and when i start using them I feel like as if i am walking in the dark .
Sorry for the long post.
Thanks
What is a request?
It is a HttpRequest object [Django-doc]. This is an object that contains data about the request the client made to the server. For example this contains an attribute .method [Django-doc] that contains a string like 'GET', 'POST', 'PATCH', etc. that specifies the request method used.
but online i see python code like self.request.user.is_superuser and I am thinking of an User object fetched and displayed to the template to which I can apply User methods.
One can install middleware [Django-doc], this is tooling that pre-processes the request, or post-processes the response. Normally the AuthenticationMiddleware [Django-doc] is added in the settings.py file by default. This will add an extra attribute .user to the request that lazily loads the user that has been logged in. If you would remove this middleware, the .user attribute will no longer exist.
CBV's built in methods. The get methods. How do they execute? In what order.
That depends on the specific class-based view. The documentation however specifies how most methods are performed. For example for a ListView [Django-doc], the documentation mentions the method flowchart:
Method Flowchart
setup()
dispatch()
http_method_not_allowed()
get_template_names()
get_queryset()
get_context_object_name()
get_context_data()
get()
render_to_response()
It also links to the methods that explain what these are doing.
In essence, each class-based view can have methods like get, post, put, patch, etc. Based on the method of the request, the request is dispatched to the method with the same name.
Queryset. Is it a list?
No. A QuerySet is an object that more or less represents a query that you can perform on the database. QuerySets are lazy. That means that as long as you do not iterate over them or for example call len(…) over these, they will not make that query. If you iterate, etc. over these, they will make a query to the database, and then you iterate over the result of the query. The results are normally wrapped in model objects (unless you use functions like values(…) [Django-doc] or values_list(…) [Django-doc].
Can you kindly recommend a Udemy course, video course or book where querysets, CBV methods and ORM are explained clearly?
It might help to start with the Django tutorials. These go step-by-step over the architecture of Django. The documentation on the QuerySet API explains how you can make querysets. The page on Query expressions gives examples on how to make more advanced queries. Finally the Django documentation also has a page on class-based views.
Related
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 am learning django rest framework, while I understand what a serializer does and when you would use it, I cannot fully seat the need for a serializer and a model serialzer class. Can one of you please give me a concrete real world example use case of both please?
Yes I have gone through the tutorial on DRF website several times and I still am experiencing fuzziness
There is an excellent example on the DRF tutorial and it would take too much to cover in an answer, but I would like to make some points.
First, the DRF documentation explains:
Our SnippetSerializer class is replicating a lot of information that's also contained in the Snippet model. It would be nice if we could keep our code a bit more concise.
In the same way that Django provides both Form classes and ModelForm classes, REST framework includes both Serializer classes, and ModelSerializer classes.
The Snippet model is the name of the model used in that example. So as the documentation says, rather than typing again the same fields from the model over to a Serializer, we can use a ModelSerializer as a shortcut, in a similar way that we would use a ModelForm over a simple Form.
But this leaves the question essentially as "ok, then why is there a simple Serializer class at all?", as you pointed out in your comment.
In the vast majority of cases where you have models and you need to serialize/deserialize relevant data (usually JSON but not limited to), then ModelSerializer is the way to go. Even if additional fields, related serializers or arbitrary logic is required, a ModelSerializer can be easily tweaked. Personally it has never occured to me with any of my projects that ModelSerializer is not suitable for data related to a model.
But there may be cases where you need to handle data that do not abide to a model. Such data would be POSTed to a DRF view and a Serializer would handle them. Such cases could be for example to send a mail message, to setup a Celery task, to add data to session, and many others that do not involve a model at all.
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.
Being a newb I'm trying to work out what belongs where. I've got a ListView to list all users in the system, and it includes a get_queryset method -something along the lines of:
def get_queryset(self):
users = []
for user in User.objects.all():
a_user = {}
a_user['username'] = user.username
a_user['full_name'] = user.get_full_name()
a_user['num_of_friends'] = len(user.friends.all())
a_user['phone_num'] = user.get_profile().phone_num
a_user['has_subscription'] = bool(Subscription.objects.filter(subscriber=self.request.user))
users.append(a_user)
return users
So rather than returning a queryset of users I'm making this dictionary out of various chosen attributes of each user, and what a template designer gets is limited to only what I think they should have.
Is it better practice to instead pass user objects to the template, and let the template writer get whatever they need from them? I suppose the answer is Yes.
But, when it comes to the a_user['has_subscription'] line above, I assume the answer becomes No?
The way you've done it is totally fine. I've found it to be useful to separate my templates from my model by explicitly providing the information needed by the template in the view, which is essentially what you've done. It's a little bit weird to not be returning an actual queryset from a method called get_queryset, but I've also come to the conclusion based on criticisms like this that class-based views as they are currently implemented in Django should be considered a means to an end, as opposed to a dogmatic way of organizing your view code. The abstraction simply isn't as clean as say, the Django ORM.
If you really wanted something a little slicker, you could try using the values method to narrow your queryset, with an annotation to add in the subscription count. But there's probably not much point.
It depends on what you're trying to do with the array 'users'. Someone editing the template can only style and display the data in a certain way. The get_queryset function can provide the data for the template.
I think that is the right way to ask it. I'm wondering which parts of the code execute first, second, etc.
My assumption would be, but I don't know:
Request
Middleware
View
Model
Middleware
Response
The reason I'm asking is because I want something to happen dynamicall in the Model based on a request variable and I'm trying to device the best way to automatically add the request in to the model layer without passing in via the views. I would assume that some sort of middleware fantastic contraption would be the way to do it somehow.
To answer your clarification comment -- You can't get there from here.
models.py is just a file where you put model classes, which are just classes that get accessed from all over the place. Unless the request object is passed to the function you're working with, then it does not exist, and there is no request.user. Models can be used from anywhere, not just from within contexts where there's a request.
If you need to work with the request object, then pass it as a parameter. And if that doesn't make sense, then you're using your model wrong.
Neither the model nor the templates are ever part of the stack. Do your work in a view.
I think it's more like:
Request
Middleware (URL mapper)
View
Model (if requested by the view)
Template (if requested by the view)
Middleware (response output)