Can I call Django Manager Methods from AngularJS? - python

Is it possible to call Django Manager Methods from AngularJS?
For example like this factory PUT method called in AngularJS:
var app = angular.module('app', ['ngResource', 'ngRoute']);
// Some APIs expect a PUT request in the format URL/object/ID
// Here we are creating an 'update' method
app.factory('Notes', ['$resource', function($resource) {
return $resource('/notes/:id', null,
{
'update': { method:'PUT' }
});
}]);
// snipped ...
Notes.update({ id:$id }, note);
But for Django's get_or_create for example?
So instead of this in Django:
obj, created = MyObject.objects.get_or_create(**kwargs)
I'd like to do something like:
app.factory('Notes', ['$resource', function($resource) {
return $resource('/notes/:id', null,
{
'get_or_create': // some code here but do not know what??
});
}]);
// snipped ...
Notes.get_or_update({ id:$id }, note);
I'd like to do this because I have written a good deal of custom Django Managers and would like to use AngularJS for the UI, but don't want to re-write them all if necessary.
Thanks

The point is that Angular is a client-side framework, and Django is server side. The only way they can communicate is via HTTP, which means that if you want Angular to call a Django manager method, you need to expose that via a URL connected to a view. As the comments say, one way to do that is via Django REST framework, but if that's overkill for your use case you can always write the views yourself.

Related

What is the default hashing algorithm used by Django cache

I am using caching in Django. My cache is a django-redis cache:
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
}
}
I am using view based cache:
#cache_page(timeout=60 * 10)
def my_view(request: Request):
# my view stuff
What I would like to know is what is the algorithm used by Django to create the key? The docs just say that it's made from the URL and headers. But I would like to know the specifics or better yet the code that generates it. But the docs lack this information.
So, how does Django derive keys for view based caches?
Found it!
https://docs.djangoproject.com/en/2.2/_modules/django/utils/cache/
What you are looking for is the method _generate_cache_header_key. Below is how it looks like as of writing this answer:
def _generate_cache_header_key(key_prefix, request):
"""Return a cache key for the header cache."""
url = hashlib.md5(force_bytes(iri_to_uri(request.build_absolute_uri())))
cache_key = 'views.decorators.cache.cache_header.%s.%s' % (
key_prefix, url.hexdigest())
return _i18n_cache_key_suffix(request, cache_key)

React on form changes

I have a general question to the django-admin.
Is it possible to react on form changes?
I have a select field in my django-admin detail site. Whenever I change the data from the select field, I want to change fields which are read-only.
Has anybody ever dealt with this issue?
My two cents:
As any other guys said it is a javascript work. In admin pages Django pases jquery. It is called django.jQuery. So basilly you would do what #Ashfaq suggested. You will create a custom_script.js and added to the Media metaclass.
Basically(as #Ashfaq):
class MyModelAdmin(admin.ModelAdmin):
class Media:
js = ("js/custom_script.js",)
and custom_script.js will be something like this(assuming that your select field is called id_category):
django.jQuery( document ).ready(function() {
console.log( "ready!" );
django.jQuery('#id_category').change(function() {
alert( "Handler for #id_category was called." );
});
});
The ready function will guarantee the handler is getting set.
I think the thing that will work here is to add jQuery + your custom javascript and play with the events / clicks what-ever you want with elements.
class MyModelAdmin(admin.ModelAdmin):
class Media:
js = ("js/custom_script.js",)
in custom_script you can add click or change events as you want.
Found a great answer by Abhijith K in another SO Q&A:
How can i add a onchange js event to Select widget in Django?
reciept=forms.ChoiceField(reciept_types, widget = forms.Select(attrs = {'onchange': "myFunction();"}))
To be clear, this is what you add within your widget definition: attrs = {'onchange': "myFunction();"} to define which JS function will be called, in this when an onchange event is triggers.
In the ModelAdmin you can then define a JavaScript file that you want to have access to, where you can define your function "myFunction()":
#admin.register(AnswerTree)
class AnswerTreeAdmin(ModelAdmin):
form = AnswerTreeForm
...
class Media:
js = ("admin_js/answertree_modeladmin.js",)
Django docs on defining assets (Like JavaScript & CSS) on your ModelAdmin:
https://docs.djangoproject.com/en/dev/ref/contrib/admin/#modeladmin-asset-definitions
What is also useful, I found out that you can access the value of the input by using attrs = {'onchange': "myFunction(this.value);"}, note that I am passing the argument this.value here now.
Example of the JavaScript function definition:
myFunction = (value) => {
console.log(value)
}
OR
myFunction(value) {
console.log(value)
}

Django autocomplete from json

I'm trying to add some autocomplete field in Django Admin (Django 2.0.1).
I managed to get it to work (both with the autocomplete included in Django and with Select2) because in those cases I loaded the dropdown options from a ForeignKey field.
Now I need to have autocomplete on a simple CharField but the choices need to be taken from a remote API that return a json response. I can decide how to structure the json response. Any way to do this?
The returned json responde doesn't represent objects of model, just simple text options.
Not sure if this fits your needs, but here was a solution to a similar problem (remote API, JSON, autocomplete text input). Select portions of the code:
HTML
<label>Which student? (search by last name.)</label>
<input type="text" name="studentname" id="student_name">
JS
// Build list of all students - hit API.
var ajax = new XMLHttpRequest();
ajax.open("GET", "example.com/api/student/?format=json", true);
ajax.onload = function() {
students = JSON.parse(ajax.responseText);
list = students.map(function(i) {
name = i.last_name + ', ' + i.first_name;
return name;
});
var input = document.getElementById("student_name");
new Awesomplete(input, { list: list });
};
ajax.send();
All this of course requires the Awesomplete JS library.
This is a solution when working outside the Django admin, but I think could be adapted to work within the admin setting without too much difficulty?
Perhaps something like this in your ModelAdmin?
def special_field(self, obj):
return render_to_string('special.html')
special_field.allow_tags = True
Then throw the aforementioned HTML/JS in special.html.
Finally you'll need to remove the old field from your ModelAdmin, add your new custom field, and likely override your ModelForm - something like this:
def save(self, commit=True):
extra_input = self.cleaned_data.get('studentname', None)
self.instance.full_name = extra_input # the model instance to save to
return super(NameOfYourForm, self).save(commit=commit)

Sailsjs route and template rendering

This question is directed to anyone with both flask (python) and sailsjs knowledge. I am very new to the concept of web frameworks and such. I started using flask but now I must use Sailsjs. In flask, I can define a route as:
#app.route('/company/<org_name>')
def myfunction(org_name):
...use org_name to filter my database and get data for that company...
return render_template('companies.html', org_name=org_name, mydata=mydata)
Where I can use myfunction() to render a template in which I can pass the parameters org_name and mydata.
In sails, I am confused as to how to define my route with a given parameter. I understand:
'/': {
view: 'companies'
}
but I am not sure how to make the route dynamic in order to accept any variable org_name.
Another problem is that in python, mydata is a query from a MySQL database. I have the same data base connected to Sailsjs with the model completely set up but I am sure this model is useless. The site that I am creating will not be producing any new data (i.e. I will neither be updating nor saving new data to the database).
My Question is thus: with
'/company/:org_name': {
view: 'companies'
}
where should I create the function that filters the database? how should I be sure that sails will pass that org_name parameter into the function and how should I pass the data as a parameter into an html template?
Thanks a ton.
There are 2 options here but it helps to explain a bit about each in order for you to pick the best course of action.
Firstly, routes...You can indeed as you have shown render a view from a route directly, but you can also do a few other things. Below are 2 snippets from the sails.js website docs:
module.exports.routes = {
'get /signup': { view: 'conversion/signup' },
'post /signup': 'AuthController.processSignup',
'get /login': { view: 'portal/login' },
'post /login': 'AuthController.processLogin',
'/logout': 'AuthController.logout',
'get /me': 'UserController.profile'
}
'get /privacy': {
view: 'users/privacy',
locals: {
layout: 'users'
}
},
Snippet 1 shows how you can render a view directly as you have shown but also how you can point to a controller in order to do some more complex logic.
The login within your controller could mean that for the /me "GET" route you can execute a database query within the "profile" method to accept a get parameter, find a user and then display a view with the users data within. An example of that would be:
Profile: function (req,res){
User.find({name: req.param('name')}.exec(function founduser(err,result){
return view('profile',{userdata: result});
});
}
In the second snipped from the sails docs you can see "locals" being mentioned. Here in the GET privacy route we see that the view is being told whether to use the layout template or not. However, with that being said there is nothing stopping you pushing more into the locals such as users name etc.
In my opinion and what I feel is best practice, I would leave your routes.js to be quite thin and logicless, put the database queries/logic/redirections in to your controller.
For your specific example:
My routes.js file may look like this
// config/routes.js
module.exports.routes = {
'get /companies': 'CompanyController.index',
'get /companies/:orgname': 'CompanyController.company'
}
This allows the first route to potentially show a list of companies by going to /companies and my second route may fire when a get request is made based on clicking a company name e.g. /companies/Siemens
My CompanyController.js for these may look like this:
module.exports = {
index: function (req, res) {
return res.view('companieslist');
},
company: function (req, res) {
var companyName = req.param('orgname'); //Get the company name supplied
//My company model which could be in api/models as Company.js is used to find the company
Company.find({name: companyName}).limit(1).exec(function companyresult(err,result){
//Error catch
if(err){return res.negotiate(err)};
//The result of our query is pushed into the view as a local
return res.view('company',{companydata: result}); //Within the .find callback to ensure we keep async
});
}
};
In my view I can access the data retrieved under "companydata" e.g. for EJS:
<%=companydata[0].name%>
If you need any further help/clarifications let me know. I do recommend taking a look at the sails.js documentation but if you really want to get your head around things I recommend sails.js in Action which is an ebook from mannings. A couple of days of reading really got me up to speed!

Locating django app resources

tl:dr
How would a hosted django app correctly transform resource paths to match any hosted location (/ or /test or /testtest)?
Full Description
Let me try to explain what I am trying to do.
I am trying to write a somewhat re-usable django app which I intend to use from within multiple projects. This app is called systemstatus.
The systemstatus app provides a page under '$^' which provides a simple interface to query the system status.
This page makes an ajax query back to the systemstatus app to determine the actual system status and report it on the UI.
The systemstatus app provides a location '^service/$' which points to the ajax call handler.
This page has to somehow figure out the correct URI for the ajax handler depending on where this app is hosted (e.g. under / or /status or /blahblah).
I am wondering what an ideal way of doing this would be. I would say that this applies to other resources bundled inside the app too (stylesheets, images).
Right now I am using request.path to determine what the target path should be. This path is then passed down as a parameter to the template. But this approach will soon become too cumbersome to handle.
def system_status (request):
queryPath = request.path + "service/"
return render_to_response ('systemstatus.html', {'queryPath': queryPath})
My page template looks like this:
function do_ajax () {
$.getJSON ('{{ queryPath }}', function (data) {
$("#status").html (data.status);
});
}
Thanks!
You shouldn't hardcode your urls like that, but use reverse instead!
Django also has a built-in template tag to reverse urls. So you could do something like
function do_ajax () {
$.getJSON ('{% url path.to.my_ajax_view %}', function (data) {
$("#status").html (data.status);
});
}
directly in your template!
You can also send the ajax request directly to your current page's url and check if it is an ajax request or not:
def my_view(request):
if request.is_ajax():
# generate response for your ajax script
else:
# generate the response for normal request
# (render template of your page)

Categories

Resources