How can I build a website with template and rest api for mobile app in Django - django

I want to build a project with Django framework, it includes website and mobile app, website is built based on Django template, and mobile app needs rest api. How can I do it with only one copy of source code?
In other words, can I create one project, in which there are several django apps, it supports returning both rendering template and json for mobile app?
I know we can use Angular JS in website, then both website and mobile app access rest api build with Django-Rest-Framework. But I have no idea about Angular JS and there is no time for me to learn it.
Please help.

This is easy to achieve if you leverage the power of HTTP headers, specifically speaking the "Content-Type" header
(HTTP 1.1 headers specification)
The way I personally use it is something like this:
def my_view_name(request):
if 'CONTENT_TYPE' in request.META and \
request.META['CONTENT_TYPE'] == 'application/json':
return HttpResponse(
json.dumps({"foo":"bar"}),
content_type='application/json'
)
else:
return render_to_response(
'sometemplate.html', context
)
The code above is django-specific.
It allows you to control what kind of response the server doles out, based out what the client passes in. It can detect that a JSON response is needed by checking the Content-Type header.
Just ensure your mobile app makes its HTTP requests with the Content-Typeheader set to application/json
Hope that's what you wanted.

You can do it in one project. Have the same Model, but have different views for website and REST-api.

You can build one Common Backend to serve your data.
And you can do this without having a Django-rest-Framework(without having to use angular).
You are just going call the url of the backend.
For eg.,. lets say backend code is running at 127.0.0.1/8000, and you need to get a user's details, you are just going to call url 127.0.0.1:8000/get_user_details/ from mobile app or any other front end.
And please make a habit of forming/arranging data written in a different function so that it is reusable by both the Mobile app and the website.(plz see below)
### For browser website written in DJANGO (served in template by django):
def user_details_page(request):
get_user_details(someid) #### returns json of user details
render in template
#### And for the mobile App you could use **get_user_details(someid)** just to get json data.
def get_user_details(someid):
###do watever
return json ## of user details
And you can also use Django Rest Framework(without having to use angular), it gives you a lot of stability.
Or you can setup a entire new backend in Django Framework to serve data for mobile App.

Related

Is separating django frontend and backend with API viable?

I'm used to Django and already developed website with a whole Django or with Django API + React.
For a side project, I'm thinking about creating a Django project with 2 apps:
Django API 2) Django Front.
I absolutely want to decouple front/back to be able to reuse the API in the future, and I like the view system from Django.
Is my idea making sense?
Edit 1:
To clarify.
App 1: Django API serving JSON.
App 2: Django App using API calls in the controllers to generate the views.
Edit 2:
I did a proof of concept and it works like a charm.
The only drawback is that I have to use Cookies to store the JWT token and maintain the session state, which is not convenient
it is possible, but completely wrong with idea.
How it possible. Wrong version:
Try to remember, how we can create integrate test for our view. We Should create client and send request to Django to your view-url with args kwargs querystring e.t.c.
In response you have already answer. Try to imagine: part with client - is your Django front, requested part - your backend.
The same works not only in test, you can create request to ask something on the completely other server.
Redis/MemCashed e.t.c. (pattern sender/receiver) Wrong version:
The Front Django speaks with Backend through Third part application. It can be faster.
"Pythonic" version. Right in your case:
You can create Backend Django part like a library with views as interfaces.
Frontend Django part is completely standalone, it import an use interfaces from library, which is your "BackEnd Module".
If you want - you can use "BackEnd Module" everywhere as import, or you can start it as server and ask info per requests.
Completely independent in this case means, you can install "BackEnd Module" without "FrontEnd Module". "FrontEnd Module" can be installed standalone too and it should take from settings, which interfaces should be used as data-source.
I hope, i am right understand your question.
You could definitely separate front and back, remember, django just creates endpoints and consumes them with its own views, you can even use both.
Here is the documentation for django views: https://docs.djangoproject.com/en/4.0/#the-view-layer
You can use a librarie like React as frontend and connect to your api(django app) and use both.

Is there a way in django to update the same page with the response without totally rendering it?

Is there a way in django to update the same page with the response without totally rendering it. I am trying to create a code editor to test. But when I am returning the results my contents are removed. I understand it is because I am rendering the page . I need the contents to retain. How can I do it using redirect? I am including the render statement I used and a screenshot of how it looks here:
Steps:
Handle post request
Program execution code
Save the result in a variable called "message". Then I used
return render(request, 'editor.html', {'message': message})
I want to redirect the message to the same page without rendering a new page.
[Before submission][1]
[After submission][2]
[1]: https://i.stack.imgur.com/BxoLU.png
[2]: https://i.stack.imgur.com/uiEOU.png
Any help will be appreciated. Thank you.
it is possible. using ajax in front-end and render or render_to_string in back-end(Django). using ajax you're able to call a url (with/without data you want to send), then in the views.py you can do anything needed and return render(request,'template.html, context). then in ajax you have success: function (res) { $('#id_of_element').append(res)}. this function in ajax will append the recived response which is a rendered HTML template to the target element.
For that, you have to switch to a different web software paradigm called "single page application", which implies that both, backend and frontend, are functional software components on their own, instead of having a "dumb" HTML frontend that only displays what the backend renders.
In a regular web application, the front end is served from a backend with all the information that is going to display. In a Single Page Application, the front end is served by a server independent of the backend server, and the frontend and backend interact through an API served by the backend.
With this architecture, the frontend component is responsible for requesting and providing data from and to the backend, as well as for displaying the data and getting user's interaction, and the mean for interchanging data with the backend is called an ajax, that is an asynchronous request.
The only language accepted by web browsers is javascript, but there are many frameworks and second level languages that can render a javascript application, like React, Angular, Vue, and many others.

Communication between Django and React

I'm trying to setup a project using Django for backend and React for frontend. The project has several screens, a lot of information in DB and images generated by the backend, and will include some authentication and user permissions for different screens.
According to what I found - the best way to do it is having Django render an html file:
def index(request):
return render(request, 'frontend/index.html')
which references a .js file:
<script src="{% static "frontend/main.js" %}"></script>
Which is created using Webpack.
This main.js retrieves the data it needs from Django using a REST api:
fetch("...some Django endpoint..").then(response => ... this.setState(...retrieved data...))
Unlike when just using Django for backend + Django templates for frontend where the backend can just send the context directly to the template:
def index(request):
context = {'information': .... retrieve info from DB}
return HttpResponse(loader.get_template('bla/index.html').render(context, request))
and the template can use this info directly, without referencing the backend again:
{% for bla in information %}
I'm wondering if it is a reasonable setup?
It seems excessive to have the frontend use REST for retrieving each piece of information it needs and the backend exposing another REST api for each part of data it needs to supply (Instead of just pushing all of the information to a single dict and sending it over along with the template),
Also, it requires at least 2 RTTs to render the full page (which I guess usually is okay)
According to what I found - the best way to do it is having Django render an html file:
I disagree with this line. I would say it would be best to keep the react app and Django app totally separate.
I believe, the Django application should solely provide APIs and adminsite(maybe, depending on your needs).
And the frontend should be a standalone app which can be served through NGINX/ExpressJs/Apache etc.
There are several advantages of this setup.
From Django application's perspective, the advantages are:
Django will not be burdened to serve the Frontend. Use gunicorn or uwsgi to serve the Django APIs.
As Django will provide data through API only, it will provide clarity on how the frontend application will communicate with the backend. I know that you can send data using context when Django serves the react app, but this might cause confusion because of API and context's co-existence.
You can use Token based authentication, JWT etc instead of Django's own session based authentication, which have a lot of other advantages.
Freeing your frontend application from backend is the best thing can happen for the frontend. Like for example:
if you had Django to serve the frontend, you were almost forced to use session based auth(its not like you can't use other auths, but whats the point of having multiple auth systems)
You couldn't have used server side rendering with Django rendering the frontend.
Lets say, you are have no idea about how Django works, but you will be forced to setup a Django application in your local machine, because it serves the frontend.
You couldn't have used ExpressJs to serve the frontend, or use the advantages of using NGINX to serve those contents.
Deployment would be complicated if you have docker setup. In this case, you would have had to use one Docker Container to serve everything, else you could have used multiple docker containers to serve backend/frontend.
Lets say, you want to serve the Django application in one server, frontend from other server, but with Django tightly coupled with Frontend, you can't do this setup.
You can easily connect external RESTful API services without bothering about Django. Even you can use any other frameworks like Tornado, Flask etc(but DRF+Django ORM is awesome) to develop APIs.
There are some more generic advantages of having backend and frontend separated.
There is a fantastic tutorial which you can read on medium about setting up separate Django + ReactJs app.
You can use GraphQL, it has several advantages over REST, f.e.:
only one endpoint for entire app;
ability to fetch data with relations between them;
easy data structure modifications on both sides;
advanced client with cache/normalization/subscriptions/optimistic updates (I prefer apollo to relay);
can be used as datasource for static site generation (SEO);
you can stich other services/APIs;
... many more.
Using react Server Side Rendering you can get pages without additional requests - 'prefilled'/rehydrated, ready for interactions - better Time to Interactive.
Tutorial/demo: django-graphql-apollo-react-demo

Django rest framework Reactjs sessions not working

So I have set up Django rest framework as a backend API for an e-commerce website. The website is displayed through a React frontend, which is not served by the django backend.
I am currently running both the Django backend and the React frontend from their local development servers (http://127.0.0.1:8000 and http://127.0.0.1:3000 respectively). In the future they will be on separate domains, probably.
When I set a session in a view, and read the content in another, this works if I just type in the urls for creating and reading directly into my browser (just for testing purposes). But when I access the backend through my frontend, sessions can not be accessed anymore, or don't seem stored. What will happen is that I get a KeyError when trying to access the data that I set in a previous view.
I guess this has to do with something I have read about some time ago, but I find it hard to find the correct information on how to work with this. Does this have to do with the cookie with the session id not being available to the frontend, but only to the backend itself?
Main question:
I would like to know how I can work with sessions, using the above settup, for keeping a shopping cart.
My backend code, just in case someone wonders:
from django.http import HttpResponse
def cart_add(request, product_id, update, quantity):
request.session['one'] = 'created through "cart_add" view'
return HttpResponse("Created a session - cart_add")
def create(request):
request.session['one'] = 'created through "read" view'
return HttpResponse("Created a session - create")
def read(request):
print(request.session['one'])
I have removed some unnecessary code.
The cart_add view is called from the React frontend, using an ajax call (axios).
The create and the read view I called by typing their urls directly into the browser.
(This is all done for testing purposes, just making sure sessions are working before I start to write the real code.)
I've found a solution in another stackoverflow question. This is the link to it.
By adding the following to my axios request, the code works successfully:
axios.get('some api url', {withCredentials: true});
So it seems my assumption about the cookie with the session id not being available to the frontend is incorrect.
I also found out that I could see the cookie by opening the web page in Chrome, then opening the developer tools > going to 'application' tab > click on cookies.
Here all the available cookies are listed, and also a sessionid cookie is shown.
I had the same issue, by adding withCredentials in axios call didn't solve my problem in django 2.2.3 and axios 0.19.0.
If the answer here doesn't work for you, then look into the below answer :)
React Django REST framework session is not persisting/working

notifications handling angular 4 with django backend

i am using following django app for generating notifications
https://github.com/django-notifications/django-notifications. It gives usage instructions for simple html and javascript, but angular won't understand those tags out of box. How can i achieve this with angular 4?
Since Angular will render your templates, you must get that information from api request, so this template tags wont work.
Check if this lib provide apis or try to create one api by yourself and override this lib if is possible