Intergrating Django with React Frontend: Is a REST API Needed - django

so I am trying to connect my back-end Django to my front-end React. Now the front-end react is essentially completed and running on a node server to check it out. I want to integrate it into my Django to use as a back-end. My first thing i want to do is set up the login and register page. I have most of the django back-end done but now i need to get the information like the email and password from the React to Django.
The HTML for EMail and Password
<form action="/authentication/" method ="POST">
{% csrf_token %}
Email :
<input type="email" name="email"><br><br>
Password :
<input type="password" name="pass"><br><br>
<input type="submit" value="Login">
<button type="button" onclick="location.href='{% url 'register' %}'">Register</button>
</form>
the react text field for just the email looks like this:
<TextField
variant="outlined"
margin="normal"
required
fullWidth
id="email"
label="Email Address"
type="email"
name="email"
autoComplete="email"
autoFocus
/>
Django
def user_login(request):
return render(request, 'user_login.html') # page which user will login at
def authentication(request):
email = request.POST.get('email')
passwrd = request.POST.get('pass')
try:
user = authen.sign_in_with_email_and_password(email, passwrd)
except Exception as E:
# Where login fails goes
message = "Credentials Wrong"
return render(request, 'user_login.html', {'message':message}) # sends message login failed
My first question is do i need to create a separate REST API fro the back-end? At the moment the back end is taking a simple test HTML file where i can enter the email and password which is as below, but if i wanted to implement it with react would i have to change out the .html for the .js file?

For React to communicate with Django, it requires an api(Restful or Graphql) to work. Django has a nice way by providing django_resful api or django_graphene which works well with the Django model and reactjs for frontend. For me I use graphql for Django and reactjs, it way so easy and later I will send you a GitHub link of my project or you can check on Youtube (justdjango).

Related

cannot get flask to upload a file [duplicate]

I have the code below in my Python script:
def cmd_wui(argv, path_to_tx):
"""Run a web UI."""
from flask import Flask, flash, jsonify, render_template, request
import webbrowser
app = Flask(__name__)
#app.route('/tx/index/')
def index():
"""Load start page where you select your project folder
or load history projects from local DB."""
from txclib import get_version
txc_version = get_version()
prj = project.Project(path_to_tx)
# Let's create a resource list from our config file
res_list = []
prev_proj = ''
for idx, res in enumerate(prj.get_resource_list()):
hostname = prj.get_resource_host(res)
username, password = prj.getset_host_credentials(hostname)
return render_template('init.html', txc_version=txc_version, username=username)
Also, I have an HTML form in init.html:
<form>
<input type="text" id="projectFilepath" size="40" placeholder="Spot your project files">
<input type="button" id="spotButton" value="Spot">
</form>
How can I pass the user input from "projectFilepath" when a user clicks "spotButton" on a variable in my python script?
I'm new in Python and Flask, so forgive me if I make any mistakes.
The form tag needs some attributes set:
action: The URL that the form data is sent to on submit. Generate it with url_for. It can be omitted if the same URL handles showing the form and processing the data.
method="post": Submits the data as form data with the POST method. If not given, or explicitly set to get, the data is submitted in the query string (request.args) with the GET method instead.
enctype="multipart/form-data": When the form contains file inputs, it must have this encoding set, otherwise the files will not be uploaded and Flask won't see them.
The input tag needs a name parameter.
Add a view to handle the submitted data, which is in request.form under the same key as the input's name. Any file inputs will be in request.files.
#app.route('/handle_data', methods=['POST'])
def handle_data():
projectpath = request.form['projectFilepath']
# your code
# return a response
Set the form's action to that view's URL using url_for:
<form action="{{ url_for('handle_data') }}" method="post">
<input type="text" name="projectFilepath">
<input type="submit">
</form>
You need a Flask view that will receive POST data and an HTML form that will send it.
from flask import request
#app.route('/addRegion', methods=['POST'])
def addRegion():
...
return (request.form['projectFilePath'])
<form action="{{ url_for('addRegion') }}" method="post">
Project file path: <input type="text" name="projectFilePath"><br>
<input type="submit" value="Submit">
</form>

Access request.GET or inject a variable in Django's auth login/registration form

I have a custom form using Django's auth library and I want some users to click on a link to login/register that will pre-populate the email field, without them having to enter their email (avoid entering it manually and make sure the user uses the email we have on file).
A link like this: /account/login?email=name#domain.com
However on the receiving page, I can't use this as Django doesn't permit in templates:
<input type="text" name="username" placeholder="Email" class="form-control" required="" value="{{ request.GET.get('email', '') }}">
If there is a way to inject a variable in Django's auth template, I don't know how since the view is not accessible.
Is there a way to access request.GET.get() in the templates, or is there a better way to do this?
EDIT:
#dirkbo's comment makes sense, however the request is always None in my form, which is called like this:
urlpatterns = [
...
path('accounts/register/', RegistrationView.as_view(form_class=CustomRegistrationForm))
...
]

implementing PayPal IPN in Django Application

I'm writing an application in Django 2.0
It is a multi membership application. I have to implement PayPal payment method and activate the membership based on payment received.
For this, I have created a button in PayPal with generates code as
upgrade.html
<form action="https://www.sandbox.paypal.com/cgi-bin/webscr" method="post" target="_top">
<input type="hidden" name="cmd" value="_s-xclick">
<input type="hidden" name="hosted_button_id" value="<button-id>">
<input type="image" src="https://www.sandbox.paypal.com/en_US/i/btn/btn_buynowCC_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!">
<img alt="" border="0" src="https://www.sandbox.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1">
</form>
and views.py is
class Pricing(TemplateView):
template_name = 'membership/pricing.html'
class Upgrade(TemplateView):
template_name = 'membership/upgrade.html'
class PaymentSuccess(TemplateView):
template_name = 'membership/payment-success.html'
class PaymentFailed(TemplateView):
template_name = 'membership/payment-failed.html'
def paypal_ipn(request):
# IPN response goes here
and urls.py
urlpatterns = [
path('pricing/', Pricing.as_view(), name='pricing'),
path('upgrade/', Upgrade.as_view(), name='upgrade'),
path('payment-success/', PaymentSuccess.as_view(), name='payment-success'),
path('payment-failed/', PaymentFailed.as_view(), name='payment-failed'),
path('paypal-ipn/', paypal_ipn, name='paypal-ipn'),
]
All is working fine as Payment is being made and user is redirected to the payment-success page.
But How do I receive the payment confirmation so that I could process the membership and record the transaction data in the database?
I have enabled instant payment notification from the settings in paypal sandbox accoun on url https://example.com/paypal-ipn/
I do not want to use django-paypal plugin due to some limitations.
You can create your own IPN handling page to receive PayPal IPN message. IPN Sample code below.
https://github.com/paypal/ipn-code-samples

Django Rest Framework returns 200 OK even though login request has incorrect credentials

This is my URLS.py:
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
url(r'^CMS/', include('CMSApp.urls')),
url(r'^admin/', include(admin.site.urls)),
]
and this is CMSApp/urls.py:
from django.conf.urls import url
from django.conf.urls import include
from CMSApp import views
urlpatterns = [
url(r'^$', views.HomePageView.as_view()),
url(r'^users$', views.user_list.as_view()),
url(r'^users/(?P<pk>[0-9]+)$', views.user_detail.as_view()),
url(r'^api-auth/', include('rest_framework.urls',
namespace='rest_framework')),
]
My HomePageView serves this home.html page:
<h3>Register</h3>
<form ng-submit="ctrl.add()" name="myForm">
<label>Username</label>
<input type="text" name="uname" ng-model="ctrl.user.username" required>
<label>Password</label>
<input type="password" name="pwd" ng-model="ctrl.user.password" required>
<label>Email</label>
<input type="email" name="mail" ng-model="ctrl.user.email" required>
<input type="submit" value="Register">
</form>
<h3>Login</h3>
<form ng-submit="ctrl.loginUser()" name="myLoginForm">
<label>Username</label>
<input type="text" name="uname" ng-model="ctrl.user.username" required>
<label>Password</label>
<input type="password" name="pwd" ng-model="ctrl.user.password" required>
<input type="submit" value="Login">
</form>
<script>
angular.module("notesApp", [])
.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
}])
.controller("MainCtrl", ["$http", function($http) {
var self = this;
self.users = {};
var fetchUsers = function() {
return $http.get("/CMS/users").then(function(response) { // get list of existing users
self.users = response.data;
}, function(errResponse) {
console.error("Error while fetching users.");
});
};
self.loginUser = function() {
$http.post("/CMS/api-auth/login/", self.user)
.error(function(data, status, headers, config) {
console.log(data);
})
.then(fetchUsers);
console.log("Success Login with ", self.user);
};
}]);
</script>
When I register a user which already exists, then Django returns a 400 Bad Request error, which is good because I use AngularJS on the frontend to handle the 400 status code.
The issue is, when I try to log in with an incorrect username and password (a username which does not exist or a username and password which do not match), Django returns a 200 OK status code so I can't track the issue using AngularJS on the frontend. Any idea why Django returns a 200 OK when I try to log in with an incorrect username and password? How do I get Django to return a 400 when an incorrect username / password is submitted?
Edit: This was my original post: Django Rest Framework + AngularJS not logging user in or throwing errors and charlietfl commented on it saying "as for the ajax error handling. If login fails .... using true REST methodology would send back a 401 status which would then fire your ajax error handler", which is why I do not want a 200 OK when login fails.
The first thing to understand is that Django does not by default enforce authentication.. you can use the auth module to enroll users and to authenticate them, but you have to protect your views explicitly. The authentication app only provides API's for you to use, it doesn't actually protect anything unless you use those API's.
Any view that isn't explicitly checked for authentication will be open to anyone.
Sure, admin requires you to log in, but that's because the authors of the admin app included checks in their code...
The Django REST Framework has it's own checks for this, so very little coding needed, you just have to configure each view (see docs):
http://www.django-rest-framework.org/api-guide/authentication/
For any other view you might want to protect, you need to add some checks. The #login_required decorator on your view is one way to do that, for regular function type views. Since you are dealing with Class-Based-Views, look at the Django docs here:
https://docs.djangoproject.com/en/1.8/topics/class-based-views/intro/#mixins-that-wrap-as-view
Another option for checking login status is to use a middleware class. That's what I'm doing in my current system since almost everything on our site requires that the user be logged in. So, in the middleware class, we check to see if request.user.is_anonymous. If they are, then there's just a small subset of pages they can access, and if they aren't accessing those pages, we redirect them to login. The middleware runs before any view so that covers the whole site.
Ok, so now that I understand you want to actually log the user in via an ajax request, and not just check their access.. and you want control over what response comes back, then what I suggest is implementing your own view for the login service. Something like:
class LoginView(View):
def get(self, request, *args, **kwargs):
user = auth.authenticate(
username=request.GET.get('username'),
password=request.GET.get('password'))
# return whatever you want on failure
if not user or not user.is_active:
return HttpResponse(status=500)
auth.login(request, user)
return HttpResponse('OK')
I did not test this code but it should be pretty close.

Django how redirect to other site by post query string

How can I redirect from first site to second site.
Second site have form:
<form action="http://example.com/authAs" method="POST">
<input id="login" type="text" name="login"></td>
<input id="password" type="password" name="password"></td>
<button type="submit">login</button>
</form>
I want to authenticate the user at the first site and redirect it to a second site already authorized by POST request
How can I do it?
I have tried do it:
import urllib2,urllib
post_data = [('login', login), ('password', password)]
result = urllib2.urlopen('http://example.com/authAs', urllib.urlencode(post_data))
content = result.read()
But how redirect user to authorized page on second site?
It is not possible to redirect through POST, if you want the client to post to another site the only option is to use javascript to make a browser based redirection.
Instead of redirecting to example site, you can redirect to a local page with the form html and add this JS:
document.forms['form_id'].submit();
Note that the client will see the page for a few seconds before redirection and it won't work if JS is not enabled.