D3.js Directed Graph Django Integration - python

I have a simple Django application that queries a database and displays the fields of the objects returned. I was wondering what would be the best way to go about integrating this directed graph visualisation into my project; I've never worked with d3 until now.
Allow me to explain my application. At the moment, it's simply a form that allows users to query contents of the database regarding information on books, by entering the unique ID of a book. This works fine, the contents are displayed through the use of a template.
What I wish to do is used one of the fields of the queried objects to push data into the graph example above, and simply display this graph in a new window when a text-link is pressed.
Here's my application structure:
Code
myapp.models.py:
from django.db import models
class Book(models.Model):
uid = models.IntegerField(primary_key=True)
title = models.CharField(max_length=30)
related_books = models.CharField(max_length=2048)
class Meta:
db_table = u'books'
The field related_books contains the data I wish to graph. The data is stored in the format rel_book1 rel_book2 rel_book3 ... where each book is related to the queried Book object, there are n related books for each object, but there is at least always two.
myproject.templates.search.html:
<form action="" method="get">
<label for="id_q">Search:</label>
<input id="id_q" name="q" type="text">
<input type="submit" value="Submit">
{% if found_entries %}
<ul>
{% for i in found_entries %}
{{ i.uid }} {{ i.title }} {{ value|linebreaks }}
{% endfor %}
</ul>
{% endif %}
</form>
So this is where I'd like to display the graph; in a new window when a text-link is pressed.
myapp.views.py:
from django.shortcuts import render_to_response
from django.template import RequestContext
from myapp.search import get_query
from myapp.models import Book
def search(request):
query_string = ''
found_entries = None
if ('q' in request.GET) and request.GET['q']:
query_string = request.GET['q']
found_entries = Book.objects.filter(uid=query_string)
return render_to_response('search.html',
{ 'query_string': query_string, 'found_entries': found_entries },
context_instance=RequestContext(request))
So just to reiterate, a user enter a unique ID for a given book and contents of the database related to that book are displayed. At the moment the ID and title are displayed, I'd also like to display a link to the directed graph example.
So my question is, how would I go about extracting the information out of the field related_books when the Book model is queried, so that I can push this data into the graph example to generate graphs for each Book object generated?
Thanks for bearing with me!

It seems to me you already have enough information. Your view returns book objects that match the filter, and related_books is a member of the Book class.
You'd simply need to generate a link on the fly by iterating over the related_books attribute of each book, e.g.
{% for book in found_entries %}
# print out whatever results here
<a href="graphing_page.html?contents=
{% for content in book.related_books %}content{% endfor %}
">Graph this</a>
{% endfor %}
I'm not sure what parameters the d3 library takes, but a list of connected components seems reasonable.

Related

How to frequently update some particular field in database?

This is my model to store bus details. Here I have kept a field named bookedSeat to store which seat is booked ( input a-z or A-Z ).Every-time user book a seat a single character (inputted from user) should be added to bookedSeat field in database.
class busDetails(models.Model):
busID = models.AutoField(primary_key=True)
arrival = models.CharField(max_length=50)
destination = models.CharField(max_length=50)
rent = models.IntegerField()
distance = models.IntegerField()
bookedSeat = models.CharField(max_length=100)
def __str__(self):
return self.arrival+' --> '+self.destination
I am getting stuck at how to frequently update(add into existing) that particular database field(bookedSeat)? (without adding any new row)
How do you solve this problem?
Thank You :)
Create an updateview for that Model and specify the fields that you would like to update. You can use a custom form, But trust me these generic views will save you a lot of time .
views.py :
from django.views.generic.edit import UpdateView
class updimagesUpdateView(UpdateView):
model = updimages
fields = ['approval']
template_name_suffix = '_update_form'
Of all the attributes, you can mention the ones you need to be updated.
As shown in the last line above (template_name_suffix) , use the same naming suffix pattern for the template... [modelname_update_form.html] and display the form...
modelname_update_form.html :
{% extends "base.html" %}
{% load static %}
{% load bootstrap_tags %}
{% block title %} Update {% endblock %}
{% block body%}
<div class="jumbotron">
Are you sure you want to approve the Image ?
</div>
<br>
<form method="POST">
{% csrf_token %}
{{ form|as_bootstrap }}
<input type="submit" value="Submit" />
</form>
{% endblock %}
make sure you get the corresponding element you want to update from the template :
<h3>update</h3>
clicking the above triggers the url. Add the urls ,
urls.py:
path('update/<int:pk>', views.updimagesUpdateView.as_view() , name = "update"),
PS: You can also update values from views using queries to select the desired object and then editing them like this ,
in views.py :
example = model.objects.filter(id=images.id).update(content=txt)
check out the documentation for more info :
https://docs.djangoproject.com/en/3.1/ref/class-based-views/generic-editing/

Get model attributes without making them required for modelform_factory?

I've got a modelform_factory which works perfect for what I need.
I call it like this:
dep_formset = modelformset_factory(
Dependent,
fields=('has_medical', 'med_group_id'),
max_num = dep_count
)
As you might guess, Dependent has additional fields that I want to use simply for display purposes (first_name and last_name respectively) I want to show the first_name and last_name of the dependent person - but have it be simply for display, not edit.
If I add 'first_name' and 'last_name' to the fields in the above, I can then access them in my template - but the form fails against .is_valid() because I'm displaying them simply as text and not as an input, so they're not being POST'ed
Is there some clever way to get access to the first_name and last_name of the dependent objects without adding them to fields for the formset_factory?
The template looks like this (partial snippet so you can see what I'm trying to do with the first_name, last_name):
{% for form in dep_formset %}
{{ form.id }}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
<div class="g">
<h4>{{ form.first_name.value }} {{form.last_name.value}}</h4>
</div>
<div class="g dependent-option">
<div class="g-1-4 dependent-option-check">
{% if form.has_medical %}
Based on provided information it looks like the formset is tied to an instance which you can access in template:
{{ form.instance.first_name }}

Duplicate query for every form in the formset

In my django application I have users which can have multiple positions. ie: The Position model has a foreign key to the User model. By using a django modelformset_factory I output all the positions associated to the currently logged in user as follows:
Views.py:
class ABCUpdate(View):
def get(self, request):
user = request.user
PositionFormSet = modelformset_factory(Position)
formset = PositionFormSet(queryset=user.position_set.all().prefetch_related('symbol'))
return render(request,
'some_template.html',
{'formset': formset})
some_template.html
<form action="#" method="post">
{% csrf_token %}
{{ formset.management_form }}
{% for position in formset %}
<div class="row">
{{ position }}
</div>
{% endfor %}
<button type="submit">
Update
</button>
</form>
Position model:
class Position(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL)
symbol = models.OneToOneField(Symbol)
# more fields...
One of the fields on some_template.html is the symbol field (ie: the one for which I am using prefetch_related in the above snippets). Symbol is from a different model using a foreign key. This means that on the html template, the symbol field is a dropdown allowing the user to select the desired symbol.
This all works correctly, however the problem is that the database is being queried for every single form in the formset to retrieve the list of symbol's. For example if the user has 10 positions, then each position will have a dropdown for symbol,...which results in a separate database query to retrieve all the symbols.
How do I go about just doing one query for all the available symbol's and using that for the dropdown in every form in the formset?
I think you should point in prefetch_related all the fields of the model Position that have a link to another model, in your cases you must add field user:
PositionFormSet(queryset=user.position_set.all().prefetch_related('symbol', 'user')).
P.S. it worked for me.

How do I use the same view with two different forms and don’t loose the data provided by the user with Flask?

I have a form with several input fields about a meeting.
#app.route('/Alt_Reuniao/<WCodigoChaveP>', methods=['GET', 'POST'])
def Alt_Reuniao(WCodigoChaveP):
# This function returns a list with de data from the Database about a specific meeting
WReuniao = Executa_Query_Leitura("0005", WCodigoChaveP, "O")
if not WReuniao:
flash('Error.......')
return redirect(url_for('Cad_Reunioes'))
else:
if WReuniao[8]:
# this function returns a list with de data from the Database about the topic of the meeting
WAssunto = Executa_Query_Leitura("0002", WReuniao[8], "O")
Wform = Cad_Reunioes_Form()
if request.method == "POST":
if Wform.validate():
# save the data ......
return redirect(url_for('Cad_Reunioes'))
else:
for Werro in Wform.errors.values():
flash(Werro[0])
return render_template('Reuniao.html', Wformulario=Wform)
else:
Wform.WCPO_Reuniao.data = WReuniao[1]
Wform.WCPO_Desc_Reuniao.data = WReuniao[2]
Wform.WCPO_Nro_Part.data = WReuniao[3]
Wform.WCPO_Cod_Assunto.data = WReuniao[8]
if WReuniao[8]:
if WAssunto:
Wform.WCPO_Assunto.data = WAssunto[1]
return render_template('Reuniao.html', Wformulario=Wform)
This is my Reuniao.html template:
{% extends "Base_Cad_2.html" %}
{% block dados %}
{{ Wformulario.WCPO_Reuniao.label(id="WCPO_Reuniao", class="lab1") }} {{ Wformulario.WCPO_Reuniao(size = 100, maxlength=30, id="WCPO_Reuniao") }}
<p id="PL"> {{ Wformulario.WCPO_L_Desc_Reuniao(id="WCPO_L_Desc_Reuniao", class="lab1") }} </p>
{{ Wformulario.WCPO_Desc_Reuniao(rows=5, cols=100, id="WCPO_Desc_Reuniao") }}
{{ Wformulario.WCPO_Nro_Part.label(id="WCPO_Nro_Part", class="lab1") }} {{ Wformulario.WCPO_Nro_Part(size = 5, id="WCPO_Nro_Part") }}
{{ Wformulario.WCPO_Cod_Assunto.label(id="WCPO_Cod_Assunto", class="lab1") }} {{ Wformulario.WCPO_Cod_Assunto(size=10, readonly='readonly', id="WCPO_Cod_Assunto") }}
{{ Wformulario.WCPO_Assunto.label(id="WCPO_Assunto", class="lab1") }} {{ Wformulario.WCPO_Assunto(size=95, readonly='readonly', id="WCPO_Assunto") }}
<button id="Selec_Assunto" name="Selec_Assunto" value="Selec_Assunto" type="button"> <a class="botoes" href="{{ url_for('Selec_Assuntos_Inicio', WRotChama = "001", WCodorig = Wformulario.WCPO_Cod_Reuniao ) }}" hreflang="pt-br"> Seleciona </a> </button>
{% endblock %}
{% block botoes %}
<button id="gravar" name="gravar" value="Gravar" type="submit" class="botoes" > Gravar </button>
{% endblock %}
Basically, this view works fine.
When I select a meeting from a list in a previous template the view method is a GET and the data from the database is passed to the form and the template renders correctly.
When the method is a POST the data from the form is saved correctly in the Database,…
On the form there is a button Selec_Assunto. When the user click on that button I point to a view witch renders a template with a list of all possible topics for the meeting. These topics come from the database. There can be a lot of them so I can’t just use a combo. That’s why I use a template.
When the user select an topic from the list I have to render Alt_Reuniao view again and I have to pass to the view the selected topic.
This is working fine.
My problem is this: the method again is a GET. If before hitting the Selec_Assunto button the user alter or input data on the other fields in the form I loose these data from the user when the topic is selected. The view render the template with the data from the database again.
Everything seems to be working fine. I just want to maintain the data the user already change in the form before clicking on the Selec_Assunto button.
As you can see I’m new in Web developing, Python, Flask,…
Thanks a lot in advance for your help.
In this case you could update the "Selec_Assunto" button behavior to post the form data back to the server, but also include a redirect variable. When the redirect variable is included, the server would save the form changes and then redirect to the "Selec_Assuntos_Inicio" view, whereas it would follow the previous/normal form posting behavior if the redirect variable isn't present. For example:
if request.method == "POST":
if Wform.validate():
# save the data ……
if Wform.redirect.data:
return redirect(Wform.redirect.data)
else:
return redirect(url_for('Cad_Reunioes'))
else:
for Werro in Wform.errors.values():
flash(Werro[0])
return render_template('Reuniao.html', Wformulario=Wform)
It's worth noting that this approach requires you to use JavaScript to override the "Selec_Assunto" button behavior (as you'd be forcing it to perform a form submission essentially). Here's one way you could do that using jQuery:
$('button#Selec_Assunto').on('click', function() {
$('form#formId').append('<input type="hidden" name="redirect" value="{{ url_for('Selec_Assuntos_Inicio', WRotChama = "001", WCodorig = Wformulario.WCPO_Cod_Reuniao ) }}">');
$('form#formId').submit();
});
That said, a potentially better option from both a coding and usability perspective would be to asynchronously load the topic data into the existing page so that you don't have to reload the view at all. That would enable you to avoid needing to do an interim save of the form data.

A help in concept and a database query question (Django/Python)

I am trying to build a kind of news website for learning purposes.
class NewsCategory(models.Model):
category = models.CharField(max_length=50)
Note: A category can be Soccer, Tennis, business ... User can register to different news category. This choice will be saved in their preferences.
class Profile(models.Model):
user = models.ForeignKey(User, unique=True)
gender = models.CharField(max_length=1,blank=True)
preference = models.ManyToManyField(NewsCategory)
I am currently stuck on how to update the preference list of each user (the list that specifies in which categories he is interested in.)
View:
category = [(item.category) for item in NewsCategory.objects.all()]
and then I am sending the category to the template below
template:
<div id="c_b">
{% for c in category %}
<input type="checkbox" name="category[]" value="{{c}}">
<label for="{{c}}">{{c}}</label>
{% endfor %}
</div>
Questions:
What is the best way to add the checked tag next to the checkboxes that are already saved in the user's preference when I display the template.
I though of getting all the preferences users are registered for: saved_preference = user.preference.all() and then checking for each item in category if it is in saved_preference
I am also blanking out on the way to actually write that into code, and whether this should be done in the view or the template.
What is a good way to update the user preference list?
I was planning on running user.preference.clear() and then going through every item in the submitted form and running user.preference.add(the_new_preference)
You'll need to pass the complete list of categories and also an index of user-selected categories to your template. You don't need to convert the NewsCategory queryset into a list in your view, by the way:
View
categories = NewsCategory.objects.all()
user_preferences = [item.id for item in Profile.preference.all()]
The user_preferences variable will act as a lookup index for our template.
Then you loop through all the categories in the template, and check to see if it exists in the list of user preferences:
Template
<div id="c_b">
{% for c in categories %}
<input type="checkbox" name="category[]" id="id_{{ c.category }}" value="{{ c.id }}" {% if c.id in user_preferences %}checked="checked"{% endif %} />
<label for="id_{{ c.id }}">{{ c.category }}</label>
{% endfor %}
</div>
Update - saving user preferences
There is no hard and fast rule here. The main consideration, as far as I am concerned, would be minimising database hits. You can just clear the user preferences, like you say, and add the new ones - in fact, this is how Django's admin handles it. Just make use of Django's transaction management:
from django.db import transaction
#transaction.commit_manually
def add_preferences(user, preferences):
user.preference.clear()
for pref in preferences:
user.preference.add(pref)
transaction.commit()
You should learn about forms and model forms in django. It would be the best way for both adding and changing. Forms will do the most of job for you.

Categories