I would like to render an image in html using javascript, and the image is being retrieved from a django view using the fetch api. I think I am close but can't figure out how to display image in browser using javascript.
view #1: (url: builds/imgretrieve/int:device/)
class imgRetrieve(generics.GenericAPIView):
permission_classes = (permissions.IsAuthenticated,)
def get(self, request, *args, **kwargs):
device = self.kwargs['device']
deviceVals = CustomUser.objects.get(id=device)
buildImg = ImageRequest.objects.filter(author = deviceVals).latest("dateAdded")
return FileResponse(buildImg.image)
When I access this view directly using a browser, it displays an image as expected.
However when I want the javascript to display it in a different view, it just displays [object Response] instead of the image.
Here is how I am attempting to do this:
view #2 (url: builds/chamberCam/int:device/)
class chamberCamView(LoginRequiredMixin,TemplateView):
template_name = 'chamberCam.html'
login_url = 'login'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
device = self.kwargs['device']
deviceVals = CustomUser.objects.get(id=device)
CustomUser.objects.filter(id = device).update(imgRequested = True, imgReceived = False,)
context['deviceName'] = deviceVals.UserDefinedEquipName
context['deviceID'] = deviceVals.id
return context
html
{% block body %}
<p hidden id = "id">{{ deviceID }}</p>
<div class="">Chamber cam for {{deviceName}}</div>
<div class="imageDiv" id = "image">
</div>
{% load static %}
<script src="{% static 'camera/chamberCam.js' %}"></script>
{% endblock %}
chamberCam.js
let deviceID = document.getElementById("id").innerHTML;
getImg(deviceID)
function getImg(deviceID){
fetch('http://127.0.0.1:8000/builds/imgretrieve/' + deviceID + '/')
.then(function(res){
return res;
})
.then(function(data) {
let image = document.getElementById("image");
console.log(data)
image.innerHTML = `
<img>${data}</img>
`;
})
.catch(function(err){
console.log(err);
});
}
I was over complicating it..
I replaced the javascript code with:
let deviceID = document.getElementById("id").innerHTML;
addimage(deviceID)
function addimage() {
var img = new Image();
img.src = 'http://127.0.0.1:8000/builds/imgretrieve/' + deviceID + '/'
image.appendChild(img);
}
Related
For my project I need to be able to submit a form through ajax without refreshing the page. I have a model called Post with three fields: animal, image, and description.
here is a picture of my model
class Post(models.Model):
BISON = 'Bison'
WOLF = 'Wolf'
ELK = 'Elk'
BLACKBEAR = 'Black Bear'
GRIZZLY = 'Grizzly Bear'
MOOSE = 'Moose'
MOUNTAINLION = 'Mountain Lion'
COYOTE = 'Coyote'
PRONGHORN = 'Pronghorn'
BIGHORNSHEEP = 'Bighorn Sheep'
BALDEAGLE = 'Bald Eagle'
BOBCAT = 'Bobcat'
REDFOX = 'Red Fox'
TRUMPETERSWAN = 'Trumpeter Swan'
YELLOWBELLIEDMARMOT = 'Yellow-bellied Marmot'
RIVEROTTER = 'River Otter'
LYNX = 'Lynx'
SHREW = 'Shrew'
PIKA = 'Pika'
SQUIRREL = 'Squirrel'
MULEDEER = 'Mule Deer'
SANDHILLCRANE = 'Sandhill Crane'
FLYINGSQUIRREL = 'Flying Squirrel'
UINTAGROUNDSQUIRREL = 'Uinta Ground Squirrel'
MONTANEVOLE = 'Montane Vole'
EASTERNMEADOWVOLE = 'Eastern Meadow Vole'
BUSHYTAILEDWOODRAT = 'Bushy-tailed Woodrat'
CHIPMUNK = 'Chipmunk'
UINTACHIPMUNK = 'Uinta Chipmunk'
WHITETAILEDJACKRABBIT = 'White-tailed Jackrabbit'
BEAVER = 'Beaver'
AMERICANMARTEN = 'American Marten'
MOUNTAINCHICKADEE = 'Mountain Chickadee'
BOREALCHORUSFROG = 'Boreal Chorus Frog'
CUTTHROATTROUT = 'Cutthroat Trout'
GREATHORNEDOWL = 'Great Horned Owl'
SNOWSHOEHARE = 'Snowshoe Hare'
ROCKYMOUNTAINELK = 'Rocky Mountain Elk'
NORTHWESTERNWOLF = 'Northwestern Wolf'
BLACKFOOTEDFERRET = 'Black-footed Ferret'
WOLVERINE = 'Wolverine'
ANIMALS = [
(BISON, ('Bison')),
(WOLF, ('Wolf')),
(ELK, ('Elk')),
(BLACKBEAR, ('Black Bear')),
(GRIZZLY, ('Grizzly Bear')),
(MOOSE, ('Moose')),
(MOUNTAINLION, ('Mountain Lion')),
(COYOTE, ('Coyote')),
(PRONGHORN, ('Pronghorn')),
(BIGHORNSHEEP, ('Bighorn Sheep')),
(BALDEAGLE, ('Bald Eagle')),
(BOBCAT, ('Bobcat')),
(REDFOX, ('Red Fox')),
(TRUMPETERSWAN, ('Trumpeter Swan')),
(YELLOWBELLIEDMARMOT, ('Yellow-bellied Marmot')),
(RIVEROTTER, ('River Otter')),
(LYNX, ('Lynx')),
(SHREW, ('Shrew')),
(PIKA, ('Pika')),
(SQUIRREL, ('Squirrel')),
(MULEDEER, ('Mule Deer')),
(SANDHILLCRANE, ('Sandhill Crane')),
(FLYINGSQUIRREL, ('Flying Squirrel')),
(UINTAGROUNDSQUIRREL, ('Uinta Ground Squirrel')),
(MONTANEVOLE, ('Montane Vole')),
(EASTERNMEADOWVOLE, ('Eastern Meadow Vole')),
(BUSHYTAILEDWOODRAT, ('Bushy-tailed Woodrat')),
(CHIPMUNK, ('Chipmunk')),
(UINTACHIPMUNK, ('Uinta Chipmunk')),
(WHITETAILEDJACKRABBIT, ('White-tailed Jackrabbit')),
(BEAVER, ('Beaver')),
(AMERICANMARTEN, ('American Marten')),
(MOUNTAINCHICKADEE, ('Mountain Chickadee')),
(BOREALCHORUSFROG, ('Boreal Chorus Frog')),
(CUTTHROATTROUT, ('Cutthroat Trout')),
(GREATHORNEDOWL, ('Great Horned Owl')),
(SNOWSHOEHARE, ('Snowshoe Hare')),
(ROCKYMOUNTAINELK, ('Rocky Mountain Elk')),
(NORTHWESTERNWOLF, ('Northwestern Wolf')),
(BLACKFOOTEDFERRET, ('Black-footed Ferret')),
(WOLVERINE, ('Wolverine'))
]
animal = models.CharField(max_length=32, choices=ANIMALS, default=BISON)
image = models.ImageField(upload_to='images', default='static/images/yellowstonelake.jpg')
description = models.TextField(null=True, blank=True)
def __str__(self):
return self.animal
here is a picture of my form.py
class PostForm(ModelForm):
class Meta:
model = Post
fields = '__all__'
here is a picture of my views page
def homePage(request):
form = PostForm()
if request.method == 'POST':
animalType=request.POST['animal']
new_post = Post(animal=animalType)
new_post.save()
context = {'form': form}
return render(request, 'home.html', context)
I believe the problem lies within the javascript I am using to submit my form without refreshing the page. I am able to submit by form successfully, but the data:{...} section within my <script type="text/javascript>... section has to be incorrect? I am referring to line 651 in the following image.
ajax javascript img
<script type="text/javascript">
$(document).on('submit','#post-form',function(e){
e.preventDefault();
$.ajax({
type:'POST',
url:'',
data:
{
animal:$("form").val(),
csrfmiddlewaretoken:$('input[name=csrfmiddlewaretoken]').val(),
},
success:function(data){
alert("success!")
}
})
});
</script>
I need this value to be something other than just:
animal:$("form).val()
since whenever I submit this and go to the backend admin site of my project, I am unable to edit my posts and they are just empty objects within my data base. Ideally I would like this value to be the name of the animal the user selected. I have tried using values such as $("form.model.animal").val() or $("form").val(animal) but i am having no luck.
This is what my back end admin site looks like with a few "successful" submission. Please let me know I you can see where I am making a mistake and how to fix this annoying issue! Thanks!
Admin Posts Page
Form field Template:
const postpopup = new mapboxgl.Popup({ offset: [0, -15] })
.setLngLat([lt, lg])
.setHTML(
`<h1>Yellowmap :) Post Forum</h1>
<div style="margin-left: 40px;">
<form id="post-form">
{% csrf_token %}
{{form}}
<input type="submit"/>
</form>
<p></p>
</div>`
)
Everything in your code is alright,
you just have to change your AJAX code a little bit. and your views.py file.
AJAX
$(document).on('submit', '#post-form', function (e) {
e.preventDefault();
$.ajax({
type: 'POST',
url: "{% url 'insert_form' %}",
data:
{
animal: $("#id_animal").val(),
image: $("#id_image").val(),
description: $("#id_description").val(),
csrfmiddlewaretoken: '{{ csrf_token }}',
},
success: function () {
alert("success!")
}
})
});
views.py
def homePage(request):
form = PostForm()
if request.method == 'POST':
form = PostForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return HttpResponse('')
context = {'form': form}
return render(request, '.html', context)
I am fetching a json response from my django response by this url /inbox/<str:username> to get a json response of all the messages in the conversation with that user.
The problem starts with the inbox page which holds the threads and chatbox on the same page like instagram which looks like this
but as it can be seen that I want the url to be like with the username. Let's say when I click on thread with dummy I want the url to be like "inbox/dummy" but in this my url is "/inbox" which will not let me initiate the socket for messaging, my views.py that renders this inbox template is
views for inbox
thread_objs= Thread.objects.by_user(user=request.user)
l=len(thread_objs)
chat_objs=[]
for i in range(l):
chat_objs.append(list(thread_objs[i].chatmessage_set.all()).pop())
chat_objs_serialized=[]
for i in range(l):
chat_objs_serialized.append(json.dumps(ChatMessageSerializer(chat_objs[i]).data))
for i in range(l):
print(chat_objs_serialized[i])
thread_objs_list=[]
for i in range(l):
thread_objs_list.append(json.dumps(ThreadSerializer(thread_objs[i]).data))
return render(request,'uno_startup/inbox.html',context={"Threads":thread_objs_list,"Messages":chat_objs_serialized})
now when I click a thread it's content should load on the right side of screen as with the javascript of inbox.html that is this page in this image.
javascript of inbox
<body>
<div class='container'>
<div class='row'>
<div class="col-md-4" id ="Threadholder">
<ul id ="Threadbox">
{% for object in threads %}
<li>{% if user != object.first %}{{ object.first }}{% else %}{{ object.second }}{% endif %}</li>
{% endfor %}
</ul>
</div>
<div class="col-md-8" id="Chatholder" >
<ul id="Chatbox">
</ul>
<form id="form" method="POST">
<input type="hidden" value="{{ user.username }}" id="myusername">
<input type="text" id="chat_message">
<input type="submit" class="btn btn-primary">
</form>
</div>
</div>
</div>
<script>
var threads={{ Threads|safe }};
var messages={{ Messages|safe }};
const l=threads.length
const threadholder=$("#Threadbox")
for(i=0;i<l;i++){
var data=JSON.parse(threads[i])
var Message=JSON.parse(messages[i])
var username =data.second.username
if (username=="{{ user.username }}"){
username=data.first.username
}
var thread=document.createElement("li")
var main=document.createElement("a")
var div=document.createElement("div")
var username_holder=document.createElement("p")
div.className="thread"
var p=document.createElement("p")
p.innerText=Message.message
username_holder.innerText=username
div.appendChild(username_holder)
div.appendChild(p)
main.appendChild(div)
thread.appendChild(main)
threadholder.append(thread)
};
function add_message(message){
message=JSON.parse(message)
const chatholder=$("#Chatbox")
console.log(message.user.username)
const chat_message= document.createElement("li")
var div= document.createElement("div")
var p = document.createElement("p")
var sender=message.user.username
var text=message.message
p.innerText=text
div.appendChild(p)
chat_message.appendChild(div)
if(sender=="{{ user.username }}"){
chat_message.className="user"
}
else{
chat_message.className="other"
}
chatholder.prepend(chat_message)
}
$(document).ready(function(){
$("li").click(function(){
$("#Chatbox").empty()
var other_user= this.children[0].children[0].children[0].innerText
fetch(`/inbox/${other_user}`).then(response => response.json())
.then(data => data.messages.reverse().forEach(add_message))
})
})
and this is the function that returns the json response
view for json response
thread=Thread.objects.get_or_new(user=request.user,other_username=username)
messages=thread[0].chatmessage_set.all()
l= len(messages)
messages_serialized=[]
for i in range(l):
messages_serialized.append(json.dumps(ChatMessageSerializer(messages[i]).data))
print(messages)
return JsonResponse({"messages":messages_serialized})
and this Chat function is called via this url /inbox/<str:username>
I want a method that can help me get the thread open without reloading, and updates the url, I have used AJAX but it didn't help as it also took to me the page where it gave me the Json Response from django, changing the original page.
The failed AJAX implementation
<script>
var threads={{ Threads|safe }};
var messages={{ Messages|safe }};
const l=threads.length
const threadholder=$("#Threadbox")
for(i=0;i<l;i++){
var data=JSON.parse(threads[i])
var Message=JSON.parse(messages[i])
var username =data.second.username
if (username=="{{ user.username }}"){
username=data.first.username
}
var thread=document.createElement("li")
var main=document.createElement("a")
var div=document.createElement("div")
var username_holder=document.createElement("p")
div.className="thread"
var p=document.createElement("p")
p.innerText=Message.message
username_holder.innerText=username
div.appendChild(username_holder)
div.appendChild(p)
main.appendChild(div)
thread.appendChild(main)
threadholder.append(thread)
};
function add_message(message){
message=JSON.parse(message)
const chatholder=$("#Chatbox")
console.log(message.user.username)
const chat_message= document.createElement("li")
var div= document.createElement("div")
var p = document.createElement("p")
var sender=message.user.username
var text=message.message
p.innerText=text
div.appendChild(p)
chat_message.appendChild(div)
if(sender=="{{ user.username }}"){
chat_message.className="user"
}
else{
chat_message.className="other"
}
chatholder.prepend(chat_message)
}
$(document).ready(function(){
$("li").click(function(){
$("#Chatbox").empty()
var other_user= this.children[0].children[0].children[0].innerText
<script>
var threads={{ Threads|safe }};
var messages={{ Messages|safe }};
const l=threads.length
const threadholder=$("#Threadbox")
for(i=0;i<l;i++){
var data=JSON.parse(threads[i])
var Message=JSON.parse(messages[i])
var username =data.second.username
if (username=="{{ user.username }}"){
username=data.first.username
}
var thread=document.createElement("li")
var main=document.createElement("a")
var div=document.createElement("div")
var username_holder=document.createElement("p")
div.className="thread"
var p=document.createElement("p")
p.innerText=Message.message
username_holder.innerText=username
div.appendChild(username_holder)
div.appendChild(p)
main.appendChild(div)
thread.appendChild(main)
threadholder.append(thread)
};
function add_message(message){
message=JSON.parse(message)
const chatholder=$("#Chatbox")
console.log(message.user.username)
const chat_message= document.createElement("li")
var div= document.createElement("div")
var p = document.createElement("p")
var sender=message.user.username
var text=message.message
p.innerText=text
div.appendChild(p)
chat_message.appendChild(div)
if(sender=="{{ user.username }}"){
chat_message.className="user"
}
else{
chat_message.className="other"
}
chatholder.prepend(chat_message)
}
$(document).ready(function(){
$("li").click(function(){
$("#Chatbox").empty()
var other_user= this.children[0].children[0].children[0].innerText
$.ajax({
type: "GET",
url: {% url 'Chat' username=other_user %},
data: {'Messages': messages}
})
.done(function(response) {
console.log(reposne)
});
})
})
})
})
Your Django view is reloading the page because it's returning a response of content type HTML instead of, say, JSON.
Instead of
return render(request,'uno_startup/inbox.html',context={"Threads":thread_objs_list,"Messages":chat_objs_serialized})
Do something like
from django.http import JsonResponse
...
return JsonResponse({"Threads": thread_objs_list, "Messages": chat_objs_serialized})
You should still fetch this response from the front-end using JavaScript/AJAX.
As for how to change the URL without inducing a page refresh, refer to this answer.
I have a Django form with Area and Subarea. The subarea input is a ManytoManyField (not every area is a subarea but all subarea is an area), but I have to style it in the frontend, in a way that I can add and remove elements from a text input before I submit the form. I have already implemented a JavaScript function that collects all subareas in an array.
I would like to know how can I pass this array to Django, so it can go to the Subarea field and save it. Is there any possible way?
Django models.py:
class Area(models.Model):
name = models.CharField(max_length=50)
is_subarea = models.BooleanField(default=False)
Subarea = models.ManyToManyField('Area', blank=True)
def __str__(self):
return self.name
Django views.py:
class AddLanguageView(LoginRequiredMixin, CreateView):
model = Area
template_name = 'language/add-language.html'
form_class = LanguageForm
def post(self, request, *args, **kwargs):
area = Area()
area.name = request.POST.get('nome')
area.subarea = request.POST.get('Subarea')
area.save()
return render(request, 'language/add-language.html')
let sublanguageArray = [];
let i = 0;
const addSublanguage = () => {
// Add to array
const sublanguage = document.getElementById("sublanguage-input").value;
sublanguageArray.push({
name: sublanguage,
id: i
});
// Screen Preview
document.querySelector('#sublanguages').innerHTML += `
<div>
<div class="delete-sublanguage">
<img src="/static/assets/delete.png" id-delete="${i}" onclick="deleteSublanguage(this)">
</div>
${sublanguage}
</div>
`;
i++
}
// Delete html preview and from array
const deleteSublanguage = (item) => {
const block = item.parentElement.parentElement;
block.parentNode.removeChild(block);
sublanguageArray = sublanguageArray.filter(sub => sub.id !== +item.getAttribute('id-delete'));
};
<form method="POST" class="add-language-form" >
{% csrf_token %}
<div class="language-title-box" >
<h2>Linguagem:</h2>
{{ form.name }}
</div>
<div class="subarea-box">
<h2>Sub-linguagem</h2>
<input type="text" id="sublanguage-input">
<button id="submit-sublanguage" onclick="addSublanguage()">ADD</button>
<div id="sublanguages"></div>
</div>
<div class="submit-lang-box" >
<input type="submit" value="ADD AREA" id="addLanguageButton" next="partials/base.html">
</div>
</form>
I'm working on a job scheduling app for a REST API and I've created a Tasks, Nodes, URL, Adom, BaseOptions, and Jobs tables in Django. The BaseOptions have a foreign key for src_adom and dst_adom and the Jobs have foreign keys for the Task, src_node, dst_node, url and baseOptions. I didn't use a ModelForm but a generic Form instead and just loaded up the initial values and choices for all the fields I need in order to process a job. I did that because I couldn't figure out how to make the form change when the user selects a different node and want to change the select field for the corresponding adoms. I'm using javascript to detect a new node and changing the select field with the appropriate adoms for that node. I get a validation error if I change the initial source and/or destination node and modify the adom selection list. I know it is because my list of choices have changed from what I initially rendered the form with.
Is there a way to change the choices associated with a ChoiceField during the "clean" method? I can't seem to find that in the documents or digging through the Django code on github.
Models:
FMG = 'FMG'
FOS = 'FOS'
NODE_TYPE_CHOICES = (
(FMG, 'FMG'),
(FOS, 'FOS'),
)
# Create the types of tasks to run
class TaskType(models.Model):
name = models.CharField(max_length=200)
command = models.CharField(max_length=200)
node_type = models.CharField(max_length=60, choices=NODE_TYPE_CHOICES, default=FMG)
def __str__(self):
return self.name
# Create the nodes for tasks to be run on
class Node(models.Model):
ip = models.GenericIPAddressField(protocol='IPv4')
name = models.CharField(max_length=200)
apiname = models.CharField(max_length=200)
apikey = EncryptedCharField(max_length=200)
node_type = models.CharField(max_length=60, choices=NODE_TYPE_CHOICES, default=FMG)
def __str__(self):
return "{0} ({1})".format(self.name, self.ip)
class FMG_URLManger(models.Manager):
def get_queryset(self):
return super(FMG_URLManger, self).get_queryset().filter(node_type='FMG')
class FOS_URLManger(models.Manager):
def get_queryset(self):
return super(FOS_URLManger, self).get_queryset().filter(node_type='FOS')
class NodeURL(models.Model):
name = models.CharField(max_length=200)
node_type = models.CharField(max_length=60, choices=NODE_TYPE_CHOICES, default=FMG)
table_id = models.CharField(max_length=100)
table_url = models.CharField(max_length=200)
help_text = models.CharField(max_length=400, null=True)
filename = models.CharField(max_length=200)
objects = models.Manager()
fmg_objects = FMG_URLManger()
fos_objects = FOS_URLManger()
def __str__(self):
return self.name
class Adom(models.Model):
name = models.CharField(max_length=200)
version = models.CharField(max_length=60)
fmg = models.ForeignKey(Node, related_name='fmgs', on_delete=models.CASCADE)
class Meta:
unique_together = (("name", "version", "fmg"),)
def __str__(self):
return self.name
class BaseOption(models.Model):
src_adom = models.ForeignKey(Adom, related_name="src_adom", on_delete=models.CASCADE)
dst_adom = models.ForeignKey(Adom, related_name="dst_adom", on_delete=models.CASCADE, null=True)
name_filter = models.CharField(max_length=100, null=True)
site_name_filter = models.CharField(max_length=100, null=True)
policy_id_list_filter = models.CharField(max_length=60, null=True)
keep_policy_id = models.BooleanField(default=False)
disable_policy = models.BooleanField(default=False)
import_only = models.BooleanField(default=False)
def __str__(self):
return self.src_adom.name
# Create the actual request for jobs
class Job(models.Model):
UNKNOWN = 'Unknown'
PENDING = 'Pending'
SUCCESS = 'Success'
FAILURE = 'Failure'
STATUS_CHOICES = (
(UNKNOWN, 'Unknown'),
(PENDING, 'Pending'),
(SUCCESS, 'Success'),
(FAILURE, 'Failure'),
)
description = models.CharField(max_length=400)
task = models.ForeignKey(TaskType, related_name='job_task', on_delete=models.CASCADE)
src_node = models.ForeignKey(Node, related_name='src_node', on_delete=models.CASCADE)
urls = models.ManyToManyField(NodeURL)
dst_node = models.ForeignKey(Node, related_name='dst_node', on_delete=models.CASCADE)
user = models.ForeignKey(User, related_name='jobs', on_delete=models.CASCADE)
opts = models.OneToOneField(BaseOption, related_name='job', on_delete=models.CASCADE)
created = models.DateTimeField(auto_now_add=True)
run_at = models.DateTimeField(editable=True, default=timezone.now)
start = models.DateTimeField(editable=True, null=True)
finished = models.DateTimeField(editable=True, null=True)
status = models.CharField(max_length=12, choices=STATUS_CHOICES, default=UNKNOWN, editable=True)
status_text = models.TextField(editable=True, null=True)
file_location = models.CharField(max_length=4086, editable=True, null=True)
objects = models.Manager()
def __str__(self):
return self.description
The ScheduleFormView:
class ScheduleView(LoginRequiredMixin, generic.FormView):
login_url = '/login/'
redirect_field_name = 'redirect_to'
template_name = 'tools/schedule.html'
form_class = ScheduleJobForm
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
print("Got a POST request, checking for valid...")
if form.is_valid():
# <process form cleaned data>
taskID_nodeType = form.cleaned_data['task']
description = form.cleaned_data['description']
src_nodeID_name = form.cleaned_data['src_node']
dst_nodeID_name = form.cleaned_data['dst_node']
urlsID_tableID = form.cleaned_data['urls']
src_adomID = form.cleaned_data['src_adom']
dst_adomID = form.cleaned_data['dst_adom']
name_filter = form.cleaned_data['name_filter']
site_name_fiter = form.cleaned_data['site_name_fiter']
policy_id_list_filter = form.cleaned_data['policy_id_list_filter']
taskID = taskID_nodeType.split('.')[0]
src_nodeID = src_nodeID_name.split('.')[0]
dst_nodeID = dst_nodeID_name.split('.')[0]
# urlsID_tableID was a list, now it's a single URL
# urlIDs = []
# for urlID_tableID in urlsID_tableID:
# urlID = urlID_tableID.split('.')[0]
# print("Got back id {}".format(urlID))
# urlIDs.append(urlID)
urlID = urlsID_tableID.split('.')[0]
urls = NodeURL.objects.filter(id=urlID)
# print("List of URLS = {}".format(urls))
src_node = Node.objects.get(id=src_nodeID)
dst_node = Node.objects.get(id=dst_nodeID)
task = TaskType.objects.get(id=taskID)
src_adom = Adom.objects.get(id=src_adomID)
dst_adom = Adom.objects.get(id=dst_adomID)
job = Job(description=description,
task=task,
src_node=src_node,
dst_node=dst_node,
user=request.user)
opts = BaseOption(src_adom=src_adom,
dst_adom=dst_adom,
name_filter=name_filter,
site_name_filter=site_name_fiter,
policy_id_list_filter=policy_id_list_filter)
opts.save()
job.opts = opts
job.save()
for url in urls:
url.job_set.add(job)
return HttpResponseRedirect('job-list.html')
else:
print("The form was not valid. Return for more processing.")
return render(request, self.template_name, {'form': form})
The ScheduleJobForm (with my unfinished code for 'clean'):
class ScheduleJobForm(forms.Form):
def clean(self):
print("Don't actually check for on src_adom.")
cleaned_data = super(ScheduleJobForm, self).clean()
print(cleaned_data)
adom = self.cleaned_data.get("src_adom")
print(adom)
# if adom < 1:
# raise forms.ValidationError("You didn't choose a valid ADOM.")
print("Don't actually check for on dst_adom.")
cleaned_data = super(ScheduleJobForm, self).clean()
adom = self.cleaned_data.get("dst_adom")
print(adom)
# if adom < 1:
# raise forms.ValidationError("You didn't choose a valid ADOM.")
initTasks = []
selectedNodeType = ''
# Get the first node_type because it will be the default selection of tasks.
for task in TaskType.objects.all().filter(node_type='FMG').order_by('id'):
if selectedNodeType == '':
selectedNodeType = task.node_type
taskChoice = str(task.id) + '.' + task.node_type, task.name
initTasks.append(taskChoice)
# Fill in the initial Nodes for the selected task above.
initNodes = []
selectedNodeID = 0
for node in Node.objects.all().filter(node_type=selectedNodeType).order_by('id'):
nodeChoice = str(node.id) + '.' + node.name, node.name + ' (' + node.ip + ')'
if selectedNodeID == 0:
selectedNodeID = node.id
initNodes.append(nodeChoice)
# Also grab the URL's for those node types and fill them in.
initURLs = []
for url in NodeURL.objects.all().filter(node_type=selectedNodeType).order_by('table_id'):
urlChoice = str(url.id) + '.' + url.table_id, url.name
initURLs.append(urlChoice)
# Since we've got the first node selected, then all the ADOMs are the same. Get them.
initAdoms = []
for adom in Adom.objects.all().filter(fmg_id=selectedNodeID).order_by('id'):
adomChoice = adom.id, adom.name
initAdoms.append(adomChoice)
# Add some hidden fields for the jQuery script to examine.
selected_node_type = forms.CharField(initial=selectedNodeType, widget=forms.HiddenInput)
# After this, a jQuery will have to keep the select fields updated if they are changed.
task = forms.ChoiceField(choices=initTasks)
description = forms.CharField()
src_node = forms.ChoiceField(choices=initNodes)
dst_node = forms.ChoiceField(choices=initNodes)
urls = forms.ChoiceField(choices=initURLs)
# These fields will have to be updated by the jQuery to get the available ADOMS for the selected
# Nodes. We also have to create a custom validator since the choices will change via the JS.
src_adom = forms.ChoiceField(choices=initAdoms)
dst_adom = forms.ChoiceField(choices=initAdoms)
name_filter = forms.CharField()
site_name_fiter = forms.CharField()
policy_id_list_filter = forms.CharField()
The schedule.js script that modifies the adoms:
/*
Of cource, I could use the following but I think the code below is
a bit more readable.
$(function(){
initPage();
}
); */
const coreapi = window.coreapi
const schema = window.schema
$(document).ready(function(){
initPage();
}
);
function initPage() {
console.log("Adding the change code.")
// Fill in the initial srcAdom
getSrcAdom()
// and the initial dstAdom
getDstAdom()
// Hide the wait icon
$('.loading').hide();
$('#id_task').change(
function() {
var currentNodeType = $('#id_selected_node_type').val();
var selectedOption = $('#id_task option:selected').val();
var selectedNodeType = selectedOption.split(".").pop();
if (currentNodeType != selectedNodeType) {
// The more I look at the options, I think this will have to be locked
// into FMG only nodes and create another form for just FOS nodes.
}
}
);
$('#id_src_node').change(
function() {
// Need to change the src adoms
$('.loading').show();
getSrcAdom()
$('.loading').hide();
}
);
$('#id_dst_node').change(
function() {
// Need to change the src adoms
$('.loading').show();
getDstAdom()
$('.loading').hide();
}
);
}
function getSrcAdom() {
var selectedOption = $('#id_src_node option:selected').val();
var selectedNodeName = selectedOption.split(".").pop();
// Clear the src adom options.
$('#id_src_adom')
.find('option')
.remove();
// Initialize a client
var client = new coreapi.Client()
// Interact with the API endpoint
var action = ["adom", "list"]
var params = {
search: selectedNodeName,
}
client.action(schema, action, params).then(function(result) {
// Return value is in 'result'
$.each(result, function(index, obj) {
$('#id_src_adom')
.append('<option value="' + obj["id"] + '">' + obj["name"] + '</option>');
console.log(index + " got '" + obj["name"] + "' (id: " + obj["id"] + ")");
})
})
}
function getDstAdom() {
var selectedOption = $('#id_dst_node option:selected').val();
var selectedNodeName = selectedOption.split(".").pop();
// Clear the src adom options.
$('#id_dst_adom')
.find('option')
.remove();
// Initialize a client
var client = new coreapi.Client()
// Interact with the API endpoint
var action = ["adom", "list"]
var params = {
search: selectedNodeName,
}
client.action(schema, action, params).then(function(result) {
// Return value is in 'result'
$.each(result, function(index, obj) {
$('#id_dst_adom')
.append('<option value="' + obj["id"] + '">' + obj["name"] + '</option>');
console.log(index + " got '" + obj["name"] + "' (id: " + obj["id"] + ")");
})
})
}
function createNodeSelect(data) {
// This was to clear all selected nodes and list new node types.
// It's not going to be used in this form at this time.
// Need to determine data format from JSON return.
// Leaving for future code example of how to clear options
// and replace it with a single option.
$('#id_src_node')
.find('option')
.remove()
.end()
.append('<option value="whatever">text</option>')
.val('whatever');
}
The schedule.html template (with Bootstrap 4 tags):
{% extends "tools/base_site.html" %}
{% block extra_js %}
{% load static %}
<script src="{% static 'rest_framework/js/coreapi-0.1.1.js' %}"></script>
<script src="{% url 'api-docs:schema-js' %}"></script>
<script src="{% static 'js/schedule.js' %}"></script>
{% endblock %}
{% block content %}
<div id="content-main">
<br>
{% block loading %}
{% load static %}
<div id="loading" class="loading">
<img src="{% static 'images/spinning-wait-icons/wait30.gif' %}" alt="Wait" />
<!-- <h3>Loading Data from Server</h3> -->
</div>
{% endblock %}
{% load widget_tweaks %}
{% if form.errors %}
<div class="alert alert-primary">
<button type="button" class="close" data-dismiss="alert">×</button>
{% for field in form %}
{% if field.errors %}
<li>{{ field.label }}: {{ field.errors|striptags }}</li>
{% endif %}
{% endfor %}
</div>
{% endif %}
<form method="post">
{% csrf_token %}
{% for hidden_field in form.hidden_fields %}
{{ hidden_field }}
{% endfor %}
{% for field in form.visible_fields %}
<div class="form-group">
{{ field.label_tag }}
{% render_field field class="form-control" %}
{% if field.help_text %}
<small class="form-text text-muted">{{ field.help_text }}</small>
{% endif %}
</div>
{% endfor %}
<button type="submit" class="btn btn-primary">Schedule</button>
</form>
</div>
{% endblock %}
I must confess I didn't go through all the code (it's quite a lot), but at a first glance it looks to me as you should move the initialization of your choices (intTasks, initNodes...) into the __init__ method of your FormClass (ScheduleJobForm).
Because you want the code to be run when you instantiate the class, not when you load the module, right?
So:
class ScheduleJobForm(forms.Form):
selected_node_type = forms.CharField(initial=selectedNodeType, widget=forms.HiddenInput)
task = forms.ChoiceField(choices=initTasks)
# further fields
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# initialize initNodes and the rest
self.fields["src_node"]=initNodes
# and resp.
The form does not care about Javascript, as it is instantiated in the post request after all the Javascript magic on the frontend.
So there doesn't have to (and cannot) be any interaction between Javascript and your form.
I was able to figure out how to dynamically change the choices by using the getter and setter property of ChoiceField (see github repo).
The change I made was in the ScheduleJobForm view. I added these additional lines before calling 'is_valid':
print("Got a POST request, checking for valid...")
print("Fix the choices in the ADOMs first.")
src_nodeID_name = form['src_node'].value()
dst_nodeID_name = form['dst_node'].value()
src_nodeID = src_nodeID_name.split('.')[0]
dst_nodeID = dst_nodeID_name.split('.')[0]
srcAdoms = []
for adom in Adom.objects.all().filter(fmg_id=src_nodeID).order_by('id'):
adomChoice = adom.id, adom.name
srcAdoms.append(adomChoice)
dstAdoms = []
for adom in Adom.objects.all().filter(fmg_id=dst_nodeID).order_by('id'):
adomChoice = adom.id, adom.name
dstAdoms.append(adomChoice)
form.fields['src_adom'].choices = srcAdoms
form.fields['dst_adom'].choices = dstAdoms
For efficiency, I should probably check changed_data and see if the ADOM's have actually changed or not.
this is my code:
class Marker_latlng(db.Model):
geo_pt = db.GeoPtProperty()
class Marker_info(db.Model):
info = db.StringProperty()
marker_latlng =db.ReferenceProperty(Marker_latlng)
class BaseRequestHandler(webapp.RequestHandler):
def render_template(self, filename, template_values={}):
values={
}
template_values.update(values)
path = os.path.join(os.path.dirname(__file__), 'templates', filename)
self.response.out.write(template.render(path, template_values))
class HomePage(BaseRequestHandler):
def get(self):
q = Marker_latlng.all()
q.filter("info =", "sss")
self.render_template('3.1.html',{'datas':q})
and the 3.1.html is :
var marker_data=[];
{% for i in datas %}
marker_data.push([{{db.Key(i.marker_latlng).geo_pt}}])
{% endfor %}
but the error is :
TemplateSyntaxError: Could not parse the remainder: (i.marker_latlng).geo_pt
so ,what can i do ?
thanks
Did you mean:
q = Marker_info.all()
q.filter("info =", "sss")
?
Maybe try this:
marker_data.push([{{i.marker_latlng.geo_pt}}])
Or maybe:
marker_data.push([{{i.marker_latlng.geo_pt.lat}}, {{i.marker_latlng.geo_pt.lon}}])