ExtJs to DJango url query parameters - django

Ok So this is kinda a long question. I am using ExtJS and Django to create a websiteish. Ive search the internet on how to add query parameters to the url when get an IFrame. So bascily I have this which creates a panel in ExtJS which has an html page with in it. I want to be able to pass a port number with in the url so that when it calls the html it will automaticly have the port number to connect to with vnc. My VNC client is noVNC
var noVNC = Ext.create('Ext.panel.Panel', {
title: "noVNC",
frame: false,
title: false,
width: '100%',
height: '100%',
layout: 'fit',
items: [{
xtype: "component",
autoEl: {
tag: "iframe",
src: "/noVNC"
}
}]
});
At first I thought that I could just do
src: "/noVNC?port=5900"
However, (through research) I realized you have to edit views.py and urls.py
I think i have urls.py correct
from django.conf.urls.defaults import *
urlpatterns = patterns('',
url(r'^$', 'kfe.views.index'),
url(r'^index$', 'kfe.views.index'),
url(r'^noVNC/(?P<port>\d+)/$' , 'kfe.views.noVNC'),
)
But I am not sure how to use the views.py
def noVNC(request):
return render(request, 'noVNC_Auto.html', content_type='text/html')
hope that is enough info. If not just tell me
Thanks

Ok so the way I fixed it was very easily because of my conditions (I did not need any of my arguments in views.py).
So what I did was inside my IFrame html page I did this
window.onload = function () {
con_port = "?port=" + WebUtil.getQueryVar('con_port', null);
and inside ExtJS I did this
var noVNC = Ext.create('Ext.panel.Panel', {
title: "noVNC",
frame: false,
title: false,
width: '100%',
height: '100%',
layout: 'fit',
items: [{
xtype: "component",
autoEl: {
tag: "iframe",
src: "/noVNC?con_port=5901"
}
}]
});
for now I just hard coded in the port number but you can just add your port number to the string like so
src: "/noVNC?con_port=590" + port
views.py
def noVNC(request):
return render(request, 'noVNC_Auto.html', content_type='text/html')
urls.py
urlpatterns = patterns('',
url(r'^$', 'kfe.views.index'),
url(r'^index$', 'kfe.views.index'),
url(r'^noVNC$' , 'kfe.views.noVNC'),

Related

How to extract a geometry from PostGIS using a view and then add it to a leaflet map in a template using Django

I want to extract polygon geometry data from a PostGIS database using python within a view and add it to my leaflet map within a template.
The easiest way seemed to be to extract the data and convert it to GeoJSON using the postgis function ST_AsGeoJSON in my Django view and then render it to the template as context within the L.geoJSON(GEOJSON).addTo(map) function.
This does not work. On requesting the map page, the map is now blank and as it seems the GeoJSON is not recognised. I have been able to pass a hard-coded polygon from a view and add it to a map but the geometry data in my postgis database simply isn't valid.
Here is a view with a hardcoded polygon that is successfully printed on the map:
from django.shortcuts import render
def map_view(request, *args, **kwargs):
geo_json={
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-0.10746002197265625,
51.505537109466715
],
[
-0.11466979980468751,
51.498377681772325
],
[
-0.0968170166015625,
51.493568479510415
],
[
-0.09080886840820312,
51.502438390761164
],
[
-0.10746002197265625,
51.505537109466715
]
]
]
}
}
]
}
return render(request ,'map.html', {'geo_json': geo_json})
The map template looks as follows:
<!DOCTYPE html>
<html>
<head>
<title>Map Page</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.6.0/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet#1.6.0/dist/leaflet.js"></script>
<style>
#map { position: relative;
width: 600px;
height: 775px;
border: 3px solid #000000;}
</style>
</head>
<body>
<div id="map"></div>
<script>
var map = L.map('map').setView([54.8,-4.45],6);
L.tileLayer('https://api.maptiler.com/maps/streets/{z}/{x}/{y}.png?key=9GKOA9jJ3jCIWFUd8k00', {attribution: '© MapTiler © OpenStreetMap contributors',}).addTo(map);
L.geoJSON({{ geo_json | safe }}).addTo(map);
</script>
</body>
</html>
Here is the leaflet map with the polygon added
Now when I try to get pass GeoJSON from my postgis database using my new view it doesn't work:
import psycopg2
from django.shortcuts import render
def map_view(request, *args, **kwargs):
connection = psycopg2.connect(database="electio5_geekdata",user="electio5_blake", password="dummypassword", host='localhost')
cursor = connection.cursor()
cursor.execute("select st_AsGeoJSON(shape) from boris_constituency limit 1")
varpoly=cursor.fetchall()
geo_json={
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {},
"geometry": varpoly
}
]
}
return render(request ,'map.html', {'geo_json': geo_json})
I notice that the format of the GeoJSON is slightly different when I output it:-
IS FINE
{'type': 'FeatureCollection', 'features': [{'type': 'Feature', 'properties': {}, 'geometry': {'type': 'Polygon', 'coordinates' and so on and so on
IS A PROBLEM
{'type': 'FeatureCollection', 'features': [{'type': 'Feature', 'properties': {}, 'geometry': [('{"type":"MultiPolygon","coordinates" and so on and so on
The problematic GeoJSON has extra brackets and a quote preceding the second "type" key
So my question is:-
1/ Is it possible to reformat the problematic GeoJSON? I had difficulty stripping out the unwanted characters which wrap the list
2/ Or can I extract just the co-ordinates and pass those to the relevant part of geo_json?
3/ Or any way at all I can extract the polygon data from postgis and add it to the leaftlet map
btw you may wonder why I'm using a cursor rather than using the Django model object which has a GeoJSON method. This approach gave me a GDAL error due to the libraries not being properly configured and is a problem for another day!
Big thanks for your attention to this.
Phil #anoobintrouble
I was given the answer by "cabesuon" as you will see in the comments above. But I'll consolidate everything to hopefully help future users.
Here is a way you can extract geometry (polygon) data from a PostGIS database and then render it to a template and add it to a leaflet map using the Django web framework.
The view below extracts the data, converts it to GeoJSON and then returns it to the map.html template:-
from django.shortcuts import render
import json
import psycopg2
def map_view(request, *args, **kwargs):
connection = psycopg2.connect(database="electio5_geekdata",user="electio5_blake", password="adummypassword", host='localhost')
cursor = connection.cursor()
cursor.execute("select name, st_AsGeoJSON(shape) from boris_constituency limit 1")
varcons=cursor.fetchone()
geo_json={
"type": "Feature",
"name": varcons[0],
"properties": {},
"geometry": json.loads(varcons[1])
}
return render(request ,'map.html', {'geo_json': geo_json})
The map template below picks up the geo_json context and adds it to the leaflet map, plotting the polygon geometry (which in this case is the UK parliamentary constituency of "Aldershot"):-
<!DOCTYPE html>
<html>
<head>
<title>Map Page</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.6.0/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet#1.6.0/dist/leaflet.js"></script>
<style>
#map { position: relative;
width: 600px;
height: 775px;
border: 3px solid #000000;}
</style>
</head>
<body>
<div id="map"></div>
<script>
var map = L.map('map').setView([54.8,-4.45],6);
L.tileLayer('https://api.maptiler.com/maps/streets/{z}/{x}/{y}.png?key=9GKOA9jJ3jCIWFUd8k00', {attribution: '© MapTiler © OpenStreetMap contributors',}).addTo(map);
L.geoJSON({{ geo_json | safe }}).addTo(map);
</script>
{{ geo_json }}
</body>
</html>
here is the geometry plotted on the map
A couple of notes:-
1/ I have used pure python to access the database. I really should be using GeoDjango , calling the geometry like so:-
from boris.models import constituency
obj=constituency.objects.get(id=1)
geo_json=obj.shape.geojson
but got a GDAL_ERROR 1: b'PROJ: proj_create_from_database: Cannot find proj.db'
I believe the GDAL library isn't configured properly - I may try and fix this
2/ I now intend to make this application interactive, letting the user select constituencies, regions or finding their constituency based on their location and returning as much interesting information as I can.
Feel free to comment, correct and add anything useful.
Phil #anoobinneed
1.model created
from django.db import models
from django.contrib.gis.db import models
# Create your models here.
class Locate(models.Model):
name=models.CharField(max_length=200)
location =models.PointField(srid=4326)
2.create a geojson in views tobe dispalyed
from django.shortcuts import render
from django.views.generic import TemplateView
from django.core.serializers import serialize
from django.http import HttpResponse
from .models import Locate
# Create your views here.
class HomePageView(TemplateView):
template_name='index.html'
# county views
def locate_datasets(request):
locate=serialize('geojson',Locate.objects.all())
return HttpResponse(locate,content_type='application/json')
3.create a url in your app/urls.py
from django.conf.urls import url
from djgeojson.views import GeoJSONLayerView
from .views import HomePageView,locate_datasets
#create your urls here
urlpatterns=[
url(r'^$',HomePageView.as_view(),name='home'),
url(r'^locate_data/$',locate_datasets,name='locate'),
]
4.template
using geojson ajax to load our data
<!DOCTYPE html>
<html lang="en">
{% load static %}
{% load leaflet_tags %}
<head>
{% leaflet_js %}
{% leaflet_css %}
</head>
<body>
<script>
function our_layers(map,options){
var locate = new L.GeoJSON.AJAX("{% url 'locate' %}",{}).addTo(map);
</script>
{% leaflet_map "map" callback="window.our_layers" %}
</body>
<script src="{% static 'leaflet.ajax.js' %}"></script>
</html>
Hope this solves your problem

Is there some equivalent to {% url 'some-name' %} for router.register(...)

I am trying to get the URL to a specific ViewSet automatically.
I tried using {% url 'api-movement' %} but get the following error:
Reverse for 'api-movement' not found. 'api-movement' is not a valid view function or pattern name.
I searched the web but couldn't really find what I was looking for.
viewset.py
class MovementViewSet(viewsets.ModelViewSet):
queryset = Movement.objects.all()
serializer_class = MovementSerializer
router.py
from farm.api.viewsets import *
from rest_framework import routers
router = routers.DefaultRouter()
router.register('movement', MovementViewSet, base_name='api-movement')
urls.py
from django.urls import path, include
from farm.api.responder import *
from farm import views
from farm.router import router
urlpatterns = [
path('api/', include(router.urls)),
]
html excerpt:
$.ajaxSetup({
headers: { "X-CSRFToken": '{{csrf_token}}' },
});
$.ajax({
method: 'POST',
url: "{% url 'api-movement' %}",
data: {pk: pk},
success: function (data) {
location.reload();
},
error: function (error_data) {
alert('An error occurred, please reload page and try again.\n\nError: ' + error_data.responseText);
}
});

Use differents configs in CKEDITOR with Django

In my Django back end, I have a full toolbar.
However, I want to propose Ckeditor to my users with a minimum of functionnalities.
The problem is, I don't know how to this.
I tried to override my config :
<script type="text/javascript">
CKEDITOR.replace( 'default',
{
toolbar : 'Basic',
});
</script>
But nothing happened, even after removing my browser cache.
This is my Django settings :
CKEDITOR_BASEPATH = "/static/ckeditor/ckeditor/"
CKEDITOR_JQUERY_URL = 'https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js'
CKEDITOR_UPLOAD_PATH = 'uploads/'
CKEDITOR_IMAGE_BACKEND = "pillow"
CKEDITOR_CONFIGS = {
'default': {
'toolbar': 'full',
'height': 500,
'width': 1500,
},
}
Maybe it is not working because in your Django code the settings "CKEDITOR_CONFIGS" for toolbar defined as full.
Also, you can configure toolbar through online builder - https://ckeditor.com/docs/ckeditor4/latest/guide/dev_plugins.html.

how to pass post parameter in Django rest swagger?

I have integrated swagger with django rest framework, but the swagger docs does not create a input box to post data for post request.
I am using Function based views with decorator(#api_view)
#api_view(['GET','POST'])
#permission_classes((AllowAny, ))
#renderer_classes([OpenAPIRenderer, SwaggerUIRenderer])
def preferences(request,format=None):
try:
"logic starts here "
in urls.py i have added:
schema_view = get_swagger_view(title='API')
path('', schema_view, name="schema_view"),
in settings.py :
SWAGGER_SETTINGS = {
'USE_SESSION_AUTH': False,
'JSON_EDITOR': True,
'api_version': '0.1',
'enabled_methods': [
'GET',
'POST',
],
'SECURITY_DEFINITIONS': {
"api_key": {
"type": "apiKey",
"name": "Authorization",
"in": "header"
},
},
}
But, when i open the api url i'm getting something like this (in image) where i'm unable to pass the parameters through post
what can be the problem here?is there any other changes to be done ?
When you click on the Try it Out link, you should get an input to fill in the POST data
make sure the class is imported from the generics API, example:
from rest_framework import generics
class Something (generics.GenericAPIView):
serializer_class=SomeSerializer
def post(self,request):
pass

django tinymce does not show toolbar

i have install django-tinymce and set js url and js root correctly
but as a result it show only a simple text area and doesnt show toolbar and other tinymce features:
from django.db import models
from tinymce import models as tinymce_models
class MyModel(models.Model):
content= HTMLField()
i use this:
self.fields['content'].widget=TinyMCE(attrs={'cols': 80, 'rows': 30})
but this not work too! and it show only a simple text area with 80 cols and 30 rows size.
please help me! what should i do?
Make sure you have added tinymce urls to your urls.py and loaded media resources in your templates like:
<head>
...
{{ form.media }}
</head>
There is my django-tinymce config, add them to your settings.py:
TINYMCE_DEFAULT_CONFIG = {
'theme': 'advanced',
'relative_urls': False,
'plugins': 'media',
'theme_advanced_buttons1': 'bold,italic,underline,bullist,numlist,|,media,link,unlink,image',
'theme_advanced_resizing': True,
'theme_advanced_path': False,
}
You can get more details via reading the docs.