我正在尝试建立一个针对自己生产的产品的网站。产品将来自传感器的数据记录在CSV文件中。我想做的事情:用户可以创建一个帐户,上传他们的CSV,然后使用chart.js,通过模板标签将x和y轴数据传递给模板。 我的想法是使用本地CSV测试文件很好地工作,但是现在我需要在视图中引用用户特定的文件,然后解析csv并将数据作为上下文返回,但是我仍然坚持如何引用特定的用户csv以及如何在视图中处理文件。
models.py
from django.db import models
from django.contrib.auth.models import User
from django.contrib.auth import get_user_model
def user_directory_path(instance, filename):
return 'user_{0}/{1}'.format(instance.user.id, filename)
class Document(models.Model):
docfile = models.FileField(null=True, blank=True, upload_to=user_directory_path)
description = models.CharField(max_length=255)
user = models.ForeignKey(User, on_delete=models.CASCADE)
def get_upload_path(self,filename):
return "media/uploads/"+str(self.user.id)+"/"+filename
def __str__(self):
return self.description
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
#additional
portfolio_site = models.URLField(blank=True)
profile_pic = models.ImageField(upload_to='profile_pics',blank=True)
docfiles = models.OneToOneField(Document, on_delete=models.CASCADE)
def __str__(self):
return self.user.username
views.py
from django.shortcuts import render, redirect, render_to_response, reverse
from django.http import HttpResponse
from django.http import HttpResponseRedirect
from django.conf import settings
from django.contrib import messages
from . import parsecsv
import json
from .models import Document
from .forms import UploadFileForm, UserForm, UserProfileForm
from django.views import View
from django.views.generic import TemplateView, FormView
from django.contrib.auth import authenticate,login,logout
from django.urls import reverse
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from .forms import UploadFileForm
from . import parsecsv
# Create your views here.
class HomePageView(TemplateView):
template_name = "EdiApp/index.html"
def upload(request):
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
docfile = form.save(commit=False)
docfile.user = request.user
docfile.save()
return HttpResponseRedirect(reverse('edigraph'))
else:
form = UploadFileForm
return render(request, 'EdiApp/upload.html',{'form':form})
class EdiGraphView(LoginRequiredMixin, TemplateView):
template_name = "EdiApp/edigraph.html"
def get_queryset(self):
user = self.request.user
ds = Document.objects.get(user=user)
def time(self):
with open(ds,'r') as csv_file:
csv_reader = csv.reader(csv_file)
next(csv_reader) #takes out header of CSV
for line in csv_reader:
return [line[0] for line in csv_reader]
return time()
#Context referencing a local static file to test the chart.js
time = str(parsecsv.time()).replace("'","").replace(":","")
temp = str(parsecsv.temp()).replace("'","")
emfval = str(parsecsv.emfval()).replace("'","")
hum = str(parsecsv.hum()).replace("'","")
pres = str(parsecsv.pres()).replace("'","")
geo = str(parsecsv.geo()).replace("'","")
mar = str(parsecsv.mar()).replace("'","")
def get_context_data(self, **kwargs):
context = super(EdiGraphView, self).get_context_data(**kwargs)
context.update({"insert_time": self.time(), "insert_temp": self.temp, "insert_emfval": self.emfval, "insert_hum": self.hum, "insert_pres": self.pres, "insert_geo": self.geo, "insert_mar": self.mar})
return context
@login_required
def user_logout(request):
logout(request)
return HttpResponseRedirect(reverse('index'))
def register(request):
registered = False
if request.method == "POST":
user_form = UserForm(data=request.POST)
profile_form = UserProfileForm(data=request.POST)
if user_form.is_valid() and profile_form.is_valid():
user = user_form.save()
user.set_password(user.password)
user.save()
profile = profile_form.save(commit=False)
profile.user = user
if 'profile_pic' in request.FILES:
profile.profile_pic = request.FILES['profile_pic']
profile.save()
registered = True
else:
print(user_form.errors)
else:
user_form = UserForm()
profile_form = UserProfileForm()
return render(request,'EdiApp/registration.html',
{'user_form':user_form,
'profile_form':profile_form,
'registered':registered})
@login_required
def form_page(request):
form = UploadFileForm(request.POST or None, request.FILES or None)
if form.is_valid():
instance = form.save(commit=False) #commit=false is so you can manipulate the data before saving it to the database / save after to prevent collision errors
instance.save()
messages.success(request, "Successfully uploaded")
# return redirect('EdiApp/index/')
return HttpResponseRedirect(reverse('index'))
context = {
"form": form,
}
return render(request, "EdiApp/form_page.html", context)
def user_login(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
user = authenticate(username=username,password=password)
if user:
if user.is_active:
login(request,user)
return HttpResponseRedirect(reverse('index'))
else:
return HttpResponse("ACCOUTN NOT ACTIVE")
else:
print("someone tried to login and failed")
print("username: {} and password {}".format(username,password))
return HttpResponse("invalid Login details supplied!")
else:
return render(request,'EdiApp/login.html',{})
HTML
<!DOCTYPE html>
{% extends "EdiApp/base.html" %}
{% block body_block %}
{% load staticfiles %}
<style type="text/css">
body {
height: 100%;
width: 100%;
background-image: None;
background-color: rgba(30,30,30,1) !important;
}
</style>
<body class="graphbody">
<div class="headertext py-4">
<h3 class="pb-2">Upload Your EdiLog CSV {{ insert_time }} </h3>
<a class="btn btn-primary" href="{% url 'EdiApp:upload' %}">Upload CSV</a>
</div>
<hr style="border-color:white;" class="pb-2">
<div class="wrapper" style="">
<canvas id="temp"></canvas>
</div>
<script type="text/javascript">
var ctx = document.getElementById("temp");
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: {{ insert_time }},
datasets: [
{
label: 'Temperature',
data: {{ insert_temp }},
backgroundColor: "rgba(255, 99, 132, 0.8)",
borderColor: "rgba(255, 99, 132, 1.0)",
pointBackgroundColor: "black",
pointBorderWidth: 0,
pointHoverRadius: 8,
pointHoverBackgroundColor: "white",
pointHoverBorderWidth: 1,
pointRadius: 1,
pointHitRadius: 10,
}
]
},
options: {
responsive: true,
scales: {
xAxes: [{
gridLines: {
color: ['rgba(255,255,255,0.3)']
},
ticks: {
autoSkip: true,
maxTicksLimit: 20
},
}],
yAxes: [{
gridLines: {
color: ['rgba(255,255,255,0.3)']
},
}]
}
}
});
</script>
<hr style="border-color:white;" class="pb-2">
<div class="wrapper" style="">
<canvas id="emf"></canvas>
</div>
<script type="text/javascript">
var ctx = document.getElementById("emf");
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: {{ insert_time }},
datasets: [
{
label: 'EMF',
data: {{ insert_emfval }},
backgroundColor: "rgba(75, 200, 50, 0.8)",
borderColor: "rgba(0, 255, 0, 1.0)",
pointBackgroundColor: "black",
pointBorderWidth: 0,
pointHoverRadius: 8,
pointHoverBackgroundColor: "white",
pointHoverBorderWidth: 1,
pointRadius: 1,
pointHitRadius: 10,
}
]
},
options: {
responsive: true,
scales: {
xAxes: [{
gridLines: {
color: ['rgba(255,255,255,0.3)']
},
ticks: {
autoSkip: true,
maxTicksLimit: 20
},
}],
yAxes: [{
gridLines: {
color: ['rgba(255,255,255,0.3)']
},
}]
}
}
});
</script>
<hr style="border-color:white;" class="pb-2">
<div class="wrapper" style="">
<canvas id="geo"></canvas>
</div>
<script type="text/javascript">
var ctx = document.getElementById("geo");
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: {{ insert_time }},
datasets: [
{
label: 'Vibration',
data: {{ insert_geo }},
backgroundColor: "rgba(138, 43, 226, 0.8)",
borderColor: "rgba(75, 0, 130, 1.0)",
pointBackgroundColor: "black",
pointBorderWidth: 0,
pointHoverRadius: 8,
pointHoverBackgroundColor: "white",
pointHoverBorderWidth: 1,
pointRadius: 1,
pointHitRadius: 10,
}
]
},
options: {
responsive: true,
scales: {
xAxes: [{
gridLines: {
color: ['rgba(255,255,255,0.3)']
},
ticks: {
autoSkip: true,
maxTicksLimit: 20
},
}],
yAxes: [{
gridLines: {
color: ['rgba(255,255,255,0.3)']
},
}]
}
}
});
</script>
<hr style="border-color:white;" class="pb-2">
<div class="wrapper" style="">
<canvas id="hum"></canvas>
</div>
<script type="text/javascript">
var ctx = document.getElementById("hum");
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: {{ insert_time }},
datasets: [
{
label: 'Humidity',
data: {{ insert_hum }},
backgroundColor: "rgba(91,192,222,0.8)",
borderColor: "rgba(91,192,222,1)",
pointBackgroundColor: "black",
pointBorderWidth: 0,
pointHoverRadius: 8,
pointHoverBackgroundColor: "white",
pointHoverBorderWidth: 1,
pointRadius: 1,
pointHitRadius: 10,
}
]
},
options: {
responsive: true,
scales: {
xAxes: [{
gridLines: {
color: ['rgba(255,255,255,0.3)']
},
ticks: {
autoSkip: true,
maxTicksLimit: 20
},
}],
yAxes: [{
gridLines: {
color: ['rgba(255,255,255,0.3)']
},
}]
}
}
});
</script>
<hr style="border-color:white;" class="pb-2">
<div class="wrapper" style="">
<canvas id="pres"></canvas>
</div>
<script type="text/javascript">
var ctx = document.getElementById("pres");
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: {{ insert_time }},
datasets: [
{
label: 'Pressure',
data: {{ insert_pres }},
backgroundColor: "rgba(220,220,220,0.8)",
borderColor: "rgba(90,90,90,1)",
pointBackgroundColor: "black",
pointBorderWidth: 0,
pointHoverRadius: 8,
pointHoverBackgroundColor: "white",
pointHoverBorderWidth: 1,
pointRadius: 1,
pointHitRadius: 10,
}
]
},
options: {
responsive: true,
scales: {
xAxes: [{
gridLines: {
color: ['rgba(255,255,255,0.3)']
},
ticks: {
autoSkip: true,
maxTicksLimit: 20
},
}],
yAxes: [{
gridLines: {
color: ['rgba(255,255,255,0.3)']
},
}]
}
}
});
</script>
</body>
{% endblock %}
parsecsv.py the file I use to parse the CSV and get the test context
import csv
import datetime
def time():
with open('EDILOG01.CSV','r') as csv_file:
csv_reader = csv.reader(csv_file)
next(csv_reader) #takes out header of CSV
for line in csv_reader:
return [line[0] for line in csv_reader]
def emfval():
with open('EDILOG01.CSV','r') as csv_file:
csv_reader = csv.reader(csv_file)
next(csv_reader, None) #takes out header of CSV
for line in csv_reader:
return [line[1] for line in csv_reader]
def temp():
with open('EDILOG01.CSV','r') as csv_file:
csv_reader = csv.reader(csv_file)
next(csv_reader, None) #takes out header of CSV
for line in csv_reader:
return [line[2] for line in csv_reader]
def hum():
with open('EDILOG01.CSV','r') as csv_file:
csv_reader = csv.reader(csv_file)
next(csv_reader, None) #takes out header of CSV
for line in csv_reader:
return [line[3] for line in csv_reader]
def pres():
with open('EDILOG01.CSV','r') as csv_file:
csv_reader = csv.reader(csv_file)
next(csv_reader, None) #takes out header of CSV
for line in csv_reader:
return [line[4] for line in csv_reader]
def geo():
with open('EDILOG01.CSV','r') as csv_file:
csv_reader = csv.reader(csv_file)
next(csv_reader, None) #takes out header of CSV
for line in csv_reader:
return [line[5] for line in csv_reader]
def mar():
with open('EDILOG01.CSV','r') as csv_file:
csv_reader = csv.reader(csv_file)
next(csv_reader, None) #takes out header of CSV
for line in csv_reader:
return [line[6] for line in csv_reader]
最终,我希望用户能够从上载CSV的列表中进行选择,然后将所选的CSV文件放入要显示的上下文标签中,但是我只能通过引用最新文件用户上传并返回上下文。
我是python和Django的新手,在阅读文档时,我觉得答案就在我眼前,尽管我只是不知道该怎么做。任何输入都会有很大的帮助,谢谢大家!