How to redirect from StreamingHttpResponse in Django - python

I would like to achieve this flow:
User's face is detected by webcam in homepage
The app takes the attendance of the user, display a webpage with the attendance details
The attendance details page will redirect back to the homepage after few seconds with the webcam still running
As of now, my app is able to take the attendance of the user but will not render to the attendance details page even though I used return render(). It will remain on the homepage with the webcam still running. Is there a way I can solve this problem or am I getting something wrong? I have tried changing the request details manually like this but it is not working.
request.resolver_match = resolve('/takeAttendance/')
request.path='/takeAttendance/'
request.path_info='/takeAttendance/'
A problem similar to How to redirect to another url after detect face in django but none of the answers worked for me.
The involved code is as below:
views.py
from django.shortcuts import render, redirect
from django.contrib import messages
from django.http import HttpResponse , StreamingHttpResponse
from datetime import datetime, date
import cv2
import face_recognition
import numpy as np
import threading
foundFace = False
vs = cv2.videoCapture(0)
lock = threading.Lock()
frame = None
def videoFeed(request):
return StreamingHttpResponse(getFace(request),content_type="multipart/x-mixed-replace;boundary=frame")
def getFace(request):
global vs,outputFrame,lock,foundFace
known_face_names,known_face_encodings = getFiles() # get the image files from my project directory
face_location = []
face_encoding = []
while foundFace==False:
check,frame = vs.read()
small_frame = cv2.resize(frame,(0,0),fx=0.5,fy=0.5)
face_roi = small_frame[:,:,::-1]
face_location = face_recognition.face_locations(face_roi)
face_encoding = face_recognition.face_encodings(face_roi,face_location)
face_names = []
names=[]
for encoding in face_encoding:
matches = face_recognition.compare_faces(known_face_encodings,np.array(encoding),tolerance=0.6)
distances = face_recognition.face_distance(known_face_encodings,encoding)
matches = face_recognition.compare_faces(known_face_encodings,np.array(encoding),tolerance=0.6)
distances = face_recognition.face_distance(known_face_encodings,encoding)
best_match_index = np.argmin(distances)
if matches[best_match_index]:
name = known_face_names[best_match_index]
face_names.append(name)
if name not in names:
names.append(name)
#process the frame (add text and rectangle, add the name of the identified user to names)
with lock:
(flag,encodedImg) = cv2.imencode(".jpg",frame)
if len(names)!=0:
foundFace=True
if foundFace==True:
takeAttendance(request,names)
foundFace==False
yield(b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n' +
bytearray(encodedImg) + b'\r\n')
def takeAttendance(request,names):
context={}
if request.method=='GET':
if user_id in names:
attendance = Attendance(user_ID = str(user_id),
date_in = date.today(),
time_in = datetime.now())
attendance.save()
context={'attendance':attendance}
messages.success(request,'Check in successful')
return render(request,'Attendance/attendance.html',context)
else:
messages.error(request,'Check in failed')
return redirect('home')
else:
return redirect('home')
urls.py
from django.urls import path
from . import views
urlpatterns=[
path('home/',views.home,name='home'),
path('takeAttendance/',views.takeAttendance,name='takeAttendance'),
path('videoFeed/',views.videoFeed,name='videoFeed'),
]
I'm using Django 3.1 and I'm quite new to it, thank you!
Edit
Actually I would like to redirect to Attendance.html but keep the video stream running, like in a loop so I can redirect from Attendance.html to the webcam page with Javascript and still have the video stream running. Sorry for not making it clear.

Oh... why I didn't notice that...
The problem is:
...
if foundFace==True:
takeAttendance(request,names)
...
Yes, you execute function that returns render output inside getFace. And that's all, getFace don't use return value at all.
Correct code should be like:
...
if foundFace==True:
returned_render = takeAttendance(request,names)
return returned_render
...
or simply:
...
if foundFace==True:
return takeAttendance(request,names)
# or maybe you should use yield instead of return?
# I don't know. Check both
yield takeAttendance(request,names)
...

Related

How to call instance variable form another class and file

I have a question, I have 4 file app.py, face.py, camera.py and db.py Inside face.py file I have one variable call known_encoding_faces. If I put print code inside my face.py and run the app.py the result will display in my command prompt.
My question is how can i use known_encoding_faces variable in my camera.py? My expected result is when i run my app.py and open my webcam the command prompt will show the printed known_encoding_faces output. I believe if this work means this known_encoding_faces variable successfully can be used by camera.py file.
Here I attach my code. Hope someone can help me regarding on this matter.
app.py
from flask import Flask, Response, json, render_template
from werkzeug.utils import secure_filename
from flask import request
from os import path, getcwd
import time
from face import Face
from db import Database
app = Flask(__name__)
import cv2
from camera import VideoCamera
app.config['file_allowed'] = ['image/png', 'image/jpeg']
app.config['train_img'] = path.join(getcwd(), 'train_img')
app.db = Database()
app.face = Face(app)
def gen(camera):
while True:
frame = camera.get_frame()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')
#app.route('/video_feed')
def video_feed():
return Response(gen(VideoCamera()),
mimetype='multipart/x-mixed-replace; boundary=frame')
#app.route('/')
def index():
return render_template('index.html')
def success_handle(output, status=200, mimetype='application/json'):
return Response(output, status=status, mimetype=mimetype)
face.py
import face_recognition
from os import path
import cv2
import face_recognition
class Face:
def __init__(self, app):
self.train_img = app.config["train_img"]
self.db = app.db
self.faces = []
self.face_user_keys = {}
self.known_encoding_faces = [] # faces data for recognition
self.load_all()
def load_user_by_index_key(self, index_key=0):
key_str = str(index_key)
if key_str in self.face_user_keys:
return self.face_user_keys[key_str]
return None
def load_train_file_by_name(self,name):
trained_train_img = path.join(self.train_img, 'trained')
return path.join(trained_train_img, name)
def load_unknown_file_by_name(self,name):
unknown_img = path.join(self.train_img, 'unknown')
return path.join(unknown_img, name)
def load_all(self):
results = self.db.select('SELECT faces.id, faces.user_id, faces.filename, faces.created FROM faces')
for row in results:
user_id = row[1]
filename = row[2]
face = {
"id": row[0],
"user_id": user_id,
"filename": filename,
"created": row[3]
}
self.faces.append(face)
face_image = face_recognition.load_image_file(self.load_train_file_by_name(filename))
face_image_encoding = face_recognition.face_encodings(face_image)[0]
index_key = len(self.known_encoding_faces)
self.known_encoding_faces.append(face_image_encoding)
index_key_string = str(index_key)
self.face_user_keys['{0}'.format(index_key_string)] = user_id
def recognize(self,unknown_filename):
unknown_image = face_recognition.load_image_file(self.load_unknown_file_by_name(unknown_filename))
unknown_encoding_image = face_recognition.face_encodings(unknown_image)[0]
results = face_recognition.compare_faces(self.known_encoding_faces, unknown_encoding_image);
print("results", results)
index_key = 0
for matched in results:
if matched:
# so we found this user with index key and find him
user_id = self.load_user_by_index_key(index_key)
return user_id
index_key = index_key + 1
return None
camera.py
import face_recognition
from os import path
import cv2
from db import Database
from face import Face
class VideoCamera(object):
def __init__(self):
# Using OpenCV to capture from device 0. If you have trouble capturing
# from a webcam, comment the line below out and use a video file
# instead.
self.video = cv2.VideoCapture(0)
# If you decide to use video.mp4, you must have this file in the folder
# as the main.py.
# self.video = cv2.VideoCapture('video.mp4')
def __del__(self):
self.video.release()
def get_frame(self):
success, image = self.video.read()
# We are using Motion JPEG, but OpenCV defaults to capture raw images,
# so we must encode it into JPEG in order to correctly display the
# video stream.
ret, jpeg = cv2.imencode('.jpg', image)
return jpeg.tobytes()
known_encoding_faces is a member of a Face object. That means it does not exist on its own - as evidence, note you only reference self.known_encoding_faces rather than just known_encoding_faces. You need to initialize some Face object, and than you can use it. Further more, it looks like you would need to call load_all on said object to properly initialize it. The minimal thing you need is some thing like:
from face import Face
aface = Face(app) #You would need an app here
aface.load_all()
known_encoding_faces = aface.known_encoding_faces
If you are expecting this to exist irrespective of an objects creation, you need to rethink your design, and take it out of your class.
If you are expecting this to be called from the main script, you can demand this variable to initialize your camera:
VideoCamera(app.face.known_encoding_faces) #Called from main script
and in camera.py:
class VideoCamera(object):
def __init__(self,known_face_encodings):
self.known_encoding_faces = known_face_encodings
self.video = cv2.VideoCapture(0)
and in this class you can now use self.known_encoding_faces.

How can Import a csv file into a Django project?

I can't import a csv file into my Django project.
I have a code that is already working that basically takes a csv file and output spendings on different categories (using pandas). I'm learning Django right now and I'm trying to include that code into my project. But everytime I try to run in it says 'No module named StatementOCTRev'.
I'm not sure if it's a directory thing or a pandasXdjango thing.
I tried different approaches but none of them work. That led to an ugly code. So I apologize. Anyway here is my view.py:
from django.shortcuts import render, get_object_or_404
from .models import Post
from .budget import Categorize, Spending
import numpy as np
import pandas as pd
import csv
import mysite.StatementOCTRev
from import_export import resources
#import
# Create your views here.
def home(request):
posts = Post.objects
return render(request, 'mysite/home.html', {'posts':posts})
def post(request,post_id):
################################
coffeelist = ["WING", "COSTA", "CAFFEINE", "PASSO", "LA FELICE", "GULLUOGLU", "CARIBOU", "ARK COFFEE"]
restlist = ["TALABAT", "SOLO", "MELENZANE", "PIZZA", "HARDEES", "HARDEE'S", "MCDONALDS", "GULF ROYAL", "SARAY", "Carriage"]
gaslist = ["KNPC", "OULA", "ALFA"]
read = pd.read_csv('StatementOCTRev.csv', encoding="ISO-8859-1") # Read CSV
# create a new dataframe
df = pd.DataFrame(columns=["Date", "Reference", "Debit", "Credit", "Balance"])
df['Date'] = read.iloc[:, 0]
df['Reference'] = read.iloc[:, 1]
df['Debit'] = read.iloc[:, 2]
df['Credit'] = read.iloc[:, 3]
df['Balance'] = read.iloc[:, 4]
df['Category'] = 'Misc.'
for name in df.Debit:
if name < 0:
df.loc[df.Debit == name, 'Debit'] = name * -1
df.Reference = [str(x).replace(str(x), str(x).upper()) for x in df.Reference]
df.Reference = [x.strip().replace('POS', '') for x in df.Reference]
df.Reference = [x.strip().replace('UTAP', '') for x in df.Reference]
df.Reference = [x.strip().replace('#', '') for x in df.Reference]
df.Reference = [x.strip().replace('-', '') for x in df.Reference]
df.Reference = [x.strip().replace('_', '') for x in df.Reference]
# ------------------------ Coffee
Categorize(coffeelist, "Coffee")
SpentOnCoffee = Spending("Coffee")
# ------------------------ Restaurant
Categorize(restlist, "Restaurant")
SpentOnRest = Spending("Restaurant")
# ------------------------ Gas
Categorize(gaslist, "Gas")
SpentOnGas = Spending("Gas")
Other = 1296 - SpentOnRest - SpentOnCoffee - SpentOnGas
coffeecategorized = Categorize(coffeelist, "Coffee")
coffeespending = Spending("Coffee")
post = get_object_or_404(Post, pk=post_id)
return render(request, 'mysite/post.html', {'post':post})
Note: You can see, I'm not telling post function to return anything related to the file, that's because I actually couldn't go any further. Of course I want to. but I just want to make the code read the csv file first.
Also, models.py has nothing related to this csv file (it only has a Post class as app is just a blog that I'm making to exercise Django.)

Running python script from django view with parameters

I want to call a python script with paramters from django view. The python script is stored in a subfolder (see attached picture).
Basically I have an input form and want to call crawl.py with the input data from that form. The form data should be stored in variable "production_number" in crawl.py.
view.py
from .forms import CustomerForm, LoginForm
from .models import Orders
from .ERPProgramm.crawl import crawlmain
def newOrders(request):
if request.method == 'POST':
form = CustomerForm(request.POST)
if form.is_valid():
formdata = form.cleaned_data['product_ID']
# call crawl.py with paramter formdata
return HttpResponseRedirect('/customer/newOrders')
crawl.py
import db
import sys
import requests
import json
from datetime import datetime
def query(resource):
r = requests.get('http://11.111.11.11:8080/webapp/api/v1/' + resource,
headers={'AuthenticationToken': '11111-11111-1111-1111-11111'}
)
return r
costumer_id = 1
production_number = formdata
d = query('productionOrder/?productionOrderNumber-eq={}'.format(production_number)).json()
session = db.Session()
costumer = session.query(db.Costumer).get(costumer_id)
if 'result' in d and len(d['result']) > 0:
r = d['result'][0]
order = db.Order()
try:
order.article_id = r['articleId']
order.amount = r['targetQuantity']
order.create_date = datetime.fromtimestamp(r['createdDate'] / 1000)
order.start_date = datetime.fromtimestamp(r['targetStartDate'] / 1000)
order.end_date = datetime.fromtimestamp(r['targetEndDate'] / 1000)
except NameError as e:
sys.exit('Error {}'.format(e.what()))
article_number = r['articleNumber']
d = query('article/?articleNumber-eq={}'.format(article_number)).json()
if 'result' in d and len(d['result']) > 0:
r = d['result'][0]
article_image_id = r['articleImages'][0]['id']
order.price_offer = r['articlePrices'][0]['price']
r = query('article/id/{}/downloadArticleImage?articleImageId={}'.format(order.article_id, article_image_id))
order.article_image = r.content
else:
print('No result for article with number', article_number)
costumer.orders.append(order)
session.add(costumer)
session.commit()
else:
print('No result for production order with article number', article_number)
How can I call crawl.py from django view?
Directory Overview
you can check this
In your case you need to find exact file path for doing this you need to find the path from base dir in settings.py import it in view.py .
settings.py
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
FILE_DIR = os.path.abspath(os.path.join(BASE_DIR,'/Customer/ERPProgram')
views.py
import sys
sys.path.insert(0, os.path.join(settings.FILE_DIR))
import crawl

Python / Django compare and update model objects

Iv only just started python but have learned a lot over the last few month, now I have hit a wall about updating objects on a model at a good speed.
I have a model called Products and this is populated from a csv file, every day this file get updated with changes like cost, and quantity, I can compare each line of the file with the Products Model but having 120k lines this takes 3-4hours.
What process can I take to make this process this file faster. I only want to modify the objects if cost and quantity have changed
Any suggestions how I tackle this?
Ver3 of what i have tried.
from django.core.management import BaseCommand
from multiprocessing import Pool
from django.contrib.auth.models import User
from pprint import pprint
from CentralControl.models import Product, Supplier
from CentralControl.management.helpers.map_ingram import *
from CentralControl.management.helpers.helper_generic import *
from tqdm import tqdm
from CentralControl.management.helpers.config import get_ingram
import os, sys, csv, zipfile, CentralControl
# Run Script as 'SYSTEM'
user = User.objects.get(id=1)
# Get Connection config.
SUPPLIER_CODE, FILE_LOCATION, FILE_NAME = get_ingram()
class Command(BaseCommand):
def handle(self, *args, **options):
list_in = get_file()
list_current = get_current_list()
pool = Pool(6)
pool.map(compare_lists(list_in, list_current))
pool.close()
def compare_lists(list_in, list_current):
for row_current in tqdm(list_current):
for row_in in list_in:
if row_in['order_code'] == row_current['order_code']:
#do more stuff here.
pass
def get_current_list():
try:
supplier = Supplier.objects.get(code='440040')
current_list = Product.objects.filter(supplier=supplier).values()
return current_list
except:
print('Error no products with supplier')
exit()
def get_file():
with zipfile.ZipFile(FILE_LOCATION + 'incoming/' + FILE_NAME, 'r') as zip:
with zip.open('228688 .csv') as csvfile:
reader = csv.DictReader(csvfile)
list_in = (list(reader))
for row in tqdm(list_in):
row['order_code'] = row.pop('Ingram Part Number')
row['order_code'] = (row['order_code']).lstrip("0")
row['name'] = row.pop('Ingram Part Description')
row['description'] = row.pop('Material Long Description')
row['mpn'] = row.pop('Vendor Part Number')
row['gtin'] = row.pop('EANUPC Code')
row['nett_cost'] = row.pop('Customer Price')
row['retail_price'] = row.pop('Retail Price')
row['qty_at_supplier'] = row.pop('Available Quantity')
row['backorder_date'] = row.pop('Backlog ETA')
row['backorder_date'] = (row['backorder_date'])
row['backorder_qty'] = row.pop('Backlog Information')
zip.close()
#commented out for dev precess.
#os.rename(FILE_LOCATION + 'incoming/' + FILE_NAME, FILE_LOCATION + 'processed/' + FILE_NAME)
return list_in
I have once faced a problem of slow load of data, I can tell you what i did maybe it can help you somehow, I passed the execution to debug mode and tried to find out wich colomn is causing the slow loading, and everytime i see that a colomn is causing the problem I add an index on it (in the SGBD --> postgreSQL in my case), and it worked. I hope that you are facing the same problem so my answer can help you.
Here it's rough idea:
1, when reading csv, use pandas as suggest by #BearBrow into array_csv
2, convert the obj data from Django into Numpy Arrary array_obj
3, don't compare them one by one , using numpy substraction
compare_index = (array_csv[['cost',['quantity']]] - array[['cost',['quantity']]] == 0)
4, find the updated column
obj_need_updated = array_obj[np.logic_any(compare_index['cost'], compare['quantity'])]
then use Django bulk update https://github.com/aykut/django-bulk-update to bulk update
Hope this will give you hints to speed up your code

Django - Get I/O error on changing object attribute

In my views.py file, I am trying to add 1 to a BigIntegerField named visited_counter.
views.py :
def view_page(request,id_page):
page = get_object_or_404(Page,title=id_page)
page.visited_counter= page.visited_counter +1
page.save()
return render(request,'app/page.html',locals())
models.py :
class Page(models.Model):
title = models.CharField(max_length=30)
visited_counter= models.BigIntegerField()
landscape= models.BooleanField()
thumbnail = models.ImageField(storage=OverwriteStorage(),upload_to=thumbnail_path)
backgroundpicture =models.ImageField(storage=OverwriteStorage(),upload_to=background_path)
def save(self, *args, **kwargs):
if self.backgroundpicture.width >= self.backgroundpicture.height:
self.landscape=True
else:
self.landscape=False
if self.backgroundpicture:
from PIL import Image
import glob, os
from cStringIO import StringIO
from django.core.files.uploadedfile import SimpleUploadedFile
image = Image.open(self.backgroundpicture) ####LINE ERROR####
try:
# thumbnail
THUMBNAIL_SIZE = (160, 160) # dimensions
# Convert to RGB if necessary
if image.mode not in ('L', 'RGB'): image = image.convert('RGB')
# create a thumbnail + use antialiasing for a smoother thumbnail
image.thumbnail(THUMBNAIL_SIZE, Image.ANTIALIAS)
# fetch image into memory
temp_handle = StringIO()
image.save(temp_handle, 'JPEG')
temp_handle.seek(0)
# save it
file_name, file_ext = os.path.splitext(self.backgroundpicture.name.rpartition('/')[-1])
suf = SimpleUploadedFile(file_name + file_ext, temp_handle.read(), content_type='JPEG')
self.thumbnail.save(file_name + '.jpg', suf, save=False)
except ImportError:
pass
super(Page, self).save(*args, **kwargs)
When I create a 'Page object', I have no problem.... The save function is doing her job very well, but when I want to access to the object via the view_page function. I get a I/O operation on closed file error on that line: image = Image.open(self.backgroundpicture).
I didn't find any other Q/A related to this case, so I am stuck...
The trick is to add an if condition in your save method and check if it is necessary to read the whole code in the save function.
For this you add a function named, has_changed
def has_changed(instance, field, manager='objects'):
"""Returns true if a field has changed in a model
May be used in a model.save() method.
"""
if not instance.pk:
return True
manager = getattr(instance.__class__, manager)
old = getattr(manager.get(pk=instance.pk), field)
return not getattr(instance, field) == old
And you use it in the model definition like this:
if has_changed(self, 'backgroundpicture'):
if self.backgroundpicture.width >= self.backgroundpicture.height:
self.landscape=True
...

Categories

Resources