Add columns to queryset and django-table2 table - python

I have the following model and table;
class Person(models.Model):
first_name = models.CharField(max_length=200)
last_name = models.CharField(max_length=200)
user = models.ForeignKey("auth.User")
dob = models.DateField()
# tables.py
class PersonTable(tables.Table):
class Meta:
model = Person
I want to generate a SQL query to calculate the updated age of every Person on my MySQL DB on the fly, using 'dob' every time I retrieve objects, is it possible with django?
Moreover, if i can generate the sql query with aditional column "age" how can I add it to the table?
I am wondering if i should use django-table2 in this case.
EDIT: I've solved doing this way.
I've created a function on MYSQL for calculating age based on a arg type date.
Then I've use this function in an raw sql query in my view.
def get_persons(request):
list_people = Person.objects.raw("SELECT *, age(date_birth) AS edad FROM mytable)
For adding this new age column to my table I've created a new Table class and added two columns "age" and "detail", like this:
class TablaBeneficiarios(tables.Table):
age= tables.Column(orderable=True,verbose_name= "Age")
detail= tables.TemplateColumn('Ver',verbose_name="Acciones") #just a link column
class Meta:
model = FormularioA
attrs = {"class": "paleblue"}
fields = ("cod_pais", "num_familia", "num_miem_familia","fecha_ingreso_ret", "nombre", "prim_apellido",
"seg_apellido", "sexo", "etnia", "responsable", "age","detail")
Thanks in advance.

class Person(models.Model):
# ...
#property age(self):
result_age = 'some queryset that return one column and one row' or datetime.date.today() - self.dob
return result_age
class PersonTable(tables.Table):
age = tables.Column('Custom name', order_by=('dob', )) # you cannot order by property, so put dob or orderable=False
class Meta:
model = Person

Related

Enum field in MySQL

In MySQL there are several types of data, char, varchar int, boolean as you already know.
But it also has the Enum type that in SQL we create the table as follows:
CREATE TABLE person(
id int.....
name varchar(50),
and
Married Enum(Yes,No)
)
My goal is, when I'm creating the models in Django (Python) to be able to create the tables in MySQL I can automatically create this type of field as well.
I tried like this:
from django.db import models
from enum import enum
class options(Enum):
Yes = "Yes"
No = "No"
class Customer(models.Model) :
name = models.CharField(max_length=200)
docto = models.CharField(max_length=14)
age = models.IntegerField(default=0)
username = models.CharField(max_length=20)
password = models.CharField(max_length=20)
block = models.CharField(
max_length=3,
choices=[(tag, tag.value) for tag in options],
default= 'No'
)
def __str__(self):
return self.name
Create the field in MySQL creates but creates as VARCHAR(3) and not as enum.
Can Django do this? How would it be?
I wouldn't like to have to create the tables directly in the database,

Django multiple relations in one model

I have been trying to create a model that could represent the form as it is, tried creating an EntryForm model which is linked to EntryFormTable where then each column in the table is a model class all linked to the table, but then this proved to be a long way and one that doesn't even work, maybe there's a short or even a working method to represent this in django models,
It is recommended to model the "things" as they are in real life, and not as they would appear on the screen. So don't create a model called EntryForm, EntryFormTable or EntryFormColumn, but rather name them what they are. Example based on your image:
class CoveredWorkSet(Model):
school: CharField()
learning_area: CharField()
teacher: ForeignKey(Teacher) # or just CharField if you don't have them in your database
role:
grade: CharField()
class CoveredWork(Model):
covered_work_set = ForeignKey(CoveredWorkSet, related_name='records')
date = DateField()
lesson = CharField()
work_done = BooleanField()
reflection = TextField()
class Signature(Model):
"""
Represents a signature on either a CoveredWork record or a complete CoveredWorkSet
"""
ROLE_CHOICES = [
('subject', 'Subject teacher'),
('class', 'Class teacher'),
('head', 'Head teacher'),
]
teacher = ForeignKey(Teacher, related_name='signatures')
role = CharField(choices=ROLE_CHOICES)
covered_work_set = ForeignKey(CoveredWorkSet, null=True)
covered_work = ForeignKey(CoveredWor, null=True)
date = DateTimeField()
signature = ImageField()

DRF: How to create serializer that uses a field to search if object with given ID exists in database, and if so use this object as foreign key

I have following 2 models:
class Student(BaseModel):
external_id = models.CharField(max_length=30)
name= models.CharField(max_length=30)
last_name= models.CharField(max_length=30)
class Book(BaseModel):
student = models.OneToOneField(
"student.Student",
related_name="books",
on_delete=models.CASCADE,
)
book_name = models.CharField(max_length=30)
book_type = models.CharField(max_length=30)
I want to create such serializer that will create a Book only if there is a Student with provided external_id.
class BooksSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = [
"student",
"book_name",
"book_type",
]
def create(self, validated_data):
student_external_id = validated_data.pop('student')
st = Student.objects.get(
external_id=student_external_id
)
book = Book.objects.create(
student=st,
book_name=validated_data["book_name"],
book_type=validated_data["book_type"],
)
return book
I have written this code but obviously it doesn't work. I used nested serializers to do similar things but I don't want to create Student this time, only check if exisit's and the use it as relation, otherwise throw error that such student doesn't exists.
Maybe it's bad approach first of all? Maybe I shouldn't try to create separete endpoint for books, and try to use patch method for Student and inside of it create object Book to given Student?
You can use PrimaryKeyRelatedField . It checks sended value exists, if not exists raises ValidationError. Try this:
class BooksSerializer(serializers.ModelSerializer):
student = serializers.PrimaryKeyRelatedField(queryset=Student.objects.all())
class Meta:
model = Book
fields = [
"student",
"book_name",
"book_type",
]
def create(self, validated_data):
book = Book.objects.create(
student=student,
book_name=validated_data["book_name"],
book_type=validated_data["book_type"],
)
return book
If you want to use different field from primary key, then you can use SlugRelatedField. You should add your lookup field with slug_field key.
class BooksSerializer(serializers.ModelSerializer):
student = serializers.SlugRelatedField(queryset=Student.objects.all(), slug_field='external_id')
class Meta:
model = Book
fields = [
"student",
"book_name",
"book_type",
]
def create(self, validated_data):
book = Book.objects.create(
student=validated_data["student"],
book_name=validated_data["book_name"],
book_type=validated_data["book_type"],
)
return book

Django order by primary key does not work

I have a model as below:
class Photos(models.Model):
id = models.IntegerField(primary_key=True, default=1)
name = models.CharField(max_length=500)
size = models.IntegerField()
path = models.CharField(max_length=500)
date = models.DateField(default=datetime.now)
def __str__(self):
return self.date.strftime('%Y-%m-%d')
class Meta:
verbose_name_plural = "Photos"
I want to retrieve the last primary key from the database (postgresql) as below:
try:
last_inserted = Photos.objects.order_by('-id')[0]
print(last_inserted)
except IndexError:
print("No data in the database")
but instead of a primary key I always get a date from the date column which is really strange! printing the last_inserted gives me '2018-09-04'.
As a test I change the 'id' column to lang (does not exists in table) gives below error message:
Cannot resolve keyword 'lang' into field. Choices are: date, id, name, path, size
in the above message why date is coming first then id and so on ..!
please help!
print(last_inserted) will show you result of model's __str__ method. To see id you can change model:
class Photos(models.Model):
id = models.IntegerField(primary_key=True, default=1)
name = models.CharField(max_length=500)
size = models.IntegerField()
path = models.CharField(max_length=500)
date = models.DateField(default=datetime.now)
def __str__(self):
return str(self.id)
class Meta:
verbose_name_plural = "Photos"
Or just change query to select only id field using values_list:
last_inserted = Photos.objects.order_by('-id').values_list('id', flat=True)[0]
print(last_inserted)
As for
in the above message why date is coming first then id and so on ..!
I suppose it because of alphabetical order.
You can also try it like this. A bit shorter
Photos.objects.order_by('-id').first().id
There is also a last()

django-tables2 custom column

I'm working now on my first Django project. I want to render results table which contains all fields from Priekabos model and one custom column from Grafikas which should contain something similar to:
SELECT max(kada_moketi) FROM grafikas WHERE priekabos_id = ?
Whatever I try from examples nothing works. Should I write another view function with that custom query:
(Grafikas.objects.filter(priekabos_id=1)
neither with:
.aggregate(Max('kada_moketi')
neither with:
.latest('kada_moketi')
worked for me I created a new table class in tables.py which later PriekabosTable will inherit? That didn't work for me too.
Here's my code:
models.py
class Grafikas(models.Model):
id = models.AutoField(primary_key=True)
mokejimo_nr = models.IntegerField()
kada_moketi = models.DateField()
priekabos = models.ForeignKey('Priekabos', models.DO_NOTHING)
class Priekabos(models.Model):
id = models.AutoField(primary_key=True)
sutarties_nr = models.CharField(unique=True, max_length=45, verbose_name='Sut. Nr.')
nuomos_pradz = models.DateField()
sutarties_trukme = models.IntegerField()
views.py
def priekabos_table(request):
table = PriekabosTable(Priekabos.objects.all())
RequestConfig(request, paginate={'per_page': 20}).configure(table)
return render(request, 'isperkamoji_nuoma/priekabos_table.html', {'table': table})
tables.py
class PriekabosTable(tables.Table):
class Meta:
model = Priekabos
attrs = {"class": "paleblue"}
fields = ('id', 'sutarties_nr', 'nuomos_pradz')
For better understanding, here's 'grafikas' table:
MySQL 'grafikas' table
It sounds like you might be able to fetch the extra field using annotate.
from django.db.models import Max
queryset = Priekabos.objects.annotate(max_kada_moketi=Max('grafikas__kada_moketi'))
table = PriekabosTable(queryset)
Remember to add the field to your table.
class PriekabosTable(tables.Table):
class Meta:
model = Priekabos
attrs = {"class": "paleblue"}
fields = ('id', 'sutarties_nr', 'nuomos_pradz', 'max_kada_moketi')

Categories