Django model and views to summarize and plot an uploaded CSV
up vote
1
down vote
favorite
I have a simple web application where a user uploads a CSV of some dataset and some summary statistics and box plots are displayed. I heard that it is better to have so called skinny views and fat models, though I'm unsure how is best to divide the work. How could I improve my database schema and division of labour?
views.py
class HomeView(View):
"""View that handles when users land on the homepage"""
def get(self, request):
return render(request, 'summary/home.html')
# Will currently raise an HttpResponseNotAllowed if POST request received to home
@method_decorator(login_required, name='dispatch')
class UploadView(TemplateView):
"""Users land here after successfully signing in and are prompted to upload a CSV file"""
form_class = UploadFileForm
template_name = 'summary/uploads.html'
def get(self, request):
form = self.form_class()
datasets = Dataset.objects.filter(user=request.user)
context = {
'datasets': datasets,
'csv_form': form,
'within_dataset_limit': request.user.within_dataset_limit()
}
return render(request, self.template_name, context=context)
def post(self, request):
form = self.form_class(request.POST, request.FILES)
if form.is_valid():
uploaded_file = request.FILES['dataset_file']
datasets = Dataset.objects.filter(user=request.user)
context = {
'datasets': datasets,
'csv_form': form,
'within_dataset_limit': request.user.within_dataset_limit(),
}
# Check the file is a CSV
if not str(uploaded_file).lower().endswith('.csv'):
context['error'] = 'File not in CSV format.'
return render(request, 'summary/uploads.html', context)
# Check the file size is within the set limit
elif not 0 < uploaded_file.size < request.user.max_dataset_size:
context['error'] = 'File exceeds size limit.'
return render(request, 'summary/uploads.html', context)
else:
ds = Dataset(user=request.user, dataset_name=str(uploaded_file), dataset_file=uploaded_file)
ds.save()
return redirect(f'/{request.user.pk}/{ds.id}/overview/')
@method_decorator(login_required, name='dispatch')
class OverviewView(TemplateView):
"""Display head and summary statistics of the uploaded dataset"""
template_name = 'summary/overview.html'
def get(self, request, upk, dpk):
if request.user.pk == upk:
ds = Dataset.objects.get(pk=dpk)
head, summary, df = dataset_stats(ds)
request.session['dataframe'] = df.to_json()
context = {
'first_five': head,
'summary_stats': summary,
}
return render(request, self.template_name, context)
def delete_dataset(request, upk, dpk):
if request.method == 'POST':
if request.user.is_authenticated and request.user.pk == upk:
try:
ds = Dataset.objects.get(pk=dpk)
os.remove(ds.dataset_file.path)
ds.delete()
return HttpResponse(status=200)
except Dataset.DoesNotExist:
return HttpResponseNotFound()
return HttpResponseForbidden()
return HttpResponseBadRequest()
def boxplot(request):
"""Generation of boxplots to be moved to computation server"""
# Get the selected columns from the overview view
selected_columns = request.GET['selectedColumns']
selected_columns = json.loads(selected_columns)
code, boxplot_html = generate_plots(selected_columns, request.session.get('dataframe'))
if boxplot_html is not None:
return HttpResponse(status=code, content=boxplot_html)
else:
error = "Could not create your plots"
return HttpResponse(status=code, content=error)
models.py
def get_upload_path(instance, filename):
return "user_{}/{}".format(instance.user.pk, filename)
class Dataset(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True)
dataset_name = models.CharField(max_length=100)
date_added = models.DateTimeField(auto_now_add=True)
dataset_file = models.FileField(upload_to=get_upload_path)
def __str__(self):
return self.dataset_name
def save(self, *args, **kwargs):
user = CustomUser.objects.get(username=self.user)
if user.num_datasets == user.max_datasets:
return # Exceeding the max number of datasets
else:
user.num_datasets += 1
user.save()
super().save(*args, **kwargs)
def delete(self, *args, **kwargs):
user = CustomUser.objects.get(username=self.user)
user.num_datasets -= 1
user.save()
super().delete(*args, **kwargs)
python django
add a comment |
up vote
1
down vote
favorite
I have a simple web application where a user uploads a CSV of some dataset and some summary statistics and box plots are displayed. I heard that it is better to have so called skinny views and fat models, though I'm unsure how is best to divide the work. How could I improve my database schema and division of labour?
views.py
class HomeView(View):
"""View that handles when users land on the homepage"""
def get(self, request):
return render(request, 'summary/home.html')
# Will currently raise an HttpResponseNotAllowed if POST request received to home
@method_decorator(login_required, name='dispatch')
class UploadView(TemplateView):
"""Users land here after successfully signing in and are prompted to upload a CSV file"""
form_class = UploadFileForm
template_name = 'summary/uploads.html'
def get(self, request):
form = self.form_class()
datasets = Dataset.objects.filter(user=request.user)
context = {
'datasets': datasets,
'csv_form': form,
'within_dataset_limit': request.user.within_dataset_limit()
}
return render(request, self.template_name, context=context)
def post(self, request):
form = self.form_class(request.POST, request.FILES)
if form.is_valid():
uploaded_file = request.FILES['dataset_file']
datasets = Dataset.objects.filter(user=request.user)
context = {
'datasets': datasets,
'csv_form': form,
'within_dataset_limit': request.user.within_dataset_limit(),
}
# Check the file is a CSV
if not str(uploaded_file).lower().endswith('.csv'):
context['error'] = 'File not in CSV format.'
return render(request, 'summary/uploads.html', context)
# Check the file size is within the set limit
elif not 0 < uploaded_file.size < request.user.max_dataset_size:
context['error'] = 'File exceeds size limit.'
return render(request, 'summary/uploads.html', context)
else:
ds = Dataset(user=request.user, dataset_name=str(uploaded_file), dataset_file=uploaded_file)
ds.save()
return redirect(f'/{request.user.pk}/{ds.id}/overview/')
@method_decorator(login_required, name='dispatch')
class OverviewView(TemplateView):
"""Display head and summary statistics of the uploaded dataset"""
template_name = 'summary/overview.html'
def get(self, request, upk, dpk):
if request.user.pk == upk:
ds = Dataset.objects.get(pk=dpk)
head, summary, df = dataset_stats(ds)
request.session['dataframe'] = df.to_json()
context = {
'first_five': head,
'summary_stats': summary,
}
return render(request, self.template_name, context)
def delete_dataset(request, upk, dpk):
if request.method == 'POST':
if request.user.is_authenticated and request.user.pk == upk:
try:
ds = Dataset.objects.get(pk=dpk)
os.remove(ds.dataset_file.path)
ds.delete()
return HttpResponse(status=200)
except Dataset.DoesNotExist:
return HttpResponseNotFound()
return HttpResponseForbidden()
return HttpResponseBadRequest()
def boxplot(request):
"""Generation of boxplots to be moved to computation server"""
# Get the selected columns from the overview view
selected_columns = request.GET['selectedColumns']
selected_columns = json.loads(selected_columns)
code, boxplot_html = generate_plots(selected_columns, request.session.get('dataframe'))
if boxplot_html is not None:
return HttpResponse(status=code, content=boxplot_html)
else:
error = "Could not create your plots"
return HttpResponse(status=code, content=error)
models.py
def get_upload_path(instance, filename):
return "user_{}/{}".format(instance.user.pk, filename)
class Dataset(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True)
dataset_name = models.CharField(max_length=100)
date_added = models.DateTimeField(auto_now_add=True)
dataset_file = models.FileField(upload_to=get_upload_path)
def __str__(self):
return self.dataset_name
def save(self, *args, **kwargs):
user = CustomUser.objects.get(username=self.user)
if user.num_datasets == user.max_datasets:
return # Exceeding the max number of datasets
else:
user.num_datasets += 1
user.save()
super().save(*args, **kwargs)
def delete(self, *args, **kwargs):
user = CustomUser.objects.get(username=self.user)
user.num_datasets -= 1
user.save()
super().delete(*args, **kwargs)
python django
add a comment |
up vote
1
down vote
favorite
up vote
1
down vote
favorite
I have a simple web application where a user uploads a CSV of some dataset and some summary statistics and box plots are displayed. I heard that it is better to have so called skinny views and fat models, though I'm unsure how is best to divide the work. How could I improve my database schema and division of labour?
views.py
class HomeView(View):
"""View that handles when users land on the homepage"""
def get(self, request):
return render(request, 'summary/home.html')
# Will currently raise an HttpResponseNotAllowed if POST request received to home
@method_decorator(login_required, name='dispatch')
class UploadView(TemplateView):
"""Users land here after successfully signing in and are prompted to upload a CSV file"""
form_class = UploadFileForm
template_name = 'summary/uploads.html'
def get(self, request):
form = self.form_class()
datasets = Dataset.objects.filter(user=request.user)
context = {
'datasets': datasets,
'csv_form': form,
'within_dataset_limit': request.user.within_dataset_limit()
}
return render(request, self.template_name, context=context)
def post(self, request):
form = self.form_class(request.POST, request.FILES)
if form.is_valid():
uploaded_file = request.FILES['dataset_file']
datasets = Dataset.objects.filter(user=request.user)
context = {
'datasets': datasets,
'csv_form': form,
'within_dataset_limit': request.user.within_dataset_limit(),
}
# Check the file is a CSV
if not str(uploaded_file).lower().endswith('.csv'):
context['error'] = 'File not in CSV format.'
return render(request, 'summary/uploads.html', context)
# Check the file size is within the set limit
elif not 0 < uploaded_file.size < request.user.max_dataset_size:
context['error'] = 'File exceeds size limit.'
return render(request, 'summary/uploads.html', context)
else:
ds = Dataset(user=request.user, dataset_name=str(uploaded_file), dataset_file=uploaded_file)
ds.save()
return redirect(f'/{request.user.pk}/{ds.id}/overview/')
@method_decorator(login_required, name='dispatch')
class OverviewView(TemplateView):
"""Display head and summary statistics of the uploaded dataset"""
template_name = 'summary/overview.html'
def get(self, request, upk, dpk):
if request.user.pk == upk:
ds = Dataset.objects.get(pk=dpk)
head, summary, df = dataset_stats(ds)
request.session['dataframe'] = df.to_json()
context = {
'first_five': head,
'summary_stats': summary,
}
return render(request, self.template_name, context)
def delete_dataset(request, upk, dpk):
if request.method == 'POST':
if request.user.is_authenticated and request.user.pk == upk:
try:
ds = Dataset.objects.get(pk=dpk)
os.remove(ds.dataset_file.path)
ds.delete()
return HttpResponse(status=200)
except Dataset.DoesNotExist:
return HttpResponseNotFound()
return HttpResponseForbidden()
return HttpResponseBadRequest()
def boxplot(request):
"""Generation of boxplots to be moved to computation server"""
# Get the selected columns from the overview view
selected_columns = request.GET['selectedColumns']
selected_columns = json.loads(selected_columns)
code, boxplot_html = generate_plots(selected_columns, request.session.get('dataframe'))
if boxplot_html is not None:
return HttpResponse(status=code, content=boxplot_html)
else:
error = "Could not create your plots"
return HttpResponse(status=code, content=error)
models.py
def get_upload_path(instance, filename):
return "user_{}/{}".format(instance.user.pk, filename)
class Dataset(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True)
dataset_name = models.CharField(max_length=100)
date_added = models.DateTimeField(auto_now_add=True)
dataset_file = models.FileField(upload_to=get_upload_path)
def __str__(self):
return self.dataset_name
def save(self, *args, **kwargs):
user = CustomUser.objects.get(username=self.user)
if user.num_datasets == user.max_datasets:
return # Exceeding the max number of datasets
else:
user.num_datasets += 1
user.save()
super().save(*args, **kwargs)
def delete(self, *args, **kwargs):
user = CustomUser.objects.get(username=self.user)
user.num_datasets -= 1
user.save()
super().delete(*args, **kwargs)
python django
I have a simple web application where a user uploads a CSV of some dataset and some summary statistics and box plots are displayed. I heard that it is better to have so called skinny views and fat models, though I'm unsure how is best to divide the work. How could I improve my database schema and division of labour?
views.py
class HomeView(View):
"""View that handles when users land on the homepage"""
def get(self, request):
return render(request, 'summary/home.html')
# Will currently raise an HttpResponseNotAllowed if POST request received to home
@method_decorator(login_required, name='dispatch')
class UploadView(TemplateView):
"""Users land here after successfully signing in and are prompted to upload a CSV file"""
form_class = UploadFileForm
template_name = 'summary/uploads.html'
def get(self, request):
form = self.form_class()
datasets = Dataset.objects.filter(user=request.user)
context = {
'datasets': datasets,
'csv_form': form,
'within_dataset_limit': request.user.within_dataset_limit()
}
return render(request, self.template_name, context=context)
def post(self, request):
form = self.form_class(request.POST, request.FILES)
if form.is_valid():
uploaded_file = request.FILES['dataset_file']
datasets = Dataset.objects.filter(user=request.user)
context = {
'datasets': datasets,
'csv_form': form,
'within_dataset_limit': request.user.within_dataset_limit(),
}
# Check the file is a CSV
if not str(uploaded_file).lower().endswith('.csv'):
context['error'] = 'File not in CSV format.'
return render(request, 'summary/uploads.html', context)
# Check the file size is within the set limit
elif not 0 < uploaded_file.size < request.user.max_dataset_size:
context['error'] = 'File exceeds size limit.'
return render(request, 'summary/uploads.html', context)
else:
ds = Dataset(user=request.user, dataset_name=str(uploaded_file), dataset_file=uploaded_file)
ds.save()
return redirect(f'/{request.user.pk}/{ds.id}/overview/')
@method_decorator(login_required, name='dispatch')
class OverviewView(TemplateView):
"""Display head and summary statistics of the uploaded dataset"""
template_name = 'summary/overview.html'
def get(self, request, upk, dpk):
if request.user.pk == upk:
ds = Dataset.objects.get(pk=dpk)
head, summary, df = dataset_stats(ds)
request.session['dataframe'] = df.to_json()
context = {
'first_five': head,
'summary_stats': summary,
}
return render(request, self.template_name, context)
def delete_dataset(request, upk, dpk):
if request.method == 'POST':
if request.user.is_authenticated and request.user.pk == upk:
try:
ds = Dataset.objects.get(pk=dpk)
os.remove(ds.dataset_file.path)
ds.delete()
return HttpResponse(status=200)
except Dataset.DoesNotExist:
return HttpResponseNotFound()
return HttpResponseForbidden()
return HttpResponseBadRequest()
def boxplot(request):
"""Generation of boxplots to be moved to computation server"""
# Get the selected columns from the overview view
selected_columns = request.GET['selectedColumns']
selected_columns = json.loads(selected_columns)
code, boxplot_html = generate_plots(selected_columns, request.session.get('dataframe'))
if boxplot_html is not None:
return HttpResponse(status=code, content=boxplot_html)
else:
error = "Could not create your plots"
return HttpResponse(status=code, content=error)
models.py
def get_upload_path(instance, filename):
return "user_{}/{}".format(instance.user.pk, filename)
class Dataset(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True)
dataset_name = models.CharField(max_length=100)
date_added = models.DateTimeField(auto_now_add=True)
dataset_file = models.FileField(upload_to=get_upload_path)
def __str__(self):
return self.dataset_name
def save(self, *args, **kwargs):
user = CustomUser.objects.get(username=self.user)
if user.num_datasets == user.max_datasets:
return # Exceeding the max number of datasets
else:
user.num_datasets += 1
user.save()
super().save(*args, **kwargs)
def delete(self, *args, **kwargs):
user = CustomUser.objects.get(username=self.user)
user.num_datasets -= 1
user.save()
super().delete(*args, **kwargs)
python django
python django
edited Nov 27 at 12:38
200_success
127k15149412
127k15149412
asked Nov 26 at 20:44
awcot
61
61
add a comment |
add a comment |
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f208478%2fdjango-model-and-views-to-summarize-and-plot-an-uploaded-csv%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown