Converting Django App to DRF App - django

I have a django app that is not live yet and I just got a request to use API and i ended up selecting DRF. But am really lost on some of its components. I was able to login, get token and pass the token to get something. It will use angular.as on front end now, which needs all to be JSON.
While i will rewrite the views, i want to reuse as much as possible especially modules. E.g. I have a validation that validates registration of forms (it used from three different views because a member can be registered in three different ways with some conditions applied i.e. self-registration, company registration and company-agent registration).
def validate_member(data,editing=False,directregistration=True):
#data is passsed from forms.py. Return any error message and the cleaned data to the calling forms.py
return [errmsg,data]
forms.py clean method example:
class NewMemberForm(forms.Form):
firstName=forms.CharField(max_length=25,required=True,widget=forms.TextInput())
def clean(self):
self.cleaned_data=super(NewMemberForm,self).clean()
validate_member_form=validate_member(self.cleaned_data,directregistration=True)
#do we have error messages now?
if len(validate_member_form[0])>0: #yes we have error messages
raise forms.ValidationError(_(validate_member_form[0]),code='invalid')
return validate_member_form[1]
and my views.py:
if request.method=='POST':
err_found=False
go_id=''
form=NewMemberForm(request.POST or None)
if form.is_valid():
#create user
pass
I see forms.py is useless in DRF APIView (i failed to get an example at least). How do I convert such an app without so much pain?

Here's the thing - you can't (at the very least not easily). DRF programmers have decided to implement serializers as completely different still parallel structure from django forms. Infact they don't even share any ancestory. You can certainly share code in forms and serializers using mixins, but then again there are subtle differences like forms have clean methods, while serializers have validate ones.
Here are the few strategies that can be adopted to minimize the code repetition -
Skinny views and fat models - Try to keep most of the business logic either in models (if they are related to models), or in separate domain classes. Views should just be a connection between your models and templates, and shouldn't contain business or model related logic. This way the code you write can be reused among django's normal views and DRF views. If you want to take this a little further, try to encapsulate global validations and constraints (i.e. the validations that always holds true) at model level, and then you can write certain serializer mixins that catch validation error from models and display it to user.
Service Oriented Architecture - Try to write everything as services or REST APIs, and use those services in your normal views. My company had certain performance concerns, so I end up writing a custom request client (on the lines of django test client) that doesn't actually make an http request to an api, but still provides adequate abstraction. This approach might seem lucrative at first, but in long term it creates really messy code. Infact if you are willing to go to such extents, I'd recommend the next approach.
Frontend framework - Provided you don't have certain SEO constraints, then you can certainly move to frontend javascript framework based architecture. Then you only need to write DRF APIs, and all the other code should be handled by client framework. It also accounts for better user experience.

Related

Django: Last modified by and created by user automatic saving

The age-old question: How can I automatically save last_modifed_user in django models?
I found in several places this general process how to do it using thread local. I'm hesitant to simply implement it that way because I'm not entirely sure of the consequences it has and because all these posts are old.
Is using thread local still the "recommended" way of doing this in django 3? Or does django3 have a better options of doing it?
No, this hasn't changed. Simply because separation of concern is an architectural principle of MVC (model-view-controller), which is also how Django (model-view-template) and most web frameworks with ORM are architected. Models know nothing about the request, it's not available (and in many cases there isn't a request at all when a model is saved, think of management commands or regular tasks running in the background).
The alternative to thread local is to make sure you implement it yourself in the controller layer (view layer in Django):
Create a view mixin that you can mix with all the generic views that use the ModelFormMixin to save the user into the model (ModelFormMixin.form_valid()). Or combine it with a form mixin where the user is passed to the form (FormMixin.get_form_kwargs()) and saved when the form is saved (ModelForm.save()).
Create a ModelAdmin mixin that does the same when saving a model in the django admin site.
This of course means someone on your team may forget to do it when creating new views and forms. The link you posted contains an answer as to the advantages and disadvantages of using thread local.

How does viewset aligns with rest methods

I am relatively new to DRF, but found viewsets an amazing abstraction technique for writing RESTful API. I am having a hard time correlating Viewsets with REST methods though. Let's say I have a viewset for Userprofiles and somebody new creates a profile on client.
Should this send a PUT or a POST ?
Which url should this request go to, http://user or http://user/new_id ?
If I want this profile only accessible to the user or admin(all CRUD operations), then where should I handle the code for making it inaccessible to others ?
Should I create a new permission ? If yes, should I handle rest methods in has_permission/has_object_permission ?
I have gone through the tutorial, and know how permissions/mixins works, but I am not able to connect these dots here.
1/ In general, POST is for creating new, PUT is for updating. See the docs on the SimpleRouter to show how the various types of Http methods align with various actions in your Django backend.
2/ You'll find that different situations call for different routing methods. If yours is standard, you may want to use a SimpleRouter like the example above. In that case, creating a new user would be a POST request to /user/ and updating a user would be a PUT request to /user/{{user_id}}/.
3/ To limit access to various API methods, you want to use Permissions. It's possible that you could use one of DRF's Custom Permissions. I've found that in general, if you want only the user to access his/her own profile, it's easier to either use conditional logic within a view (i.e., return a DRF PermissionDenied exception in the view logic if the request.user.pk is not the pk of that REST url. More often than not, I've used the UserPassesTestMixin from Django Braces, that works pretty well to filter user permissions.
4/ I guess the Django Braces mixin above answers this question. You should include a test_func method if you're using Django Braces that returns True if you want to grant the user access, and False otherwise.
Hope this helps! I agree that these are difficult parts of DRF and perhaps some of these could more effectively get incorporated into the source. Good luck!

how to use django restframework as a backend for mobile apps

I need to built an "API". Using django restframework. API has to support multiple platforms like mobile apps, webapps.
API will be used as a backend which will store all information. But my problem is how do I access users information using API. I mean normally django has user model. And we access user related stuff using request.user. But how do I access request.user information using API. Please pardon me for asking such question. But as I am new to developing API for Mobile apps. I am facing difficulty.
I think the easiest way to think about it, is that Django Rest Framework will (normally) return or process JSON data, rather than an HTML page / HTML form data.
Your models stay the same.
If you use Django's ModelForms then DRF's ModelSerialzers are very similar in use.
Likewise, using Django's class based generic views, are very similar to DRF's generic views are very similar - except rather than processing POST data from an HTML forms, they will receive JSON data. The generic views cover the same things - create via POST, update via PUT, delete via DELETE.
Like I say the main difference is that you will be dealing with JSON in place of HTML.
(You could easily use bog standard Django views without the rest-framework and return or process JSON. DRF takes a fair bit of the boilerplate code out of the process).

Django equivalent to Rails application_controller

In Rails, I used the application_controller to control things like user sessions, and create objects to populate parts of the site like the menu.
How should this be done in Django, since there is no kind of "application view"? Do you have to use custom filters and partial templates to be included, for instance in the base template to do this?
I have also been looking at class-based views, but am unsure if that is it.
There are several ways to accomplish this:
Template Tags
Context Processors
Class Based Views
Middleware
It just depends on what you're needing to do. request.user is always present in the request object, even if it's an anonymous user, so you don't have to do anything special to access that object from within a template or server-side code.
Inclusion tags are as close as you'll get to render partial in Rails.
Signals and Class-Based views are close to what you'd find in controller filters.
One of the books I found most helpful when learning Django (I went to Django from Rails) was Practical Django Projects. The Definitive Guide to Django is also available for free.

How to post json to Django

What is the proper way to post json to Django? I have tried to use views, but I am not certain how to handle csrf. Is there another way to bypass views and simply accept a post of json?
Views are what handle the post data. There is no concept of "bypass views" because that is where the work of processing a request is done.
This is probably what your are looking for:
https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax
This shows you how to handle csrf tokens with ajax (namely by using cookies).
I also might suggest you slow down and try to work through the tutorial found here:
https://docs.djangoproject.com/en/dev/intro/tutorial01/
You will likely have an easier time with django if you undertstand how the pieces (Models, Views, Templates, urls, Forms, etc) fit together.
Since you've added that these are API calls the simplest thing to do would be to mark these views as csrf_exempt. Additionally, as you might guess creating an API from models is a common task (I'm assuming that your API maps to models as that's the common case and you haven't specified) you may want to not reinvent the wheel and instead use piston or tastypie to make this easier on you: http://djangopackages.com/grids/g/api/
Use the #csrf_exempt decorator on any API views.