I'm trying to connect to SQLite table using a raw sql query but unsuccessfully.
Here is my model:
class CsqAgentReport(models.Model):
nodeid_sessionid_sequenceno = models.TextField(db_column='NodeID-SessionID-SequenceNo', blank=True, null=True) # Field name made lowercase. Field renamed to remove unsuitable characters.
callstarttime = models.TextField(db_column='CallStartTime', blank=True, null=True) # Field name made lowercase.
callendtime = models.TextField(db_column='CallEndTime', blank=True, null=True) # Field name made lowercase.
contactdisposition = models.IntegerField(db_column='ContactDisposition', blank=True, null=True) # Field name made lowercase.
originatordn_callingnumber_field = models.IntegerField(db_column='OriginatorDN(CallingNumber)', blank=True, null=True) # Field name made lowercase. Field renamed to remove unsuitable characters. Field renamed because it ended with '_'.
destinationdn = models.IntegerField(db_column='DestinationDN', blank=True, null=True) # Field name made lowercase.
callednumber = models.IntegerField(db_column='CalledNumber', blank=True, null=True) # Field name made lowercase.
pivotoriginatordn = models.TextField(db_column='PivotOriginatorDN', blank=True, null=True) # Field name made lowercase.
pivotcallednumber = models.TextField(db_column='PivotCalledNumber', blank=True, null=True) # Field name made lowercase.
csqnames = models.TextField(db_column='CSQNames', blank=True, null=True) # Field name made lowercase.
queuetime = models.TextField(db_column='QueueTime', blank=True, null=True) # Field name made lowercase.
agentname = models.TextField(db_column='AgentName', blank=True, null=True) # Field name made lowercase.
ringtime = models.TextField(db_column='RingTime', blank=True, null=True) # Field name made lowercase.
talktime = models.TextField(db_column='TalkTime', blank=True, null=True) # Field name made lowercase.
worktime = models.TextField(db_column='WorkTime', blank=True, null=True) # Field name made lowercase.
nomcsq = models.TextField(db_column='NomCSQ', blank=True, null=True) # Field name made lowercase.
idunique = models.IntegerField(db_column='IDUnique', blank=True, null=True) # Field name made lowercase.
originatordnhandeled = models.IntegerField(db_column='OriginatorDNHANDELED', blank=True, null=True) # Field name made lowercase.
originatordnnothandeled = models.IntegerField(db_column='OriginatorDNNOTHANDELED', blank=True, null=True) # Field name made lowercase.
outboundmissedcall = models.TextField(db_column='OutboundMISSEDcall', blank=True, null=True) # Field name made lowercase.
missedcallshandeledy_n = models.IntegerField(db_column='MISSEDCALLSHANDELEDY-N', blank=True, null=True) # Field name made lowercase. Field renamed to remove unsuitable characters.
class Meta:
managed = False
db_table = 'CSQ Agent Report'
Here is the view I created:
def csq_detail_view(request):
with connection.cursor() as cursor:
cursor.execute("SELECT * FROM 'CsqAgentReport'")
obj = cursor.fetchone()
context = {
'object': obj
}
return render(request,"CSQ/detail.html",{context})
and here is the html:
{% extends 'base.html' %}
{% block content %}
<ul>
{% for var_nbr_app_repond in object %}
<li> {{var_nbr_app_repond}} </li>
{% endfor %}
{% endblock %}
The error message is the following :
Request Method: GET
Request URL: http://127.0.0.1:8000/CSQ_Detail/
Django Version: 3.0.5
Exception Type: OperationalError
Exception Value:
no such table: CsqAgentReport.
no such table: CsqAgentReport.
the error is self explanatory, did you create the database ? is there sqlite3 file in your project root folder ?
run those commands :
(venv) python manage.py makemigrations
to create a migration for your model, and
(venv) python manage.py migrate
to create associated table in your database.
Update
you've made a mistake, refer to https://docs.djangoproject.com/en/3.1/ref/models/options/#db-table on how to rename/override table name using db_table in Meta class. it should be:
class CsqAgentReport(models.Model):
[..]
class Meta:
managed = False
db_table = 'csq_agent_report' # HERE snake lower-cased strings
Update 2
since you've renamed db_table to csq_agent_report instead the default one CsqAgentReport you should update the sql statement to
cursor.execute("SELECT * FROM 'csq_agent_report'")
in return statement you don't need to wrap context in dictionary {..} because it's already.
change those 2 lines:
def csq_detail_view(request):
with connection.cursor() as cursor:
cursor.execute("SELECT * FROM 'CsqAgentReport'") # HERE
obj = cursor.fetchone()
context = {
'object': obj
}
return render(request,"CSQ/detail.html",{context}) # HERE
to
def csq_detail_view(request):
with connection.cursor() as cursor:
cursor.execute("SELECT * FROM 'csq_agent_report'") # HERE
obj = cursor.fetchone()
context = {
'object': obj
}
return render(request,"CSQ/detail.html", context) # HERE
Update 3
you have to change managed to True instead Flase
refer to https://docs.djangoproject.com/en/3.1/ref/models/options/#managed
class CsqAgentReport(models.Model):
[..]
class Meta:
managed = True # Here
db_table = 'csq_agent_report' # HERE snake lowercased strings
and don't forget to rerun migration commands.
Related
I have a value in a database on phpmyadmin and I want to change this value by a new calculated value. The function save() doesn't work and the error tells me that it's because it's an interger. I don't know how to solve this problem.
def DeleteBulle (request, id_bulle):
#suppression de la bulle par l'id
id_bulle
param = Bulles.objects.get(pk=id_bulle)
#param.delete()
#adaptation du champ "nombre de bulle" dans la table "site"
site=param.id_site
print('site', site)
compte=Bulles.objects.filter(id_site=site).count()
print('nombre bulle avec site identique', compte)
nbrbulle=Bulles.objects.get(pk=id_bulle).id_site.nombre_bulles
nbrbulle=compte
nbrbulle.save()
#réussite
print("Bulle supprimée")
return redirect('api_bulles_frontend')
Models :
class Site(models.Model):
id_site = models.AutoField(
db_column="Id_site", primary_key=True
) # Field name made lowercase.
nom = models.CharField(
db_column="Nom", max_length=100
) # Field name made lowercase.
vitesse_b = models.FloatField(db_column="Vitesse_b") # Field name made lowercase.
vitesse_c = models.FloatField(db_column="Vitesse_c") # Field name made lowercase.
ecart_type_b = models.FloatField(
db_column="Ecart_type_b"
) # Field name made lowercase.
ecart_type_c = models.FloatField(
db_column="Ecart_type_c"
) # Field name made lowercase.
type_site = models.CharField(
db_column="Type_site", max_length=20
) # Field name made lowercase.
longitude = models.FloatField(db_column="Longitude") # Field name made lowercase.
latitude = models.FloatField(db_column="Latitude") # Field name made lowercase.
nombre_bulles = models.IntegerField(db_column="Nombre_bulles")
date_vidange = models.DateField(
db_column="Date_vidange"
) # Field name made lowercase.
#trajet = models.ManyToManyField(Trajet, related_name='site_moi')
class Meta:
db_table = "site"
class Bulles(models.Model):
id_bulle = models.AutoField(primary_key=True)
num_bulle = models.CharField(max_length=20)
type_bulle = models.CharField(max_length=20)
colories = models.CharField(max_length=20)
latitude = models.FloatField()
longitude = models.FloatField()
date_vidange = models.DateField(
db_column="date_vidange"
)
id_depot = models.ForeignKey(
"Depot", on_delete=models.CASCADE, db_column="id_depot"
)
id_site = models.ForeignKey(
"Site",related_name='bul', on_delete=models.CASCADE, db_column="Id_site"
)
class Meta:
db_table = "bulles"
I don't know how to solve this problem. Thank you for your help.
You should save the site object with the updated item, not update the nombre_bulles, which is just an integer:
from django.shortcuts import get_object_or_404
from django.views.decorators.http import require_http_methods
#require_http_methods(['POST', 'DELETE'])
def DeleteBulle(request, id_bulle):
bulle = get_object_or_404(Bulles, pk=id_bulle)
site = param.id_site
bulle.delete()
site.nombre_bulles = site.bul.count()
site.save(update_fields=['nombre_bulles'])
return redirect('api_bulles_frontend')
Note: normally a Django model is given a singular name, so Bulles instead of Bulle.
Note: Normally one does not add a prefix id_… to a ForeignKey field, since Django
will automatically add a "twin" field with an …_id suffix. Therefore it should
be site, instead of id_site.
Note: It is often better to use get_object_or_404(…) [Django-doc],
then to use .get(…) [Django-doc] directly. In case the object does not exists,
for example because the user altered the URL themselves, the get_object_or_404(…) will result in returning a HTTP 404 Not Found response, whereas using
.get(…) will result in a HTTP 500 Server Error.
Note: One can use the #require_POST decorator [Django-doc]
to restrict the view to only be accessible for a POST request.
I am new to Django and would like some advice on how to query from 3 tables.
I have 3 tables from legacy database mapped in to models (Patient, PrescribedMeds, PrescribedMedsSchedule). We can't change this structure since this will have to remain active while we create the Django application.
1 patient can have many prescribed medication.
1 prescribed medication can have several times in the schedule
Below is the model in django.
models.py
class Patient(models.Model):
patient_name = models.CharField(db_column='patient_name', max_length=50)
dob = models.DateTimeField(db_column='DOB', blank=True, null=True) # Field name made lowercase.
gender = models.CharField(db_column='Gender', max_length=7) # Field name made lowercase.
dateofentry = models.DateTimeField(db_column='DateOfEntry', blank=True, null=True) # Field name made lowercase.
....
....
class Meta:
managed = False
db_table = 'patient'
def __str__(self):
return self.patient_name
class PrescribedMeds(models.Model):
#id = models.AutoField(db_column='ID', primary_key=True) # Field name made lowercase.
patient_id= models.ForeignKey(Patient, models.DO_NOTHING, db_column='patient_id')
med_type = models.SmallIntegerField(db_column='Type') # Field name made lowercase.
name_of_medication = models.CharField(db_column='Name_Of_Medication', max_length=50, blank=True, null=True) # Field name made lowercase.
rxno = models.CharField(db_column='RxNo', max_length=50, blank=True, null=True) # Field name made lowercase.
date_filled = models.DateTimeField(db_column='DateFilled', blank=True, null=True) # Field name made lowercase.
....
....
class Meta:
managed = False
db_table = 'prescribed_meds'
def __str__(self):
return str(self.id) + ", " + self.name_of_medication + ", " + str(self.childno)
class PrescribedMedsSchedule(models.Model):
#id = models.AutoField(db_column='ID', primary_key=True) # Field name made lowercase.
prescribed_meds_id = models.ForeignKey(PrescribedMeds, models.DO_NOTHING, db_column='prescribed_meds_ID') # Field name made lowercase.
medication_date = models.DateField()
medication_time = models.DateTimeField()
quantity = models.DecimalField(max_digits=6, decimal_places=2, blank=True, null=True)
form = models.CharField(max_length=1, blank=True, null=True)
class Meta:
managed = False
db_table = 'prescribed_meds_schedule'
I am trying to get the right syntax in Django to display data from the 3 columns (Prescribed_Meds.ID, PrescribedMeds.name_of_medication, Patient.patient_name, PrescribedMedsSchedule.medication_date, PrescribedMedsSchedule.medication_time).
In SQL the query would be
SELECT prescribed_meds.ID, prescribed_meds.Name_Of_Medication, patient.patient_name, prescribed_meds_schedule.medication_date, prescribed_meds_schedule.medication_time
FROM prescribed_meds_schedule
INNER JOIN (prescribed_meds INNER JOIN patient ON prescribed_meds.patient_id = patient.id) ON prescribed_meds_schedule.prescribed_meds_ID = prescribed_meds.ID;
What would be the correct query in Django? I am having an issue since there is no relationship from PrescribedMedsSchedule to Patient table.
I have tried the following:
my_obj = PrescribedMedsSchedule.objects.all().selected_related(
'prescribed_meds_id'
).prefetch_related('PrescribedMeds__patient_id')
However, this query does not bring up the Patient table/model.
Any advice would be appreciated.
It's worth starting with a note on what django does internally with a FK. You have a suffix in your models of _id but django will do this to the database column automatically. So in your model you could have an easier to read field, patient = models.ForeignKey(Patient) and it will be patient_id in the database.
select_related follows foreign-key relationships, so you're right to do that. If you want to INNER join you should follow the foreign-keys. In your case use the
double-underscore to get through the models:
PrescribedMedsSchedule.objects.all().select_related(
'prescribed_meds_id'
).select_related('prescribed_meds_id__patient_id')
Or you could use 2 queries and use the id values from PrescribedMeds to then query PrescribedMedsSchedule. That would be something like;
meds = PrescribedMeds.objects.all().select_related('patient_id')
med_ids = meds.values_list('id', flat=True)
schedules = PrescribedMedsSchedule.objects.filter(prescribed_meds_id__in=med_ids)
How do I do this query with Django ORM?
It is a multiple join, chained from table to table.
The Django documentation about select related (https://docs.djangoproject.com/en/2.2/ref/models/querysets/#select-related) gives an example where three tables are "chained" via foreign keys: Book -> Author -> City.
saying
b = Book.objects.select_related('author__hometown').get(id=4)
p = b.author # Doesn't hit the database.
c = p.hometown # Doesn't hit the database.
to "not hit the database" must mean that select query joins the three tables.
Therefore the sql generated by the query should show that (I have not yet checked).
My models are based on analysis of an existing database, with well-defined foreign keys.
I'll extracts of the models below.
SELECT *
FROM SERVICE
INNER JOIN VISIT ON SERVICE.VisitRecordID = VISIT.VisitRecordID
INNER JOIN CMPATIENT ON VISIT.PatientNo = CM_PATIENT.PATIENT_ID
The first join I can do with
q = Service.objects.select_related('visitrecordid',).all()
which makes sql like:
SELECT * FROM [SERVICE] LEFT OUTER JOIN [VISIT] ON ([SERVICE].[VisitRecordID] = [VISIT].[VisitRecordID])
so I am getting left outer joins, not inner joins, which is one question.
But most of all, I don't know why CmPatient is not involved in the query.
Models (extracts)
class Service(models.Model):
servrecid = models.AutoField(db_column='ServRecID', primary_key=True) # Field name made lowercase.
visitrecordid = models.ForeignKey('Visit', models.DO_NOTHING, db_column='VisitRecordID', blank=True,
null=True) # Field name made lowercase.
itemno = models.CharField(db_column='ItemNo', max_length=10, blank=True, null=True) # Field name made lowercase.
class Visit(models.Model):
visitrecordid = models.AutoField(db_column='VisitRecordID', primary_key=True) # Field name made lowercase.
patientno = models.ForeignKey(CmPatient, models.DO_NOTHING, db_column='PatientNo', blank=True,
null=True) # Field name made lowercase.
visitdate = models.DateTimeField(db_column='VisitDate', blank=True, null=True) # Field name made lowercase.
servdoctor = models.CharField(db_column='ServDoctor', max_length=6, blank=True,
null=True) # Field name made lowercase.
class CmPatient(models.Model):
patient_id = models.AutoField(db_column='PATIENT_ID', primary_key=True) # Field name made lowercase.
ur_no = models.CharField(db_column='UR_NO', max_length=9, blank=True, null=True) # Field name made lowercase.
external_id = models.CharField(db_column='EXTERNAL_ID', max_length=9, blank=True,
null=True) # Field name made lowercase.
payer = models.ForeignKey('self', models.DO_NOTHING, db_column='PAYER_ID', blank=True,
null=True) # Field name made lowercase.
You can traverse the relationship via __ (two underscores). So what you want is:
Service.objects.select_related('visitrecordid__patientno')
This is what i got in the models
class SFE(models.Model):
snpid = models.ForeignKey(Snps, models.DO_NOTHING, db_column='SNPID', primary_key=True) # Field name made lowercase.
elementid = models.ForeignKey(Functionalelement, models.DO_NOTHING, db_column='ElementID') # Field name made lowercase.
celllineid = models.ForeignKey(Celllines, models.DO_NOTHING, db_column='CELLLINEID') # Field name made lowercase.
countexperiments = models.PositiveIntegerField(db_column='countExperiments') # Field name made lowercase.
filetype = models.CharField(db_column='fileType', max_length=10) # Field name made lowercase.
class Meta:
managed = False
db_table = 'SNPs_FunctionalElement'
unique_together = (('snpid', 'elementid', 'celllineid', 'filetype'),)
def __str__(self):
return str(str(self.snpid) + str(self.elementid) + str(self.celllineid) + str(self.filetype))
class Functionalelement(models.Model):
elementid = models.AutoField(db_column='ElementID', primary_key=True) # Field name made lowercase.
name = models.CharField(unique=True, max_length=55)
class Meta:
managed = False
db_table = 'FunctionalElement'
def __str__(self):
return str(self.elementid)
class Snps(models.Model):
snpid = models.AutoField(db_column='SNPID', primary_key=True) # Field name made lowercase.
rsid = models.CharField(unique=True, max_length=20)
chrom = models.CharField(max_length=5)
pos = models.PositiveIntegerField()
ref = models.CharField(max_length=1)
alt = models.CharField(max_length=1)
maf1000genomes = models.FloatField(blank=True, null=True)
maftopmed = models.FloatField(db_column='mafTOPMed', blank=True, null=True) # Field name made lowercase.
class Meta:
managed = False
db_table = 'SNPs'
def __str__(self):
return str(self.snpid)
Now i want to join FunctionalElement with SFE in order to retrieve the field FunctionalElement.name given a specific SFE.snpid.
I tried with SFE.objects.select_related('elementid__name') but i know it's wrong and i can't understand how to work with django ORM
To get a simple object you need to do: a = SFE.objects.get(snpid=THE_SPECIFICSNPID) later you can access to all the related objects, for example: a.elementid.name will return what you want.
The Django ORM take retrieve the object for you, that is because "lazzy loading". That means that if you need a related object later Django will get it for you, of course, it need to do another query and to avoid that you need to call the method select_related
Summarizing:
To get the name you can do:
name = SFE.objects.get(snpid=THE_SPECIFICSNPID).select_related('elementid').elementid.name
It should works
Here is my code:
models.py
class TblUser(models.Model):
uid = models.IntegerField(primary_key=True, db_column='ID') # Field name made lowercase.
username = models.CharField(max_length=3072, db_column='UserName', blank=True) # Field name made lowercase.
password = models.CharField(max_length=3072, db_column='PassWord', blank=True) # Field name made lowercase.
datesstart = models.DateTimeField(null=True, db_column='datesStart', blank=True) # Field name made lowercase.
datesend = models.DateTimeField(null=True, db_column='datesEnd', blank=True) # Field name made lowercase.
num = models.IntegerField(null=True, db_column='Num', blank=True) # Field name made lowercase.
power = models.IntegerField(null=True, db_column='Power', blank=True) # Field name made lowercase.
email = models.CharField(max_length=12288, blank=True)
class Meta:
db_table = u'tbl_user'
def __unicode__(self):
return '%d--%s--%d'%(self.uid,self.username,self.power)
views.py
from app.models import TblUser
def appendUser(self,name,pwd):
#I add a new user,and the primary_key:uid is autoincrement in datebase
user = TblUser.objects.create(username=name,password=pwd)
print user.uid#None
When I call the appendUser(),it will insert a new record into datebase, and the user(TblUser's instance) only have two valid fields(username,password), the other is empty.
How can I get the user.uid because I want handle other things by using it?
You should use an AutoField not an IntegerField for the pk: https://docs.djangoproject.com/en/1.4/ref/models/fields/#autofield
You might want to read this post, different approach using ModelForm:
Get Primary Key after Saving a ModelForm in Django