cant get ndb query results - html

i just started learning python ndb i want to know how can i display students attending a selected course (filtering Attendance) then mark their attendance with a ardio button for each student,add the attendance value to the preveious one and finally save the result back to the datastore or print it to file
# -- coding: cp1256 --
import webapp2
import os
import cgi
from google.appengine.ext import ndb
from google.appengine.api import users
from google.appengine.api import mail
from google.appengine.ext.webapp import template
class Student(ndb.Model):
id = ndb.IntegerProperty()
name = ndb.StringProperty()
email = ndb.StringProperty()
#courses= ndb.StructuredProperty(Courses, repeated=True) and attendance
class Course(ndb.Model):
code=ndb.StringProperty()
title=ndb.StringProperty()
#time=ndb.TimeProperity
#students= ndb.StructuredProperty(Students, repeated=True)
#attendance
class Attendance(ndb.Model):
courseCode=ndb.StructuredProperty(Course)
#course=ndb.StructuredProperty(Course, repeated=True)
date=ndb.StringProperty()
#studentID=ndb.IntegerProperty(repeated=True)
student=ndb.StructuredProperty(Student, repeated=True)
attendance=ndb.IntegerProperty(repeated=True)# for each student
class MainHandler(webapp2.RequestHandler):
def get(self):
#cerate ndb from file
coursesfile = open('courses.txt', 'r').read()
studentsfile = open('students.txt', 'r').read()
dailyattendancefile = open('dailyattendance.txt','r').read()
for line in coursesfile.split('\n'):
line=coursesfile.split('\t')
#stroe courses to datastore
course=Course(code=line[0],title=line[1])#create Course entity
course.put()
for line in studentsfile.split('\n'):
line=studentsfile.split('\t')
student=Student(id=int(line[0]),name=line[1],email=line[2])
student.put()
for line in dailyattendancefile.split('\n'):
line=dailyattendancefile.split('\t')
attendance=Attendance(courseCode=Course(code=line[0]),date=line[1],student=Student(id=int(line[2])),attendance=int(line[3]))
attendance.put()
#print to html to test
#self.response.out.write("<tr><td>"+ course.code + "</td>")
#self.response.out.write("<td>"+ course.title+ "</td>")
#self.response.out.write("</tr>")
self.response.out.write("""
<html>
<body>
<form method="post" align="left">
<select align="center" name="course_code">
<option value="cs681" selected>CS681</option>
<option value="cs681">CS611</option>
</select>
<input type="submit" value="Submit"/>
""")
def post(self):
#get info from user
coursecode=self.request.get('course_code')
#self.response.out.write(Attendance.courseCode.code)
self.response.out.write("""
<table align="center" >
<tr align="center">
<td>Course code</td>
<td>Student ID</td>
<td>Date</td>
<td>Attendance</td>
</tr>
""")
qry=Attendance.query(Attendance.courseCode.code==coursecode).fetch()
for ent in qry:
self.response.out.write('<tr><td>%s</td></tr>' %ent.courseCode)
self.response.out.write("""
</table>
</form>
</body>
</html>
""")
app = webapp2.WSGIApplication([
('/', MainHandler)
], debug=True)

Try the following. I think you have a minor issue in your schema definition.
class Course(ndb.Model):
code=ndb.StringProperty(indexed=True)
title=ndb.StringProperty()

Related

Django SQLAlchemy engine issue - data not transferred to db using Pandas

My use case is to take excel data and load it to database.. I am using SQLAlchemy (with Pandas df) to do that, but am not able to do.. When I try with ORM bulk_create, it works, suggesting to me that Django side of stuff (eg template, url, view, model connections) is working fine, and there could be some issue in defining the Alchemy engine??
I need help from you to debug and resolve this.. My code details are as below.. Please note I dont get any errors in vscode terminal, its just that when I click on Add/ replace button, the data does not transfer.. Appreciate your help.. many thanks..
SQLAlchemy engine details (saved in engine.py)
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from django.conf import settings
engine = create_engine('postgresql://' +
settings.DATABASES['default']['USER'] + ':' +
settings.DATABASES['default']['PASSWORD'] + '#' +
settings.DATABASES['default']['HOST'] + ':' +
str(settings.DATABASES['default']['PORT']) + '/' +
settings.DATABASES['default']['NAME'])
Session = sessionmaker(bind=engine)
session = Session()
views.py
from .models import Industry
from .engine import engine, session
import pandas as pd
def industry_import_replace(request):
df = pd.read_excel('Industry.xlsx')
df.to_sql('Industry', engine, if_exists='replace', index=False)
return render(request, 'portfolio/partials/imports/industry-import.html',{})
template (html)
<form method="post">
<div class="row">
<div class="col col-md-4 col-lg-4">
<table class="table">
<thead>
<tr>
<th scope="col-md-4 col-lg-4">Imports</th>
<th scope="col-md-4 col-lg-4"> </th>
<th scope="col-md-4 col-lg-4"> </th>
</tr>
</thead>
<tbody>
<tr>
<th scope="col-md-4 col-lg-4">Industry</th>
<td>
<button type="submit" name="action" value="replace" class="btn btn-danger"
hx-post="{% url 'portfolio:industry-import-replace' %}" hx-target="#imports">Add/ Replace</button>
</td>
<td>
<button type="submit" name="action" value="append" class="btn btn-success"
hx-post="{% url 'portfolio:industry-import-append' %}" hx-target="#imports">Append</button>
</td>
</tr>
</tbody>
<div id="imports"></div>
</div>
excel file data
Stored right at the top; no row headers etc..
ID industry_name
Ind1
Ind2
Ind3
Industry model file
class Industry(models.Model):
industry_name = models.CharField(max_length=100, unique=True)
class Meta:
verbose_name_plural = 'Industry'
def __str__(self):
return self.industry_name

Cannot able to display data from database in Django 1.10?

I am new to django and i cannot able to display data from postgres database, i have following data in my database,
Data in products Table
1 "test" "images.jpg" 1
3 "sample" "images.jpg" 2
and my code is ,
views.py
from django.shortcuts import render
from products.forms import productsform
from django.http import HttpResponseRedirect
from django.http import HttpResponse
from products.models import products
def productsview(request):
if request.method == 'POST':
form = productsform(request.POST)
if form.is_valid:
name = request.POST.get('name')
image = request.POST.get('image')
code = request.POST.get('code')
products_obj = products(name=name,image=image,code=code)
products_obj.save()
return HttpResponse("Register Successfull")
else:
form = productsform()
return render(request,'products/products_view.html',{'form':form,})
def display(request):
query_results = products.objects.all()
return render(request, 'products/myview.html')
urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.productsview, name='products'),
url(r'^display', views.display, name='display'),
]
models.py
from __future__ import unicode_literals
from django.db import models
class products(models.Model):
name = models.CharField(max_length=15,unique=True)
image = models.ImageField(upload_to = 'pictures')
code = models.IntegerField()
myview.html
<table>
<tr>
<th>Name</th>
<th>Code</th>
</tr>
{% for item in query_results %}
<tr>
<td>{{ item.name }}</td>
<td>{{ item.code }}</td>
</tr>
{% endfor %}
</table>
You're not sending the data to the view from the display function.
return render(request, 'products/myview.html', {'query_results': query_results})
You forgot passing the model to the template. In you views.py file, do the following:
def display(request):
query_results = products.objects.all()
return render(request, 'products/myview.html', {'query_results': query_results})

Django: can "double" 'render_to_response' be unified into only one view?

I have defined two functions in views.py to obtain first prova.html with certain elementimenu and then, after clicking over one of them, I obtain again the page with elementimenu and elementi associated to elementimenu with the same id i.e.:
another_app.model.py
...
class ElementiTab(models.Model):
author = models.ForeignKey('auth.User', null=True, blank=False)
des = models.CharField(max_length=30)
x = models.FloatField()
y = models.FloatField()
res = models.FloatField(default=0)
created_date = models.DateTimeField(default=timezone.now)
...
And here the code that I like to get better:
views.py
from another_app.model import ElementiTab
def show_elementi(request):
elementimenu = ElementiTab.objects.all()
return render_to_response('homepage/prova.html',{'elementimenu': elementimenu, 'user.username': request}, context_instance = RequestContext(request))
def show_detail(request,id):
elementimenu = ElementiTab.objects.all()
detail = get_object_or_404(ElementiTab, pk=id)
return render_to_response('homepage/prova.html',{'elementimenu': elementimenu, 'detail': detail, 'user.username': request}, context_instance = RequestContext(request))
urls.py
...
url(r'^homepage/prova/$', views.show_elementi),
url(r'^show_detail/(?P<id>\d+)/$', views.show_detail),
...
prova.html
...
<div class="elementi">
{% for elementi in elementimenu %}
{{elementi.des}}
{% endfor %}
</div>
<div class="table-responsive">
<table class="table table-bordered">
<tr class="info">
<td width="35%" align="center"> NOME</td>
<td width="35%" align="center"> DATA CREAZIONE </td>
<td width="30%" align="center"> AUTORE </td>
</tr>
{% if detail %}
<div class="dettagli">
<tr>
<td>{{detail.des}}</td>
<td>{{detail.created_date}}</td>
<td>{{detail.author}}</td>
</tr>
{% endif %}
</div>
</table>
</div>
...
I had used this "trick" in show_detail view so that I can see elementimenu even after calling this function.
Is there a more elegant way to do this?
Yes, you can use the single view. Add the default None value for the id (or pk) argument:
def show_elementi(request, pk=None):
elementimenu = ElementiTab.objects.all()
detail = get_object_or_404(ElementiTab, pk=pk) if pk else None
return render(request, 'homepage/prova.html',
{'elementimenu': elementimenu, 'detail': detail})
And then map both urls to this view:
url(r'^homepage/prova/$', views.show_elementi),
url(r'^show_detail/(?P<pk>\d+)/$', views.show_elementi),

Scraping a forum page with Beautiful Soup 4 -- csv file ends up empty

I'm trying to scrape a bunch of HTML files for a research project, and it's not working. The csv file ends up empty, except the four column names, and I'm not sure what I'm doing wrong. I've done a similar scraping job once before, but this website's html seems messier (or perhaps the other was unusually clean).
I hope someone out there can help, and please forgive the code I've written -- I don't have much experience.
from bs4 import BeautifulSoup
import csv
import urllib2
import os
def processData( pageFile ):
f = open(pageFile, "r")
page = f.read()
f.close()
soup = BeautifulSoup(page)
one = soup.findAll("td", attrs={"class":"t_user"})
two = soup.findAll("div", attrs={"class":"right t_number"})
three = soup.findAll("div", attrs={"style":"font-size: 9pt"})
four = soup.findAll("div", atrs={"style":"padding-top: 4px;"})
names = []
threads = []
posts = []
timestamps = []
for html in one:
names.append(BeautifulSoup(str(name)).get_text().encode("utf-8").strip())
for html in two:
threads = BeautifulSoup(str(thread).strip()).get_text().encode("utf-8").replace("\n", "")
for html in three:
posts = BeautifulSoup(str(post).strip()).get_text().encode("utf-8").replace("\n", "")
for html in four:
text = BeautifulSoup(str(html).strip()).get_text().encode("utf-8").replace("\n", "")
timestamps.append(text.split("Post at:")[1].strip())
csvfile = open('S141test.csv', 'ab')
writer = csv.writer(csvfile)
for name, thread, post, timestamp in zip(names, threads, posts, timestamps):
writer.writerow([name, thread, post, timestamp])
csvfile.close()
dir = "S141test"
csvfile = "S141test.csv"
csvfile = open(csvfile, 'wb')
writer = csv.writer(csvfile)
writer.writerow(["Name", "thread", "post", "timestamp"])
csvfile.close()
# get a list of files in the directory
fileList = os.listdir(dir)
# define variables we need for status text
totalLen = len(fileList)
count = 1
# iterate through files and read all of them into the csv file
for htmlFile in fileList:
path = os.path.join(dir, htmlFile) # get the file path
processData(path) # process the data in the file
print "Processed '" + path + "'(" + str(count) + "/" + str(totalLen) + ")..." # display status
count = count + 1 # incriment counter
The html I'm trying to scrape: (the stuff I want to scrape is highlighted in capital letters, look for AUTHOR NAME, THREAD TITLE, TIMESTAMP, POST CONTENT).
HTML S141
<div class="maintable">
<div class="spaceborder" style="width: 100%; border-bottom: none">
<table cellspacing="1" cellpadding="4" width="100%" align="center">
<tr class="header"><td colspan="2" style="color: #000000">
<div class="right" style="font-weight: normal">
Email to Friend |
Subscription |
Favorites
</div>
Subject:
Ayuki - TST HG</td></tr>
</table></div>
<form method="post" name="delpost" action="topicadmin.php?action=delpost&fid=28&tid=50510&page=1">
<input type="hidden" name="formhash" value="66b6dc45">
<div class="spaceborder" style="width: 100%; margin-bottom: 4px;
border-top: none
">
<table cellspacing="1" cellpadding="4" width="100%" align="center" class="t_row">
<tr style="height: 100%">
<td width="18%" valign="top" class="t_user"> <a name="lastpost"></a>asta (AUTHOR NAME)
<br><div class="smalltxt">
Carnal Conqueror<br>
<img src="images/website141.COM/star_level2.gif" alt="Rank: 3" /><img src="images/website141.COM/star_level1.gif" alt="Rank: 3" /><br>
<br>
<br><br>
UID 7455<br>
Digest Posts
0<br>
Credits 328<br>
Posts 28<br>
Karma 327 <br>
Money 156 <br>
Acceptance 25 <br>
Reading Access 30<br>
Registered 20-1-2008<br>
Status Offline
</div>
</td>
<td width="82%" valign="top" style="padding: 0px">
<table border="0" cellspacing="0" cellpadding="4" class="t_msg">
<tr><td>
<div>
<div class="right t_number">#1</div>
<div style="padding-top: 4px;">
Post at 26-6-2014 00:20 (TIMESTAMP)
Profile
P.M.
</div></div>
</td></tr>
<tr><td valign="top" class="line" height="100%" style="padding-top: 10px;">
<a name="pid502926" href="misc.php?action=viewratings&tid=50510&pid=502926" title="[Rating] 29"><img src="images/website141.COM/agree.gif" border="0" align="right" alt="" /><img src="images/website141.COM/agree.gif" border="0" align="right" alt="" /><img src="images/website141.COM/agree.gif" border="0" align="right" alt="" /></a>
<div class="right t_number">Font size:
<a style="cursor:hand" onclick="text502926.style.fontSize='9pt';">S</a>
<a style="cursor:hand" onclick="text502926.style.fontSize='12pt';">M</a>
<a style="cursor:hand" onclick="text502926.style.fontSize='15pt';">L</a></div>
<span class="bold" style="color: #999999">Ayuki - TST HG (THREAD TITLE) </span><br><br>
<div style="font-size: 9pt" id=text502926>http://go141.com/en/27120-Tsim%2 ... ls%20-%20Ayuki.html<br />
<br />
Do I recommend her ? It depends what you are looking for.
<br />
I asked to take a photo but she didn't allow. (POST CONTENT) </div>
<br><fieldset><legend>Recent Ratings</legend><br>
<table border="0" cellspacing="0" cellpadding="0">
<tr><td>banter141a</td>
<td> 2-7-2014 13:31</td><td> Karma</td><td> <b>+3</b></td>
<td> </td></tr>
<tr><td>hlau</td>
<td> 28-6-2014 00:36</td><td> Karma</td><td> <b>+6</b></td>
I figured it out on my own. I'm not sure whether to delete the question or answer it with my own solution, but I'm going for the latter in case someone else has a very similar problem. One key mistake was that I confused csvfile with csvFile (I needed to use both in distinct ways, as seen in the code below).
from bs4 import BeautifulSoup
import csv
import urllib2
import os
def processData( pageFile ):
f = open(pageFile, "r")
page = f.read()
f.close()
soup = BeautifulSoup(page)
one = soup.findAll('td', attrs={"width": "18%"}) #close
two = soup.findAll("span", attrs={"style":"color: #999999"}) #close
three = soup.findAll("div", attrs={"style":"font-size: 9pt"}) #works
four = soup.findAll("div", attrs={"style":"padding-top: 4px;"})
names = []
threads = []
posts = []
timestamps = []
print four
for html in one:
text = BeautifulSoup(str(html).strip()).get_text().encode("utf-8").replace("\n", " ")
names.append(text.split('UID')[0].strip()) #works, at the moment
for color in two:
text2 = BeautifulSoup(str(color).strip()).get_text().encode("utf-8").replace("\n", "")
threads.append(text2.strip())
for html in three:
text3 = BeautifulSoup(str(html).strip()).get_text().encode("utf-8").replace("\n", "").replace(" ", "")
posts.append(text3.strip())
for html in four:
text4 = BeautifulSoup(str(html).strip()).get_text().encode("utf-8").replace("\n", "").replace(" ", "")
timestamps.append(text4.split("Post at")[1].split('Profile')[0].strip())
csvfile = open('S141test.csv', 'ab')
writer = csv.writer(csvfile)
for name, thread, post, timestamp in zip(names, threads, posts, timestamps):
writer.writerow([name, thread, post, timestamp])
csvfile.close()
dir = "S141test"
csvFile = "S141test.csv"
csvfile = open(csvFile, 'wb')
writer = csv.writer(csvfile)
writer.writerow(["Name", "thread", "post", "timestamp"])
csvfile.close()
# get a list of files in the directory
fileList = os.listdir(dir)
# define variables we need for status text
totalLen = len(fileList)
count = 1
# iterate through files and read all of them into the csv file
for htmlFile in fileList:
path = os.path.join(dir, htmlFile) # get the file path
processData(path) # process the data in the file
print "Processed '" + path + "'(" + str(count) + "/" + str(totalLen) + ")..." # display status
count = count + 1 # incriment counter

How can I take input from a text field in a Django page then update a SQL table with the response?

I am working on a site that will be used to clean up inactive Tableau workbooks. Logging into this site will allow my users to see their old workbooks and decide which ones to keep.
This is going to be accomplished by taking some simple text input from an HTML page, K for keep | D for delete.
The response from the user will then be stored as a Python variable that will go into an if then statement. The if then statement will basically update each row in SQL, adding either K or D to a column called "Marked_for_Deletion".
From there, a stored procedure will run, check that column, and delete all things marked with a D.
Is this feasible? If so, how would I go about pulling that input and making sure it gets added to the right column/row? If not, can you offer any suggestions on a substitute method I can use?
Thanks!
Edit: Here is the code for my table.
<table class="blueTable">
<thead>
<tr>
<th>Workbook Name</th>
<th>Deletion Deadline</th>
<th>Keep or Delete?</th>
</tr>
</thead>
<tbody>
{% for book in Workbooks %}
<tr>
<td>{{ book.name }}</td>
<td>{{ book.owner_name }}</td>
<td>
<label class="container" style="margin-bottom: 25px">
<input type="text" placeholder="(Enter K for Keep, D for Delete)">
</label>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<form method="post">
{% csrf_token %}
<button type="submit" name="run_script">Submit</button>
</form>
</body>
</html>
I want to be able to pull the input from the last td tag and store it with the submit button below there.
I'm kind of late, but I hope it helps you out.
urls.py
from django.urls import path
from workbook_app import views
app_name = 'workbook_app'
urlpatterns = [
path('books/', views.BookListView.as_view(), name='books'),
path('keep_or_delete/<int:pk>/', views.KeepOrDeleteView.as_view(), name='keep_or_delete'),
]
models.py
from django.db import models
class Book(models.Model):
name = models.CharField(max_length=250)
owner_name = models.CharField(max_length=250)
marked_for_deletion = models.BooleanField(default=False)
views.py
from django.views.generic import ListView
from workbook_app.models import Book
from django.http import HttpResponse, HttpResponseRedirect
from django.views import View
from django.urls import reverse
class BookListView(ListView):
template_name = 'workbook_app/books.html'
def get_queryset(self):
return Book.objects.all()
class KeepOrDeleteView(View):
def post(self, request, pk):
book = Book.objects.get(pk=pk)
print(book, book.marked_for_deletion, not book.marked_for_deletion)
book.marked_for_deletion = not book.marked_for_deletion
book.save()
url = reverse('workbook_app:books')
return HttpResponseRedirect(url)
books.html
<div class="container">
<h2>Books</h2>
<table class="table">
<tr>
<th>Workbook Name</th>
<th>Deletion Deadline</th>
<th>Keep or Delete?</th>
</tr>
{% for book in object_list %}
<tr>
<td>{{book.name}}</td>
<td>{{book.owner_name}}</td>
<td>
<form action="{% url 'workbook_app:keep_or_delete' pk=book.pk %}" method="POST">
{% csrf_token %}
<button type="submit" class="btn btn-{%if book.marked_for_deletion %}primary{% else%}danger{% endif %}">{%if book.marked_for_deletion %}Keep{% else%}Delete{% endif %}</button>
</form>
</td>
</tr>
{%endfor%}
</table>
P.S. I'm not handling exceptions, messages, etc. You're just gonna have to figure it out yourself or open a new question.