How can I pass my sqlite data to django, and make chart? - django

I'm trying to make line chart using data in sqlite database.
But I have no idea how to pass my data to views.py and html template file.
I want to make line chart ( x-axle : date , y-axle : count by date )
I tried to make it using raw queryset and other things...
requestCnt = ActivityLog.objects.raw("SELECT date(doDate), count(requestType) FROM mainApp_activitylog GROUP BY doDate")
OR
requestCnt = ActivityLog.objects.values('doDate').annotate(Count('requestType'))
AND ETC...
Models.py
class ActivityLog(models.Model):
doDate = model.DateTimeField()
userIP = models.CharField(max_length=200)
userName =models.CharField(max_length=200)
requestType = models.CharField(max_length=200)
Below is my raw sqlite query.
sqlite> SELECT date(doDate), count(requestType) FROM mainApp_activitylog GROUP BY doDate;
and the result is as below
2019-04-15|3
2019-04-16|16
2019-04-17|13
2019-04-18|10
2019-04-19|13
2019-04-22|24
How can I pass those results above to X-Axle and Y-axle ?
I want to make line chart (X-Axle:date , Y-axle: request count by date)
I have a little idea that I should use Json dumps or things like that.
I've already encountered error such as " cannot be serialized as Json file (?) "
I really hope someone can solve my problem.
Thx for your help in advance.

You can send the queryset to the template in the context and use the values there.
class YourTemplate(TemplateView):
def get_context_data(self, **kwargs):
requestCnt = ActivityLog.objects.annotate(request_count=Count('requestType')).values('doDate', 'request_count')
context = super().get_context_data(**kwargs)
context["data"] = requestCnt
return context
Then in your template, you can use data variable to get the data for both the axis. The data will be of the format:
[{"doDate":"...", "request_count":"..."}, {"doDate":"...", "request_count":"..."}]

Related

Django-tables2 - how can I get counts out in my table on a custom table field?

I'm trying to get some frequency data out from my queryset in a column in my table in django-tables2.
I am trying this via a custom field:
class MyTable(tables.Table):
custom_field = tables.Column(empty_values=())
def render_custom_field(self):
total_queryset = self.data.data
# trying to get out the row object, to do a filter query something like:
row_object = self.rows.instance
freq = total_queryset.filter(myfield=row_object.myfield)
return f"{len(freq)}/{len(total_queryset)}"
However I cannot get the row instance out to do this query. Does anyone know how I can get the row instance out to do this? (I'm also aware getting the total_queryset from self.data.data is probably a hacky way of doing this...)
Thanks!
record is available as a direct argument, as well if your data is a QuerySet you can also use the .count() method.
def render_custom_field(self, record):
return self.data.data.filter(myfield=record.myfield).count()
Figured it out - you get the row instances from kwargs:
def render_custom_field(self, *args, **kwargs):
total_queryset = self.data.data
obj = kwargs['record']
freq = total_queryset.filter(myfield=row_object.myfield)
return len(freq)

ReportLab get_FOO_display() Not Working On A List

Ive created a form which users fill out, then it uses reportlab to create a pdf of their answers.
It works well except for a charfield (preferred_topics) which contains a list. Data is saved like this:
['ANI', 'EDU', 'ENV']
I think that might be a problem as id exect it to save the data like this:
[['ANI'], ['EDU'], ['ENV']]
However it works fine on the website.
So to print human readable data to the pdf im using get_FOO_display(), but this doesnt work for preferred_topics. If i call (user.personalinformation.get_preferred_topics_display() i get:
AttributeError at /enrolment/final_question/
'PersonalInformation' object has no attribute 'get_preferred_topics_display'
Here is my other relevant code:
model.py
preferred_topics = models.CharField(max_length=200, default='')
utils.py
# generate pdf
def generate_pdf(request):
# get user
user = request.user
# data that will be printed to the pdf
page_contents = [
['Personal Information'],
['Name:', '%s %s' %(user.personalinformation.first_name, user.personalinformation.surname)],
['E-mail:', '%s' %(user.email)],
['Gender:', '%s' %(user.personalinformation.get_gender_display())],
# this field is causing grief
['Preferred Topics:', '%s' %(user.personalinformation.preferred_topics)]
]
forms.py
TOPICS = (
('ANI', 'Animals'),
('ART', 'Art'),
('COM', 'Communication'),
('CRI', 'Crime'),
)
preferred_topics = forms.MultipleChoiceField(choices=TOPICS, required=False, widget=forms.CheckboxSelectMultiple())
Im expecting to be told that the data is being saved wrongly in my db, but dont know how to change it, and wanted confirmation before i started changing previously working stuff as im sure i will break currently working things in the process.
SUMMARY - i want to use user.personalinformation.get_preferred_topics_display() but its not working and i suspect its because the data is being saved wrongly in the db but would like confirmation before i go wrecking stuff.
Thank you.
You are saving multiple choices as single string which is not good idea as you would have hard time filtering and working with this kind of data ( rather use Arrayfield of choices)
There is no get_FOO_display() without choices on models field so you would need to write your own converter
# create dict of options
options = dict((y,x) for y,x in PersonalInformationForm.TOPICS)
# evaluate string to list
selected_choices = ast.literal_eval(testobj2.preferred_topics)
# find choices in dict
selected values = [option.get(key) for key in selected_choices]

Django validate data when updating model with primary key

I am having trouble with updating fields of a model instance. The model is as follows:
class commonInfo(models.Model):
mothers_id = models.IntegerField(primary_key=True)
date = models.DateField()
data_collector = models.CharField(max_length=50)
Essentially, I just want to do this, but it won't work because commonInfo has a user defined primary key
commonInfo_form(request.POST or None).is_valid()
Since I am updating, I am overriding date and data_collector, but not mothers_id. So I would want to do something like this, but this specific code is not working
obj = commonInfo.objects.get(pk=commonInfo_id)
form = commonInfo_form(request.POST)
date = form.cleaned_data['data_collector'] #this line is not working
data_collector = form.cleaned_data['data_collector'] #this line is not working
obj.update(**{'date':date, 'data_collector':data_collector})
any ideas? I feel like it is just those two lines that I need to fix. Or if there is a more pythonic way or built method in Django?
Just validate with isinstance. so like,
if isinstance(request.POST['date'], datetime.date) and isinstance(request.POST['data_collector'], str):
# you might have to use getattr for request.POST here, I'm not sure
# and request.POST['date'] would have to be converted from a string to datetime.date I think
date = request.POST['date']
data_collector = request.POST['data_collector']
obj.update(**{'date':date, 'data_collector':data_collector})
The process for adding a record from a form is different from updating an existing instance. All you need to do differently is indicate which instance to bind the form to when you create it, ex:
obj = commonInfo.objects.get(pk=commonInfo_id)
form = commonInfo_form(request.POST, instance=obj)

update django choice field with database results

I am developing an application using django where the UI needs to be updated when user interacts with it. For instance I have a Drop down field where the user selects a drink and submits it then based on that a dropdown with the places that drink is available, price and quantity at each place needs to be displayed. The user will then further submit the form for second process.
From my understanding the Forms in django are pre-defined and I am not able to think of a way using which I could achieve this.
What I could come up was defining a regular form class
class dform(forms.Form):
SOURCES_CHOICES = (
(A, 'A'),
(E, 'E'),
)
drink = forms.ChoiceField(choices = SOURCES_CHOICES)
location = forms.ChoiceField(choices = **GET THIS FROM DATABASE**)
quantity = forms.ChoiceField(choices = **GET THIS FROM DATABASE**)
.
.
.
My view is like,
def getdrink():
if request.method == 'POST':
#code for handling form
drink = dform.cleaned_data['drink']
#code to get values from database
I have no idea how to generate or populate or append the values i get from the database to the choicefield in my form. I did try looking up on SO but none of the solutions here explained properly how to do it. Also, due to certain requirements I am not using the models. So my database is not at all related to the models.
I am at a total loss Please help me out
class MyForm(forms.Form):
my_choice_field = forms.ChoiceField(choices=MY_CHOICES)
So if you want the values to be dynamic(or dependent of some logic) you can simply modify your code to something like this:
either
def get_my_choices():
# you place some logic here
return choices_list
class MyForm(forms.Form):
my_choice_field = forms.ChoiceField(choices=get_my_choices())
or
User_list = [ #place logic here]
class MyForm(forms.Form):
my_choice_field = forms.ChoiceField(choices=get_my_choices())
but once database value is updated, new data value will be popoulated only on restart of server.
So write a function like this in forms:
class MyForm(forms.Form):
def __init__(self, *args, **kwargs):
super(MyForm, self).__init__(*args, **kwargs)
self.fields['my_choice_field'] = forms.ChoiceField( choices=get_my_choices() )
or in place of the get_my_choices u can ad the USER_LIST too.
If you have models for location and quantity, a ModelChoiceField should work:
class dform(forms.Form):
location = forms.ModelChoiceField(queryset = Location.objects.all())
Otherwise, you'll need to query the database directly, for example:
class dform(forms.Form):
location = forms.ChoiceField(choices = get_location_choices())
# elsewhere
from django.db import connection
def get_location_choices():
cursor = connection.cursor()
cursor.execute("select location_id, name from location_table")
return cursor.fetchall()
The SQL query to use here depends on your database engine and table schema.
I think that, based on my understanding of your question, the best solution would be to include JSON objects with your form and load these using jQuery instead of submitting the form over and over. Included in your form, you should add something like:
class MyForm(forms.Form):
CHOICE_DICT = {
'choice_1': [
'option_1',
'option_2',
],
etc...
Then you should include form.CHOICE_DICT in your context, load that with jQuery, and render it depending on changes to other fields.

how to render datatable inside ajax-modal in openstack horizon dashboard?

i'm beginner in Python Django. according to openstack's customizing horizon dashboard tutorial i've successfully added new panel, tab with datatable. i also added table actions in table class which open ajax-modal. but instead of render form inside that i need to render datatable which should feel up by ajax-response. each row contains form input element (e.g text,radio). but i couldn't figure out how to render datatable inside ajax-modal.
please have a look on tables.py
class AddSwitch(tables.LinkAction):
name = "addswitch"
verbose_name = _("Add Switch")
url = "horizon:project:sdncontroller:addswitch"
classes = ("ajax-modal", "btn-create",)
class Switches(tables.DataTable):
dpid = tables.Column("dpid",verbose_name=_("DPID"))
address = tables.Column('address', verbose_name=_("Address"))
vendor = tables.Column('vendor', verbose_name=_("Vendor"))
packets = tables.Column('packets', verbose_name=_("Packets"))
bytes = tables.Column('bytes', verbose_name=_("Bytes"))
flows = tables.Column('flows', verbose_name=_("Flows"))
connectedsince = tables.Column('connectedsince', verbose_name=_("ConnectedSince"))
detail= tables.Column('details', verbose_name=_("Detail"))
class Meta:
name = "Switches"
verbose_name = _("Switches")
table_actions = (AddSwitch,)
also i've created workflows.py and create class for AddSwitch
class AddSwitch(workflows.Workflow):
slug = "addswitch"
name = _("Add Switch")
finalize_button_name = _("Add")
success_message = _('Added switch "%s".')
failure_message = _('Unable to add switch "%s".')
success_url = "horizon:project:sdncontroller:index"
default_steps = (AddSwitchStep,)
def format_status_message(self, message):
name = self.context.get('name')
return message % name
def handle(self, request, context):
try:
#api.lbaas.pool_create(request, **context)
return True
except Exception:
return False
this is the point where i stuck. i don't how to code and where to code for rendering datatable and that too fill up dynamically through ajax-response.
Thanks, I hope someone who could lead me into this.
You forgot to mention the "columns" attribute in the Class Meta. Please follow the mechanism currently used by Horizon to render the "Instances" data table. You can find the detailed step by step tutorial to create and render a data table here: http://docs.openstack.org/developer/horizon/topics/tutorial.html
Hope it helps