angular $routeProvider does not parse django variables - python

I have this route config:
$routeProvider
.when('/store', {
templateUrl: '/static/js/partials/store.html',
controller: 'StoreController'
})
.when('/groups', {
templateUrl: '/static/js/partials/groups.html',
controller: 'GroupsController'
})
.when('/groups/:id', {
templateUrl: '/static/js/partials/group_page.html',
controller: 'GroupPageController'
})
.when('/purchases', {
templateUrl: '/static/js/partials/purchases.html',
controller: 'PurchaseController'
})
.when('/settings', {
templateUrl: '/static/js/partials/settings.html',
controller: 'SettingsController'
})
.otherwise({redirectTo: '/static/js/partials//store'});
There are lots of django variables and other django stuff used in those HTML files.
But they are not being parsed. For example:
{% trans 'vouchers' %}
is shown in the view insted of 'vouchers'
Why is this happening? How to fix this?

Django templating engine is done on the server side
Angularjs routeProvide is implemented for client side routing.
Hence, your django variables will not be parsed. (since all changes are done on client-side by angularjs and dont actually and is not interpreted by the django templating engine)

Related

Implementing Vue RESTful API calls in Django within Django Templates with Session Authentication

I have a Django project that requires page refreshes any time I want to update the content. Currently it uses the built in Django Class Based Views, which in turn use Templates.
I want to start implementing some javascript calls to refresh tables/forms/modal windows with new data, mostly in response to button clicks. I'm trying to use Vue to accomplish this, and I have created a Django REST Framework backend to facilitate this.
I got a simple 'Hello world' vue class working where the data is hard coded into the data field of the Vue class. I can't seem to make the jump to getting data from the API though. I am getting an Unauthorized response. I am using vue-resource for the HTTP API call.
I have unit tests where I call the API from the DRF APITestCase using the self.client.get('api/path') and they work as expected (unauthorized when there is no authenticated user attached to request, authorized when there is).
I have debugged into the DRF Permission class to see why the request is being refused and it is because there is no authenticated User attached to the request.
I have added SessionAuthentication to the DEFAULT_AUTHENTICATION_CLASSES in settings.
My question is, how do I add an authenticated user to the request so that when the Vue method is called from within my webapp the API request will be authorized?
I'm not sure if this is complicating matters but I am using a custom user model within Django for authentication.
I am hoping to start off by implementing a few Vue controls throughout my website, for instance the tables and forms mentioned. I don't want to turn this into a single page app. I would like to continue using the Django views for user authentication.
My Vue code looks like so;
new Vue({
delimiters: ['${', '}$'],
el: '.events-table',
data: {
message: 'Hello Vue!',
demo: [
{ id: 5 },
{ id: 2 },
{ id: 3 },
],
events: [],
},
http: {
root: 'http://localhost:8000',
},
methods: {
getEvents: function () {
this.$http.get('api/eventlog/events/?format=json').then(
function (data, status, request) {
if (status == 200) {
this.events = data.body.results;
}
}
)
}
},
mounted: function () {
this.getEvents();
}
})
I changed the http property like so
http: {
root: window.location.origin,
},
and now it seems to recognise that the request is coming from an authenticated session.

Django rest-framework with react - blank page on frontend

I have this code on my react App.js:
import React, { Component } from 'react';
import axios from "axios";
import './App.css';
class App extends Component {
state = {
inventory: []
};
async componentDidMount() {
try {
const res = await fetch('http://localhost:8000/items/');
const inventory = await res.json();
this.setState({
inventory
});
} catch (e) {
console.log(e);
}
}
render() {
return (
<div>
{this.state.inventory.map(item => (
//<div key={item.url}>
<div className="App">
<h1>{item.name}</h1>
<span>{item.url}</span>
<span>{item.price}</span>
<span>{item.scalable}</span>
<span>{item.taxable}</span>
</div>
))}
</div>
);
}
}
export default App;
I'm using django react-framework, I want to communicate from react frontend into my django backend through the framework.
So, inventory is the name of the django app. Which is registered on my settings.py file as inventory.
It has a model of course, and one of the classes of this model, is item, which, on my django backend api, the url is defined as items. Like this router.register(r'items', ItemViewSet).
it's like a list of all the products on the database. The typical rest-framework viewset.
Also, this is all serialized, and it's working well on the backend, if I access http://localhost:8000/items/ it works, but the problem is the frontend, it just shows a blank page.
My index.js hasnt been edited, I have installed the axios library, added the "proxy": "http://localhost:8000", line on my packages.json file.
Added also the corsheaders app in my settings.py file, I also have this declared on it:
CORS_ORIGIN_WHITELIST = (
'localhost:3000/'
)
But, it is still showing just a blank page from the react frontend (App.js).
I don't know what could be the cause, if You need further code or explanation, please let me know.

Integrate PayPal in Django app using Paypal Python SDK

I'm working on a project in which I'm using Python(3.6) & Django(1.10) and I need to implement Paypal payment method in this project. I have decided to use the official Python SDK from Paypal instead of other third-party packages.It's not only the csrf problem but it also how we can render a custom form for paypal checkout button.
Here's wwhat Ihave tried.
According to the docs as Here.
Here's my template:
<form class="form">
{% csrf_token %}
<div id="paypal-button"></div>
<script src="https://www.paypalobjects.com/api/checkout.js"></script>
<script>
var CREATE_PAYMENT_URL = '{% url 'users:payment' %}';
var EXECUTE_PAYMENT_URL = 'https://my-store.com/paypal/execute-payment';
paypal.Button.render({
env: 'sandbox', // Or 'production'
commit: true, // Show a 'Pay Now' button
payment: function () {
return paypal.request.post(CREATE_PAYMENT_URL).then(function (data) {
return data.paymentID;
});
},
onAuthorize: function (data) {
return paypal.request.post(EXECUTE_PAYMENT_URL, {
paymentID: data.paymentID,
payerID: data.payerID}).then(function () {
// The payment is complete!
// You can now show a confirmation message to the customer
});
}
}, '#paypal-button');
</script>
</form>
From urls.py:
url('^payment/$', views.PaymentProcess.as_view(), name='payment'),
From views.py:
class PaymentProcess(LoginRequiredMixin, generic.DetailView):
def post(self, request, *args, **kwargs):
mydict = {
'paymentID': 'PAYMENTID',
}
print('Getting payment request')
return json.dumps(mydict)
When Paypal submits a post request to /payment it returns 403 Forbidden error due to csrf_token. How can I pass the csrf_token with this request.
Any resource or tutorial will be really appreciated.
It seems you can add custom headers to your post request : https://github.com/paypal/PayPal-Python-SDK/blob/master/paypalrestsdk/api.py#L270
Given that you just have to add you csrf token to the headers : https://docs.djangoproject.com/en/2.0/ref/csrf/#setting-the-token-on-the-ajax-request
And your server should give you access

Django: AJAX and path params

I am trying to figure out how to communicate variables a particular js file that makes an AJAX request in Django.
Say we have an url with a path param that maps to a particular view:
url(r'^post/(?P<post_id>\d+)/$', TemplateView.as_view('post.html'))
And then the post.html includes a script that performs an AJAX request to fetch the post as JSON:
post.html
<script src="{{ STATIC_URL }}/js/post.js"></script>
<div id="post-container"></div>
This could be the js file. Let's say we do it this way because the post (as JSON) needs to be used in a js plugin to display it in a particular fancy manner.
post.js
$.ajax({
url: '/post/??post_id??',
contentType: 'application/json'
})
.done(function(post_data) {
togglePlugin(post_data);
});
My main concern is how to figure out what post_id is from the js file in order to make the appropriate call.
How are these parts usually connected in Django? The parts I am talking about are urls, path params, views and ajax.
To get urls from your template you should use {% url %} template tag, for that you should add a name to your url:
url(r'^post/(?P<post_id>\d+)/$', TemplateView.as_view('post.html'), name='my_name)
then in your can template call that url in this way {% url 'my_name' object.pk %} see this for more.
when you work with different file for your js, and you want to pass django variables, you should declare a <script> before import the js file, and there declare your variable:
<srcipt>var foo={{django_var}}</script>
<script src="{{ STATIC_URL }}/js/post.js"></script>
and then use the variable foo in the js.
You can pass a post_id variable to django template.
However if you don't want it to "hurt", put your .js code (script) in you html file, rendered by django. So you can use django template tags.
For example:
var url = "/post/{{post_id}}";
$.ajax({
type: 'POST',
url: url,
dataType: 'json',
data: {
some_field: field_data,
some_other_field: field_data
},
success: function(data) {
do_something();
},
error: function(data) {
do_somethin();
}
});

Using the Django URL Tag in an AJAX Call

There are LOTS of post and pages discussing the use of Django and AJAX, and I've read hundreds over the past day or so looking for the answer to this question. A quick overview:
May of the examples show a hard-coded URL like this:
$.post("/projects/create/", {"name" : name}, function(data) {...
or some use the URL template tag, but with no parameters:
$.post("{% url create_project %}", {"name" : name}, function(data) {...
However, I'd like to include a Django-style parameter in a URL. Here's my url definition:
url(r'ajax/entity_name/(?P<pk>\w+)/$',EntityAjaxView.as_view(),name='entity_name'),
Yes, I'm using a class based view, and it is based on DetailView. This view looks by default for a pk value to be provided in the URL, and in a normal template I would use:
{% url entity_name id_number %}
to provide a link. In my code, I want to grab the value entered in an input box for the pk value. Here is a snippet of my JavaScript (which doesn't work):
var id_number = $('#id_endowmententity_set-' + rownum + '-id_number').val()
$.ajax({
type: "GET",
url: '{% url entity_name id_number %}',
So, my question is, can I use the URL template tag with a value from an input box?
(I know that I could use POST instead of GET and pass the id_number in the POST data, but that won't work well with the DetailView.)
Django is a server-side application. Javascript is client-side. Django templates get rendered on the server, so {% url entity_name id_number %} is evaluated on the server side, and then it's value is returned to the client. Just because of this, it's impossible for you to combine Django templates with javascript. However there are couple of things you can do to solve your problem.
Since you are making an ajax call, and the ajax call depends on some user input, usually the best route for the client to send any type of user input to the server is by either using querystring (thing after ? in the URL) or by sending a POST data. So the simplest thing is to change your your url not to include the pk in the url, but for the view to get that as part of GET or POST data.
url(r'ajax/entity_name/$', EntityAjaxView.as_view(), name='entity_name'),
and the view (sorry I'm not familiar with class based views):
def entity_name(request):
pk = request.GET.get('pk')
...
That seems to me to be the most elegant solution. If however you absolutely need to construct the url on the client side, you can generate a template url on the server side and then replace whatever parts you need on the client side to get the full url. This however requires more maintenance and therefore is more error prone. Simple js example of this approach:
var id_number = $('#id_endowmententity_set-' + rownum + '-id_number').val(),
url = '{% url entity_name 0 %}'.replace('0', id_number);
$.ajax({
type: "GET",
url: url,
...
});
It is possible to set an Ajax url on the element you are selecting using an attribute and it will behave like Django urls. Importantly, you can even access the url in Javascript file. I use it a lot
HTML
<div class="card-body" id="js-products" data-url="{% url 'chart-data' %}">
<div class="chart-area">
<canvas id="testChart"></canvas>
</div>
</div>
Note: the data-url attribute set on parent div
JAVASCRIPT
$(document).ready(function () {
var endpoint = $("#js-products").attr("data-url");
var defaultData = [];
var labels = []
$.ajax({
method: 'GET',
url: endpoint,
success: function (data) {
labels = data.labels
defaultData = data.data_default
setChart()
},
error: function (error_data) {
console.log(error_data)
}
})
function setChart() {
var ctx = document.getElementById('testChart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'line',
responsive: true,
data: {
labels: labels,
datasets: [{
label: 'Monthly Performance',
data: defaultData,
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
}
});
DJANGO VIEWS
Am using django rest framework class view but you can use either of function or class based view
class ChartData(APIView):
authentication_classes = []
permission_classes = []
def get(self, request, format=None):
labels = ['Products', 'User', 'May']
data_default = [SeedProduct.objects.all().count(),
User.objects.all().count(), 4]
data = {
'labels': labels,
'data_default': data_default,
}
return Response(data)
DJANGO URLS:
import the view class from views
path('api/chart/data', views.ChartData.as_view(), name="chart-data"),
It's pretty time consuming to go round trip to a server just to fetch a URL. The best strategy to keep URLs dry and avoid this is to generate javascript that emulates Django's native url reverse function and then serve that code statically with the rest of your client side JS.
django-render-static does just that.
This worked for me.
my URL was:
path('myurl/<str:type>', views.myfunction, name='myfunction')
my views.py file:
def myfunction(request,type):
return render(request, "payment.html", context)
In my template, I solved the issue by:
<button type="button" class="btn"
onclick="myfunction('forward');">My Button Name
</button>
<script>
function myfunction(type){
let url = "{% url 'appName:myfunction' 'ok' %}".replace('ok', type);
$.ajax({
method: 'POST',
url: url,
data: {
csrfmiddlewaretoken: '{{ csrf_token }}'
}
});
}
</script>

Categories