Django how to add value from model into another application's view? - python

I have 2 applications in my "aplikacja" django project:
articles
qr
From articles model I would like to get a value "title" from the first article and then put it into qr.views (it prepares for me a pdf file)
Articles models:
from django.db import models
class Article(models.Model):
title = models.CharField(max_length=150)
content = models.TextField(verbose_name="Zawartosc")
published = models.DateTimeField(verbose_name="Data Publikacji")
How to get a "title" value into qr views?
I suppose I need to import article from aplikacja.articles.models. But how to get exactly value in test_qr method?
from reportlab.pdfgen import canvas
from django.http import HttpResponse
from reportlab.graphics.shapes import Drawing
from reportlab.graphics.barcode.qr import QrCodeWidget
from reportlab.graphics import renderPDF
from django.contrib.auth.models import User
from aplikacja.articles.models import article
def test_qr(request):
# Create the HttpResponse object with the appropriate PDF headers.
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename="somefilename.pdf"'
a= map(lambda x: str(x), User.objects.values_list('id', flat=True).order_by('id'))
p = canvas.Canvas(response)
p.drawString(10, 800, a[1])
qrw = QrCodeWidget(a[1])
b = qrw.getBounds()
w=b[2]-b[0]
h=b[3]-b[1]
d = Drawing(200,200,transform=[200./w,0,0,200./h,0,0])
d.add(qrw)
renderPDF.draw(d, p, 1, 1)
p.showPage()
p.save()
return response

To get the first article use the first() method:
article = article.objects.all().order_by('published').first()
title = article.title if article else None
BTW python lists are zero based so to get the first element of a list you should use a[0] instead of a[1]. But anyway I suggest you to use the same first() method to get the id of the first user:
first_user_id = str(User.objects.values_list('id', flat=True) \
.order_by('id').first())

Related

How to use while loop for showing more items in Django view?

I am making a small Django project, but I have an issue. When I write names to one form and topics to other one and press button, I want to see list of randomly attached names and topics. In my current code I donĀ“t get a list but just one name and one topic. How can I solve that problem?
My views.py file:
from django.shortcuts import render
from .losovaci_zarizeni import UvodniTabulka
from random import choice
def losovani_view(request):
form = UvodniTabulka(request.GET)
spoluzaci = request.GET.get("spoluzaci")
temata = request.GET.get("temata")
spoluzaci_list = spoluzaci.split()
temata_list = temata.split()
while True:
spoluzak = choice(spoluzaci_list)
spoluzaci_list.remove(spoluzak)
tema = choice(temata_list)
temata_list.remove(tema)
if len(spoluzaci_list)==0:
break
return render(request, "losovani.html", {"form":form, "spoluzak": spoluzak, "tema":tema})
My file with UvodniTabulka:
from django import forms
class UvodniTabulka(forms.Form):
spoluzaci = forms.CharField(max_length=500)
temata = forms.CharField(max_length=500)

How to fetch data from another app Django

I'm creating a quiz project using Django with MongoEngine. Multiple Choice Questions and quiz are two separated apps. I want to fetch multiple choice in quiz based on m_id (unique number for each multiple choice). I'm a beginner and need a little help. How can i achieve thisMCQS Model
from django_mongoengine import Document, EmbeddedDocument, fields
class multichoice(Document):
m_id = fields.IntField(min_value=1, verbose_name='MCQ Id')
m_title = fields.StringField(primary_key=True, max_length=255, verbose_name='Title')
m_question = fields.StringField(verbose_name='Question')
m_alternatives = fields.ListField(fields.StringField(),verbose_name='Alternatives')
def __str__(self):
return self.m_title
Quiz Model
from django_mongoengine import Document, EmbeddedDocument, fields
from mcqs.models import *
class quiz(Document):
q_id = fields.IntField(min_value=1, verbose_name='Quiz ID')
q_title = fields.StringField(primary_key=True, max_length=255, verbose_name='Title')
q_s_description = fields.StringField(max_length=255, verbose_name='Description')
q_questions = fields.ListField(fields.IntField(), verbose_name='Question Numbers', blank=True)
def __str__(self):
return self.q_title
MCQ Views
def view_multichoice(request, m_id):
get_md = multichoice.objects(m_question_number = m_id)
return render(request, 'mcqs/mcq.html', {'get_md':get_md})
Quiz Views
def view_quiz(request, q_id):
get_q = quiz.objects(q_id = q_id)
return render(request, 'quiz/quiz.html', {'get_q':get_q})
Current Result
Expected Result
EDIT 1
Quiz Views
from django.shortcuts import render
from django.http import HttpResponse
from .models import *
from mcqs.models import *
def view_quiz(request, q_id):
quiz_object = quiz.objects(q_id=q_id)[0]
multichoice_objects = [multichoice.objects(m_id=id) for id in quiz_object.q_questions]
get_q = [objects[0].m_question for objects in multichoice_objects if objects]
return render(request, 'quiz/quiz.html', {'get_q':get_q})
Quiz Template
{{ get_q }}
You are returning the question documents as it is. What you should be doing is, fetch the multichoice documents corresponding to the question ids, and then get the question field from each of those documents.
Change the second line in quiz views to this:
# Get the question document corresponding to given id
# objects method returns a list. Get the first one out of it.
# Here, I've assumed there's exactly 1 quiz document per ID. Handle the edge cases
quiz_object = quiz.objects(q_id = q_id)[0]
# Get the multiple choice documents corresponding to the ids in q_questions list
# Remember that objects method returns a list. Hence this is a list of lists
multichoice_objects = [multichoice.objects(m_id=id) for id in quiz_object.q_questions]
# Get the actual questions from the multichoice documents
get_q = [objects[0].m_question for objects in multichoice_objects if objects]
Ideally, you should be making multichoice as an EmbeddedDocument and the q_questions field in quiz model as EmbeddedDocumentListField. But the drawback here will be, you can't query EmbeddedDocuments independently. So you wont be able to do multichoice.objects(m_question_number=m_id).
You can read more about EmbeddedDocuments here

Sending plot image/object in addition to model query result and other variables to Django template

Please keep in mind that I am new to Django and web programming in general.
I am trying to do something that seems like it should be simple but I can't figure it out:
I have an 'object viewer' template that I am using to display information about a single selected object from the database and I want to include a graph on the page.
models.py:
class MaxExtent(models.Model):
id = models.IntegerField(primary_key=True)
geoName = models.CharField('Geounit name (territories are unique geounits)', max_length=40, null=True)
sovereignty = models.CharField('Sovereign country name', max_length=32, null=True)
lakeName = models.CharField('GLWD Lake name', max_length=50)
areaMax = models.FloatField('Max Extent area (km^2)')
area2000 = models.FloatField('2000 area (km^2)')
area2001 = models.FloatField('2001 area (km^2)')
area2002 = models.FloatField('2002 area (km^2)')
area2003 = models.FloatField('2003 area (km^2)')
area2004 = models.FloatField('2004 area (km^2)')
area2005 = models.FloatField('2005 area (km^2)')
area2006 = models.FloatField('2006 area (km^2)')
centerLat = models.FloatField('Latitude of centroid')
centerLon = models.FloatField('Longitude of centroid')
poly = models.MultiPolygonField()
def __str__(self): # default field for string representation
if self.lakeName:
return "ID {}: {} ({}, {})".format(self.id, self.lakeName, self.centerLon, self.centerLat)
else:
return "ID {}: Not named ({}, {})".format(self.id, self.centerLon, self.centerLat)
views.py:
from django.shortcuts import get_object_or_404, render
from django.forms import ModelForm
from .models import MaxExtent
from .functions import chart_object_areas
# Object viewer
def objectViewer(request, req_id):
waterBody = get_object_or_404(MaxExtent, pk = req_id)
displayFields = [str(f.name) for f in MaxExtent._meta.get_fields()]
class MaxExtentForm(ModelForm):
class Meta:
model = MaxExtent
fields = displayFields
fields = MaxExtentForm(instance=waterBody)
areas = [waterBody.area2000, waterBody.area2001, waterBody.area2002, waterBody.area2003, waterBody.area2004, waterBody.area2005, waterBody.area2006]
years = [yr for yr in range(2000,2007)]
# get the bar plot with best fit line on top
return_chart = chart_object_areas(X = years, Y = areas, waterBody.slope, waterBody.intercept) # UPDATE
context = {'waterBody': waterBody, 'displayFields': fields, 'chart': return_chart} # UPDATE - tried sending object to template
return render(request, 'waterExplorer/objectViewer.html', context)
I can show the template code but I don't think it would be helpful. Just know it successfully displays attribute information using the waterBody and displayFields, along with a map of the object.
Now for my question...
I am following tutorial here, which uses matplotlib to create a chart and render it in the template. I am trying to create a simple bar chart using information from the model (area2000 to area2006 as my Y's and year--2000, 2001, ..., 2006 as the X). I have a script that creates this graph based on info retrieved from the model (functions.chart_object_area); currently using matplotlib like in the tutorial. This gets called in views.py and returns the object to be rendered, following example 1 (see example and views.py above)
However, how to return f.getValue() in addition to waterBody and displayFields parameters? The tutorial returns the chart like so:
return HttpResponse(f.getvalue(), content_type="image/png")
But I am returning:
context = {'waterBody': waterBody, 'displayFields': form}
So how do I combine the two so I can display the plot in addition to the other stuff I already have?
I am using Django version 1.11
UPDATE: I've updated the code in views.py to indicate how I am getting the variables I'm sending to my chart function (see # UPDATE) and am adding the chart_object_areas function here. I also updated in views.py to show that I tried passing the output plot to the template:
functions.py:
import sys
from django.http import HttpResponse
import matplotlib as mpl
mpl.use('Agg') # Required to redirect locally
import matplotlib.pyplot as plt
import numpy as np
from numpy.random import rand
import cStringIO
def chart_object_areas(X, Y, slope, intercept):
plt.ylim(0.0, np.max(Y)+(np.mean(Y)/3))
plt.xlim(np.min(X)-1, np.max(X)+1)
plt.ylabel('Area ($km^2$)')
plt.xlabel('Year')
plt.bar(X, Y)
# plot the best fit line too
fitY = [(slope*x + intercept) for x,d in enumerate(X)]
plt.plot(X, fitY, color='black')
plt.savefig('test-plot.png')
f = cStringIO.StringIO() # redirect per tutorial
plt.savefig(f, format="png", facecolor=(0.95,0.95,0.95))
plt.clf()
return f.getvalue() # per tutorial
As you can see, I saved the figure and confirmed that the function is producing a plot. However, when I try to render it in the template like so:
{{ chart | safe }}
Nothing shows up. I am assuming this is because of the way I'm passing to template [in the tutorial, he uses content_type="image/png" when returning the response, and I don't know how to do that as I am sending context to render()].
Again, I am following the tutorial here to learn for using matplotlib in Django.

Value Error trying to get data from mysql in django

I'm running a django app and I've implemented MySQL. When I run the server and try to load the page I get the error "badly formed hexadecimal UUID string." This occurs in the uuid.py file in init at line 140 and from what I can tell, this occurs because the value hex is not of length 32 but I don't know how to address this issue.
This is the model that the entries in the database follow.
from django.db import models
import uuid
from django.db.models import (
UUIDField,
CharField,
TextField,
IntegerField,
DecimalField,
ImageField
)
# Create your models here.
class AnimeCatalog(models.Model):
anime_id = UUIDField(primary_key = True, default=uuid.uuid4, editable=False)
name = CharField(max_length=300)
genre = CharField(max_length=300)
typeanime = CharField(max_length = 10)
episodes = IntegerField(default=0)
rating = DecimalField(max_digits = 4, decimal_places = 2, null = True)
members = IntegerField()
anime_cover = ImageField(blank = True, null = True, upload_to = "img/animeCover", verbose_name = "Profile Photo")
Then I try to call the objects.all() method on this model to retrieve it from mysql in the views.py file which is below
from django.shortcuts import render
from django.http import HttpResponse, HttpResponseRedirect
from django.views import View
from .forms import AnimeCatalogForm
from .models import AnimeCatalog
from .WebScraping import findAnimePic
import csv
from django.core.paginator import Paginator
# Create your views here.
def home(request):
temp = []
tempID = []
pics = []
fiveNames = []
names = []
new = AnimeCatalog.objects.all()
for line in new:
temp.append(line['name'].replace(''', ''))
tempID.append(line['anime_id'])
for x in range(0,5):
pics.append(findAnimePic(tempID[x],temp[x]))
for x in range(0, len(temp), 5):
for y in range (5):
if not(x+y >= len(temp)):
fiveNames.append({'name':temp[x+y],'img':pics[y]})
names.append(fiveNames)
fiveNames = []
items = {'names': names, 'imgs': pics}
html = render(request, 'home/home.html', {'names':names})
return html
Also this is a picture of the first few entries in the mysql which i imported a csv file.
Image of mysql database with imported csv files
As is clear from that screenshot, anime_id contains integers, not UUIDs. I don't know why you set it to be a UUIDField but you should use AutoField instead and remove the default.

How to return JSON Response correctly in joining multiple table in Django

Currently I am using Django 1.10.
For example we have the models below:
class ModelOne(models.Model):
description = models.CharField(max_length = 50)
class ModelTwo(models.Model):
description = models.CharField(max_length = 50)
m1 = models.ForeignKey( ModelOne)
class ModelThree(models.Model):
description = models.CharField(max_length = 50)
m2 = models.ForeignKey(ModelTwo)
Everytime a request is made then a JSON response is return using the code below:
from app.models import *
from django.http import HttpRequest,JsonResponse
def ViewThatReceiveRequest(request):
qs = list(ModelThree.objects.filter(description__icontains='beauty').select_related('m2__m1')
data = []
for key in qs:
temp_obj = {}
# if necessary I will convert the values before equating
temp_obj['desc3'] = key.description
temp_obj['desc2'] = key.m2.description
temp_obj['desc1'] = key.m2.m1.description
data.append(temp_obj)
return JsonResponse( {'message' : 'success', 'qs' : data }, safe = False)
Note:
- I am using Django as my back-end and ReactJs for my front-end so I only need JSON Response
My question,
- Do I need to do these for every views that receive request?
- Do we have other way to solve these simpler?
Since you only need description field from all 3 models, you can also use values method or maybe values_list of the queryset and get data.
So this new query would be
ModelThree.objects.filter(description__icontains='beauty').select_related('m2__m1).values_list('description','m2__description','m2__m1__description')
Next if you want to run some changes to your data, you can run a map method in case you want to make similar changes to all the data.
Next you can make the appropriate json and send to to client side.

Categories

Resources