Django + Angular2: How to fetch data from database? - python

I am using angular2 as a front end in my html pages.I have a django project that uses postgresql.
Which is the best approach to use the angular2 in the django project to connect to the django models and the database to perform basic operations(CRUD)like Read,Update etc?
Currently I need to fetch the data from the database dynamically.
(e.g.If user clicks on the product from the product list then product details should be retrieved from the database and it is shown to the user)
Any advice or reference example link will be helpful.

Create REST api end points using Django (use DRF for standard REST api's or just use vanilla django to generate json response for the requests and call it REST api).
For ex:
/product/:id is the api end point you've created to fetch the details of a particular product in Django
Then use Angular to request throught those API's and get the responses and do whatever you want with that data.
For ex:
make a get request to /product/1 to fetch the details of a product with PK = 1 when the user clicks that product.
Browse through Github for some inspiration.

Checkout django-rest-framework
DRF is a django app that makes building ReST apps a breeze.
Checkout their quick tutorial to get a sense of how to use DRF in your project.

I'm recently working on the similar project you have. My approach is just like #praba230890 mentioned above.
Here are some samples...
Django
In views.py
class HView(APIView):
def get(self, request, format=None):
request_hero_id = request.query_params.get('id', None)
if request_hero_id:
return Response(
{
'id': 1,
'name': 'test',
'position': 'mid'
},
status=status.HTTP_200_OK
)
return Response(
{ 'error': 'does not exist' },
status=status.HTTP_404_NOT_FOUND
)
class HsView(APIView):
def get(self, request, format=None):
return Response(
[
{
'id': 1,
'name': 'test',
'position': 'mid'
},
{
'id': 2,
'name': 'test',
'position': 'mid'
}
],
status=status.HTTP_200_OK
)
In urls.py
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'', include('shweb.urls')),
]
You will need to install django-cros-headers if you run into CROS errors. Also, you will need to configure your settings.py
Angular2
In api-service.service.ts
import { Injectable } from '#angular/core';
import { Http, Headers } from '#angular/http';
import 'rxjs/add/operator/toPromise';
import { Hero } from '../utils/hero';
#Injectable()
export class ApiService {
/** Modify this later */
private backend_api_url: string = 'http://localhost:8000/api/';
private api_headers: Headers = new Headers(
{ 'Content-Type': 'application/json' }
);
constructor(private http: Http) { }
getHero(id: number): Promise<Hero>{
const url = `${this.backend_api_url}htest/?id=${id}`;
return this.http.get(url).toPromise().then(
response => response.json() as Hero
).catch(this.handleError);
} // END getHero
getHeroes(): Promise<Hero[]>{
const url = `${this.backend_api_url}htests`;
console.log(url);
return this.http.get(url).toPromise().then(
response => {
console.log(response.json());
return response.json() as Hero[];
}
).catch(this.handleError);
} // END getHeroes
private handleError(error: any): Promise<any>{
console.error('An error occurred', error); // TODO: update this
return Promise.reject(error.message || error);
}
}
In hero.ts
export class Hero{
id: number;
name: string;
position: string;
}
In your component file, inject the api-service into component
#Component({
selector: 'app-dashboard',
templateUrl: './dashboard.component.html',
styleUrls: ['./dashboard.component.css']
})
export class DashboardComponent implements OnInit{
title: string = 'Dashboard';
heroes: Hero[] = [];
constructor(private apiService: ApiService){}
ngOnInit(): void{
this.getHeroes();
}
getHeroes(): void{
this.apiService.getHeroes().then(heroes => this.heroes = heroes);
} // END getHeroes
}
Basically, using API to retrieve data and cast into class; then, you can use those data.
PS. I haven't touched the credentials and security part. I believe you need to have some sort of Authentication implemented for secure API communication. (In my case, only GETs are allowed. Therefore, I put the security part for later.)
Hope this would help!

Related

DRF-YASG different authorization for different routes

I've setup DRF-YASG but am unable to figure out how tell it that is should use different authorizations for different routs.
E.g.: My token endpoint(to POST,GET,DELETE api tokens) only accepts basic authentication
but all the other views only work with token authentication.
I know i can define which Authentication methods are available in Swagge-ui
SWAGGER_SETTINGS = {
"DEFAULT_MODEL_RENDERING": "example",
'USE_SESSION_AUTH': False,
'SECURITY_DEFINITIONS': {
'Basic': {
'type' : 'basic',
'name' : 'Basic access authentication',
'in' : 'header',
},
'Bearer': {
'type' : 'apiKey',
'name' : 'Token Bearer authentikation',
'in' : 'header',
}
}
}
but there the client, browsing the Documentation, can still decide whether he wants to authorize with basic- or token-authentication. And if he doesnt know which works for which route it will probably fail.
Does anyone know a solution?
I have tried adding different authentication_classes
class AuthTokenEndpoint(GenericAPIView):
"""
This endpoint does all your token handling.
Here you can create, get or delete your token
"""
permission_classes = [DjangoModelPermissionsIncludingView,]
authentication_classes = [BasicAuthentication]
authentication_classes = [TokenAuthentication]
but nothing changed drf-yasg still does not restrict authentication methods for these views

Wordpress REST API - Post Request for YOAST fields

I'm using python to create wordpress post taking care also of the YOAST fields, using the wordpress rest api. On YOAST website I found this statement:
The Yoast REST API is currently read-only, and doesn't currently
support POST or PUT calls to update the data.
At the same time, I'm wondering if there is some workaround to be able to update the Yoast fields by post request, something like this (that off-course is not working right know):
post = {
'title' : 'My title',
'content' : 'This is my first post created using rest API Updated',
'yoast_head_json': {'title': 'This field should be UPDATED by POST REQUEST'},
}
I found a code snippet at this link, that maybe would be a useful starting point and I report it below:
class YoastUpdateController extends WP_REST_Controller {
public function register_routes() {
register_rest_route( 'wp/v2/', '/action/', array(
'methods' => 'GET',
'callback' => [$this, 'update_yoast_meta']
));
}
function update_yoast_meta($data) {
$postID = $_GET['postID'];
$metadesc = $_GET['metaDesc'];
if ($postID && $metadesc) {
$this->add_to_yoast_seo($postID, $metadesc);
}
}
function add_to_yoast_seo($post_id, $metadesc){
$ret = false;
$updated_desc = update_post_meta($post_id, '_yoast_wpseo_metadesc', $metadesc);
if($updated_desc){
$ret = true;
}
return $ret;
}
}
function register_yoast_update_controller() {
$controller = new YoastUpdateController();
$controller->register_routes();
}
add_action( 'rest_api_init', 'register_yoast_update_controller' );
I placed the above code in function.php, I hope it is the right place.
How could I update all/some of the fields of YOAST by rest api post request? Below some fields (E.g. title, description...)
"yoast_head_json": {
"title": "Post 1 - MyWebsite",
"description": "Meta description added in backend",
"robots": {
"index": "index",
"follow": "follow",
"max-snippet": "max-snippet:-1",
"max-image-preview": "max-image-preview:large",
"max-video-preview": "max-video-preview:-1"
},
Thank you all,
According to yoast documentation: The Yoast REST API is currently read-only, and doesn't currently support POST or PUT calls to update the data.
https://developer.yoast.com/customization/apis/rest-api/#can-i-use-this-api-to-update-data

Concurrent request in django

Concurrent request to Django API from vue returns the response from the last request for both.
Here is my snippet from vue component
methods:{
users(){
axios.get('users').then((response) => {
this.sers = response.data;
}).catch((error) => {
console.log(error);
});
},
new_users(){
axios.get('users', {
params: {type:'new'},
}).then((response) => {
this.new_users = response.data;
}).catch((error) => {
console.log(error);
});
}
},
mounted(){
this.users();
this.new_users();
}
and my python snippet from the Django view
def list_objects(request):
if 'type' in request.GET and request.GET['type'] =='new' :
#return new users
else:
#return users
The problem is the new_users() and users() methods respond with new users data(the one which called last, if we call the users() method last both methods get users data )
The problem is with the Django development server. When I switch to gunicorn all problems gone and now working as expected.

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)

Django: Save JSON to database using Fetch/Post

In a Django app, I want to save JSON to the database using the fetch/post API. Two issues: (1) I'm having CSRF verification troubles, and (2) I'm unsure about using POST to modify the DB in general.
I have a model "Job" with a field that should hold JSON.
class Job(models.Model):
job_id = models.IntegerField()
setup_json = models.CharField(max_length=100000, blank=True, null=True)
The JSON is generated thru user interactions on a page. When the press a "save" button I want to write the JSON to the setup_json field of the proper job.
I don't want to use a form, because the JSON is stored in JavaScript and not written anywhere on the page. So I get the CSRF token from the template to use directly, like this:
{% csrf_token %}
<script type="text/javascript">
const csrftoken = document.getElementsByName("csrfmiddlewaretoken")[0].value;
</script>
(Note: in my "settings.py" file I added the line CSRF_USE_SESSIONS = True in order to use this technique.)
Then I have my save button call a function like this:
function onPressSave() {
fetch(`webapp/api/save-json/${jobId}`, {
method: "POST",
headers: {
"X-Requested-With": "XMLHttpRequest",
"X-CSRF-Token": csrftoken,
"Content-Type": "application/json; charset=utf-8",
Accept: "application/json"
},
credentials: "same-origin",
body: JSON.stringify("test json")
});
}
I get a "POST 403 (Forbidden)" error in the console. Any help with this would be greatly appreciated!
I'm also a little unsure of what exactly the receiving function should look like. Currently it just looks like this:
def save_json(request, id):
j = Job.objects.get(job_id=id)
j.setup_json = json.dumps(dict(name="testing"))
return HttpResponse("OK")
I ultimately want to retrieve the proper JSON from the POST request, but does it look like I'm on the right track with this function?
Django ORM supports JSONFields for a variety of databases, for example if you are using mySQL backend you can:
from django_mysql.models import JSONField
setup_json = JSONField(null=True)
or with PostGreSQL:
from django.contrib.postgres.fields import JSONField
setup_json = JSONField(null=True)
And then with your save function you could:
def save_json(request, id):
# The json you want to save, litterally a python dict {}, or list of dicts [{},{},...]
json_to_be_saved = {}
j = Job.objects.get(job_id=id)
j.setup_json = json_to_be_saved
j.save()
return HttpResponse("OK")
About the 403, It could be that in your settings file you don't have:
CORS_ORIGIN_ALLOW_ALL = True
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware', # <- Added in manually, must be at the top of this list
Which will need you to pip install: pip3 install django-cors-headers
this is something I did a long back ago:
$.ajax({
type: 'POST',
data: JSON.stringify(data),
contentType: 'application/json',
url: "{% url 'login_verification_view' %}",
headers: {
'X-CSRFToken': '{{ csrf_token }}'
},
success: function(j) {
...
your code
}

Categories

Resources