Relation between models with composite keys - django

I have two models with composite keys:
class ContestUser(models.Model):
user_id = models.IntegerField(primary_key = True)
contest_id = models.IntegerField(primary_key = True)
username = models.CharField(max_length = 1536, blank = True)
.
.
.
class ContestRegistration(models.Model):
user_id = models.IntegerField(primary_key = True)
contest_id = models.IntegerField(primary_key = True)
status = models.IntegerField(choices = EJUDGE_CONTEST_STATUSES)
.
.
.
First question is How can I relate them, and query like in join.
Select * from ContestRegistration r join ContestUser u on r.user_id = u.user_id and r.contest_id = u.contest_id where r.contest_id = 3;
Second is How to save an object like this?
cuser = ContestUser.objects.get(user_id = 1, contest_id = 1)
cuser.username = 'username'
cuser.save()
This results in IntegrityError: (1062, "Duplicate entry '1-1' for key 'PRIMARY'")
Executed SQL is:
SELECT * FROM `users` WHERE (`users`.`contest_id` = 1 AND `users`.`user_id` = 1 );
SELECT (1) AS `a` FROM `users` WHERE `users`.`user_id` = 1 LIMIT 1;
UPDATE `users` SET ... WHERE `users`.`user_id` = 1 ;

Django models don't support multiple primary keys: https://docs.djangoproject.com/en/1.3/faq/models/#do-django-models-support-multiple-column-primary-keys
However, as the documentation describes, you can use other properties on ForeignKey fields, like unique_together to do the same thing. Hope that helps you out.

Related

How to reverse query a table with foreign keys such that I can get the values of those foreign keys as well?

My models: https://pastebin.com/qCMypxwz
How can I query the Variants table from Products table? I want to get the values of image and colors (which is a table itself) from the Variants table. This is what I am doing so far but this is giving me similar queries according to debug tool:
productList = Products.objects.prefetch_related('category', 'variants_set__color_id', 'variants_set__image')
for productName in productList:
products = dict()
prod_id = productName.variants_set.all()[0].id
products['id'] = prod_id
products['category'] = productName.category.category_name
products['prod_name'] = productName.prod_name
products['brand'] = productName.brand
prod_colors = productName.variants_set.all().values_list('color_id__name', flat=True).distinct()
prod_images = list(productName.variants_set.all()[0].image.all())
image_list = list()
for image in prod_images:
image_list.append(image.image_url)
products['image'] = image_list
products['colors'] = list(prod_colors)
price = productName.variants_set.all()[0].price
products['price'] = price
createdAt = productName.variants_set.all()[0].createdAt
products['createdAt'] = createdAt
productListDict.append(products)

How to define a marshamllow List field using marshmallow_sqlalchemy

I'm trying to create a Schema using marshmallow_sqlalchemy. I want to create a list out of two entries of the Database, x_coordinate and y_coordinate, however, I'm not sure how to do that.
Here's the Schema
from marshmallow_sqlalchemy import SQLAlchemySchema, auto_field
class LocationSQLAlchemySchema(SQLAlchemySchema):
class Meta:
model = Location
load_instance = True
location_id = auto_field('id')
name = auto_field('name')
user_uid = auto_field('customer_id')
maps_url = auto_field('maps_url')
coordinates = fields.List(Meta.model.x_coordinate,Meta.model.y_coordinate) #This is what I don't know how to define.
Here's the Model I'm using for this Schema:
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.dialects.mysql import INTEGER
db = SQLAlchemy()
class Location(db.Model):
__tablename__ = 'cleaning_locations'
id = db.Column(db.String(128), primary_key=True, unique = True)
name = db.Column(db.String(45), nullable = False)
customer_id = db.Column(db.String(45),nullable = False)
maps_url = db.Column(db.String(2048),nullable = False)
x_coordinate = db.Column(db.Numeric(precision = 8, scale=5), nullable = False)
y_coordinate = db.Column(db.Numeric(precision = 8, scale=5), nullable = False)
address = db.Column(db.String(255))
country = db.Column(db.String(45))
state = db.Column(db.String(45))
size = db.Column(INTEGER(unsigned=True), nullable = False )
rooms = db.Column(INTEGER(unsigned=True), nullable = False )
bathrooms = db.Column(INTEGER(unsigned=True), nullable = False )
kitchens = db.Column(INTEGER(unsigned=True), nullable = False )
How can I make the Schema to represent the coordinates as a list containing the x_coordinate and the y_coordinate?
(newbie extra question). Is it a bad practice to use diferent variable names in the db model and in the Schema?
Please try this (untested):
from marshmallow_sqlalchemy import field_for
[...]
coordinates = fields.Tuple(
(field_for(Location, "x_coordinate"), field_for(Location, "y_coordinate"))
)
Not sure it is the best idea here because then you can't just cram the data loaded from the schema into the object init. But nothing prevents you from having an API (schemas) that differs from the DB representation.

How to write a OR query when number of parameters may change?

I need to make a filter to show BookInstances with following conditions:
BookInstance.public = True
BookInstance.owner != current logged in user
BookInstance.book.title.icontains('some text')
BookInstance.book.description.icontains('some text')
BookInstance.book.authors(id_in=some list of ids)
BookInstance.book.categories(id_in=some list of ids)
The conditions will be combined as:
1 AND 2 AND ( ( 3 OR 4 ) OR 5 OR 6 )
3 & 4 use the same text for search.
current scaffolding in view:
searchedObjects = BookInstance.objects.filter(public=True)
if request.user.is_authenticated:
searchedObjects = searchedObjects.exclude(owner=request.user)
filterObj = dict(request.POST)
for key in filterObj:
if key == 'bookTitleOrDescription':
#condition 3 & 4
bookTitleOrDescription = filterObj[key][0]
elif key == 'author[]':
#condition 5
authorList = filterObj[key]
elif key == 'category[]':
#condition 6
categoryList = filterObj[key]
searchedObjects will have the query result.
The if, elif are required as some parameters may or may not be present. We must avoid writing 10 combinations for it.
models:
class Author(SafeDeleteModel):
name = models.CharField(max_length=255)
class Category(SafeDeleteModel):
title = models.CharField(max_length=255)
class Book(SafeDeleteModel):
title = models.CharField(max_length=255)
description = models.CharField(max_length=255)
authors = models.ManyToManyField(Author)
categories = models.ManyToManyField(Category)
class BookInstance(SafeDeleteModel):
owner = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
book = models.ForeignKey(Book, on_delete=models.CASCADE)
public = models.BooleanField(verbose_name='Will show in search ?')
lendable = models.BooleanField(verbose_name='In good condition ?')
You can filter your query for each field like this:
author = request.POST.get('author', None)
if author:
searchedObjects = searchedObjects.filter(author=author)
You can do it in following way:
filter = Q()
if key == 'category[]':
filter = filter | Q(book__category__id__in='some list of ids')
if key == 'author[]':
filter = filter | Q(book__authors__id__in='some list of ids')
....
....
data = BookInstance.objects.filter(filter)

Is there any way to get primary key using record when creating tables in django_tables2

I'm trying to get the primary key of my table in tables.py using django-tables2 by using the variables record.pk. I supposed that record.pk exist originally but somehow it's not.
class TableServeur(tables.Table):
type_server = tables.Column()
memory = tables.Column(attrs={"td": {"class": "memory"}}, verbose_name="% Mem")
cpu = tables.Column(attrs={"td": {"class": "cpu"}}, verbose_name="% Cpu")
port = tables.Column()
etat = tables.Column()
# here is the problem
T1 = '<a class="btn" href="/update/{{record.pk}}" >Icon</a>'
action = CustomTemplateColumn(T1)
class Meta:
fields = ["type_server", "cpu", "memory", "port", "etat", "action"]
template_name = "django_tables2/bootstrap4.html"
views.py
def cpu_view(request,nom_client):
output = []
liste = get_proc_output()
listServers = Serveurs.objects.all() # port, tp_serveur
listNetstat = get_netstat_output() # port,pid,etat
list_pcpu = get_proc_stat(liste) # pid,cpu,mem
# we add percentage of cpu of each item
for i in range(len(liste)):
liste[i]['cpu'] = list_pcpu[i]
# we mix and reorganise the list by their pid
for x in liste:
pid = x.get('pid')
for y in listNetstat:
if pid in y.values():
output.append({**x,**y})
# we add the type of server by their port
for i in listServers:
for j in output:
if i.port in j.values():
j['type_server'] = i.type_du_serveur
# if we have switched off server, print it with different way
temp_list_1 = [i.type_du_serveur for i in listServers]
temp_list_2 = [x['type_server'] for x in output]
serveurs_eteint = list(set(temp_list_1) - set(temp_list_2))
#
for j in serveurs_eteint:
if j == k['type_server']:
output.append({'type_server':j,'memory':'--','etat':'CLOSED'})
for k in output:
k['nom_client'] = nom_client
# here we construct the table
table = TableServeur(output)
RequestConfig(request).configure(table)
return render(request, 'server/table.html', {'table': table, 'nom': nom_client, 'output': output})
So is there any way I can get the primary key directly when creating a table using django-tbales2?

add condition to join in django orm

How to get data equivalent to sql query using django orm:
SELECT *
FROM "financeDocuments_documenttemplateline"
LEFT JOIN "financeDocuments_documentinstanceline" ON "financeDocuments_documentinstanceline".template_line_id = "financeDocuments_documenttemplateline".id AND "financeDocuments_documentinstanceline".document_instance_id = 1
WHERE "financeDocuments_documenttemplateline".document_type_id = 1
I use:
document_lines = DocumentTemplateLine.objects.filter(document_type__id = document_instance.document_type.id).select_related('documentinstanceline').values('documentinstanceline__value')
But it generates:
SELECT "financeDocuments_documentinstanceline"."value" FROM "financeDocuments_documenttemplateline" LEFT OUTER JOIN "financeDocuments_documentinstanceline" ON ("financeDocuments_documenttemplateline"."id" = "financeDocuments_documentinstanceline"."template_line_id") WHERE "financeDocuments_documenttemplateline"."document_type_id" = 1
Models are like this one:
class DocumentInstance(models.Model):
company = models.ForeignKey(Company)
period = models.ForeignKey(Period, verbose_name=u'период')
document_type = models.ForeignKey(DocumentType, verbose_name=u'вид документа' )
created = models.DateTimeField('created', auto_now_add=True)
author = models.ForeignKey(User)
class Meta:
unique_together= (('company', 'period', 'document_type'),)
class DocumentInstanceLine(models.Model):
document_instance = models.ForeignKey(DocumentInstance, related_name='lines')
template_line = models.ForeignKey(DocumentTemplateLine)
value = models.FloatField(default=0.00)
comment = models.TextField(blank=True)
class Meta:
unique_together= (('document_instance', 'template_line'),)
How to change code for django orm to add second condition like in my first sql query?