django model reduce duplicate code - python

Here is my django model
Because I have ProjectsArchive and StatusArchive for saving history datas
You can see many fields are duplicate
I wonder how to reduce the duplicate code to make the code simple
class Projects(models.Model):
title = models.CharField(max_length=255, blank=True)
link = models.CharField(max_length=300, blank=True)
state = models.CharField(max_length=30, blank=True)
update_at = models.DateTimeField(auto_now=True, blank=True, null=True)
....
class ProjectsArchive(models.Model):
title = models.CharField(max_length=255, blank=True)
link = models.CharField(max_length=300, blank=True)
state = models.CharField(max_length=30, blank=True)
update_at = models.DateTimeField(auto_now=True, blank=True, null=True)
....
class Status(models.Model):
project = models.ForeignKey(Projects, null = True, blank = True)
state = models.CharField(max_length=255, blank=True)
crawl_update_at = models.DateTimeField(auto_now=True, blank=True, null=True)
....
class StatusArchive(models.Model):
project = models.ForeignKey(ProjectsArchive, null = True, blank = True)
state = models.CharField(max_length=255, blank=True)
crawl_update_at = models.DateTimeField(auto_now=True, blank=True, null=True)
....

You can refer here: Abstract base classes
According to your question, I will do:
class BasicInfo(models.Model):
title = models.CharField(max_length=255, blank=True)
link = models.CharField(max_length=300, blank=True)
state = models.CharField(max_length=30, blank=True)
update_at = models.DateTimeField(auto_now=True, blank=True, null=True)
class Meta:
abstract = True
class Projects(BasicInfo):
....
class ProjectsArchive(BasicInfo):
....
After completing BasicInfo, You can reuse the title, link , state and update_at.
However we can create common model containing state and crawl_update_at for Status and StatusArchive.
class StatusInfo(models.Model):
state = models.CharField(max_length=255, blank=True)
crawl_update_at = models.DateTimeField(auto_now=True, blank=True, null=True)
class Meta:
abstract = True
class Status(StatusInfo):
project = models.ForeignKey(Projects, null = True, blank = True)
....
class StatusArchive(StatusInfo):
project = models.ForeignKey(ProjectsArchive, null = True, blank = True)
...

You can create a CommonModel where in you can put your redundant fields then whichever models you want to use them in just inherit CommonModel instead of models.Model.
class CommonModel(models.Model):
class Meta:
abstract = True
title = models.CharField(max_length=255, blank=True)
link = models.CharField(max_length=300, blank=True)
state = models.CharField(max_length=30, blank=True)
update_at = models.DateTimeField(auto_now=True, blank=True, null=True)
class ProjectArchive(CommonModel):
any_new_field_you_want_to_add

What you are looking for is abstract meta class.
https://docs.djangoproject.com/en/1.8/topics/db/models/
class ProjectTemplate(models.Model):
title = models.CharField(max_length=255, blank=True)
link = models.CharField(max_length=300, blank=True)
state = models.CharField(max_length=30, blank=True)
update_at = models.DateTimeField(auto_now=True, blank=True, null=True)
....
class Meta:
abstract = True
class Projects(ProjectTemplate):
pass
class ProjectsArchive(ProjectTemplate):
pass

You could use inheritance.
Please look at the following link
django abstract models versus regular inheritance
And also this the django docs about models (take a look at Abstract base classes)
https://docs.djangoproject.com/en/1.8/topics/db/models/

Related

Django Relational managers

I was trying to delete my Apllication model:
class Application(models.Model):
app_type = models.ForeignKey(ApplicationCategory, on_delete=models.CASCADE, related_name='applications')
fio = models.CharField(max_length=40)
phone_number = models.CharField(max_length=90)
organisation_name = models.CharField(max_length=100, null=True, blank=True)
aid_amount = models.PositiveIntegerField()
pay_type = models.CharField(max_length=1, choices=PAY_CHOICES, default=PAY_CHOICES[0][0])
status = models.ForeignKey(AppStatus, on_delete=models.CASCADE, related_name='applications', null=True, blank=True)
created = models.DateTimeField(auto_now_add=True)
benefactor = models.ForeignKey(Benefactor, on_delete=models.CASCADE, related_name='applications', null=True)
def __str__(self):
return f"id={self.id} li {self.fio} ning mablag\'i!"
and this was my Benefactor model:
class Benefactor(models.Model):
fio = models.CharField(max_length=255)
phone_number = models.CharField(max_length=9)
image = models.ImageField(upload_to='media/')
sponsory_money = models.IntegerField()
organisation_name = models.CharField(max_length=55, null=True, blank=True)
def __str__(self):
return f"{self.fio}"
But I got the below message on superAdmin Panel:
TypeError at /admin/api/benefactor/
create_reverse_many_to_one_manager.\<locals\>.RelatedManager.__call__() missing 1 required keyword-only argument: 'manager'
I would expect delete smoothly!!
Your Benefactor model has several ForeignKey relationships that share the related_name. Give each a unique name and rerun your migrations.

Django model ordering in another models

I can't find the answer to the following question about learning application building:
I have task model, which has one-to-many relations with other models: text_message, image_message, video_message, quiz_message, web_page_message (let's call them blocks) and I want to allow the user to choose the order in which these blocks will be sent.
The issue is that if I just add small integer field called 'order' in these blocks' classes - user still can choose a number that would be much bigger than the overall number of existing blocks.
So what is the best way to make such ordering?
Thank you for your answers.
UPD.:
Sorry if the code is not perfect, it is my first real Django project.
Added my models.
Questions: 
How to make an order through all these messages?
How to design models in such a way to give the ability to the user to change this ordering?
 
class task(models.Model):
employees_appointed_id = models.ManyToManyField(profile, related_name='task_to_appointed_users')
employees_finished_id = models.ManyToManyField(profile, related_name='task_to_users_finished', blank=True, null=True)
creator_user_id = models.ForeignKey('profile', on_delete=models.CASCADE, related_name='who_created_task')
description = models.TextField(max_length=1000)
created_datetime = models.DateTimeField(models.DateTimeField(auto_now=True))
deadline = models.DateTimeField(blank=True, null=True)
title = models.CharField(max_length=55)
course = models.ForeignKey('course', on_delete=models.CASCADE)
mentor = models.ManyToManyField(profile, blank=True, null=True, related_name='task_to_profile')
class text_message(models.Model):
text = models.CharField(max_length=3900)
number_by_order = models.IntegerField()
task = models.ForeignKey('task', on_delete=models.CASCADE, related_name='message_to_task')
creator_user_id = models.ForeignKey('profile', on_delete=models.CASCADE, related_name='message_to_creator_user')
course_id = models.ForeignKey('course', on_delete=models.CASCADE, related_name='messages_to_course')
created_datetime = models.DateTimeField(auto_now=True)
class video_message(models.Model):
description = models.CharField(max_length=1024)
media = models.ForeignKey('media', on_delete=models.CASCADE)
task = models.ForeignKey('task', on_delete=models.CASCADE, related_name='video_message_to_task')
class web_page_message(models.Model):
link = models.CharField(max_length=255)
description = models.TextField(max_length=2000, blank=True, null=True)
task = models.ForeignKey('task', on_delete=models.CASCADE, related_name='web_page_to_task')
class image_message(models.Model):
media = models.ForeignKey('media', on_delete=models.CASCADE)
description = models.TextField(max_length=1024)
task = models.ForeignKey('task', on_delete=models.CASCADE, related_name='image_message_to_task')
class quiz_message(models.Model):
question = models.CharField(max_length=300)
option_1 = models.CharField(max_length=100)
option_2 = models.CharField(max_length=100)
option_3 = models.CharField(max_length=100, blank=True, null=True)
option_4 = models.CharField(max_length=100, blank=True, null=True)
option_5 = models.CharField(max_length=100, blank=True, null=True)
option_6 = models.CharField(max_length=100, blank=True, null=True)
option_7 = models.CharField(max_length=100, blank=True, null=True)
option_8 = models.CharField(max_length=100, blank=True, null=True)
option_9 = models.CharField(max_length=100, blank=True, null=True)
option_10 = models.CharField(max_length=100, blank=True, null=True)
explanation = models.CharField(max_length=200, blank=True, null=True)
task = models.ForeignKey('task', on_delete=models.CASCADE, related_name='quiz_message_to_task')

Django - Getting an object from an object

I'm trying to get the object "Book" from prommotion. Book is a ForeignKey in "prommotion", and I filtered all the prommotions that are active. I need to get the "Book" object from the Prommotion if its active and return it.
(And I know promotion is spelled wrong)
Views:
class Book_PrommotionViewSet(viewsets.ViewSet):
def list(self, request):
queryset = Prommotion.objects.filter(active=True)
serializer = PrommotionSerializer(queryset, many=True)
return Response(serializer.data, HTTP_200_OK)
Prommotion Model:
class Prommotion(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
precent = models.DecimalField(decimal_places=2, max_digits=255, null=True, blank=True)
active = models.BooleanField(default=False)
date_from = models.DateField()
date_to = models.DateField()
book = models.ForeignKey(Book, on_delete=models.SET_NULL, null=True, blank=True)
country = models.ForeignKey(Country, on_delete=models.SET_NULL, null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
verbose_name = 'Prommotion'
verbose_name_plural = 'Prommotions'
Book Model:
class Book(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
title = models.CharField(max_length=255, null=True, blank=True)
author = models.ForeignKey(Author, on_delete=models.SET_NULL, null=True, blank=True)
price = models.DecimalField(decimal_places=2, max_digits=255)
published = models.DateField()
edition = models.CharField(max_length=255)
isbn_code = models.CharField(max_length=255)
pages = models.IntegerField(blank=True, null=True, default=0)
description = models.TextField(null=True, blank=True)
cover = models.CharField(max_length=30, choices=Cover.choices(), default=None, null=True, blank=True)
genre = models.CharField(max_length=30, choices=Genre.choices(), default=None, null=True, blank=True)
language = models.CharField(max_length=30, choices=Language.choices(), default=None, null=True, blank=True)
format = models.CharField(max_length=30, choices=Format.choices(), default=None, null=True, blank=True)
publisher = models.CharField(max_length=30, choices=Publisher.choices(), default=None, null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.title
class Meta:
verbose_name = 'Book'
verbose_name_plural = 'Books'
The first way to get all Books that are related to your active promotions is to extract the book ids from the queryset and pass it to a Book filter
active_promotions = Prommotion.objects.filter(active=True)
Book.objects.filter(id__in=active_promotions.values('book_id'))
Or simply filter books with active promotions by using the double underscore syntax to follow relationships
Book.objects.filter(prommotion__active=True).distinct()

Djnago Models Design Database

I am new to Django project and wanted to know what is the best practice for designing models.
I am working on creating a small project which will have collections of stories in a category and subcategorical manner. I am tagging it as Django because I wanted to also verify the scope of app.
Apps:
index, genre
Design:
Index
Genre
|-- Story
|--Section
|-- Chapters
|--Paragraph
|-- title
|-- text
|-- highlights
genre.models.py
class Story(models.Model):
stry = models.CharField(max_length=256,unique=True)
id =models.AutoField(primary_key=True)
def __str__(self):
return self.stry
class Section(models.Model):
stry = models.ForeignKey(Story,on_delete=models.CASCADE)
name = models.CharField(max_length=256)
desc=models.TextField()
id =models.AutoField(primary_key=True)
slug = models.CharField(max_length=240, null=True, blank=False)
created_at = models.DateTimeField(auto_now_add=True, null=False)
updated_at = models.DateTimeField(auto_now=True, null=False)
class Chapter(models.Model):
sec = models.ForeignKey(Section,on_delete=models.CASCADE)
name = models.CharField(max_length=256)
desc=models.TextField()
id =models.AutoField(primary_key=True)
slug = models.CharField(max_length=240, null=True, blank=False)
created_at = models.DateTimeField(auto_now_add=True, null=False)
updated_at = models.DateTimeField(auto_now=True, null=False)
class Paragraph(models.Model):
chap = models.ForeignKey(Chapter,on_delete=models.CASCADE)
title = models.CharField(max_length=120, null=True, blank=False)
subtitle = models.CharField(max_length=180, null=True, blank=False)
slug = models.CharField(max_length=240, null=True, blank=False)
body = models.TextField()
created_at = models.DateTimeField(auto_now_add=True, null=False)
updated_at = models.DateTimeField(auto_now=True, null=False)
The genre can have many stories, and each section can have many chapters and a similar pattern
Question:
Is there a better design model that I can work on?
Can divide these into different apps or have 1 app for each genre or
include genre as a model.
I would propose this kind of design.
class DateTimeSlug(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
slug = models.CharField(max_length=240)
class Meta:
abstract = True
class NameDesc(models.Model):
name = models.CharField(max_length=256)
desc=models.TextField()
class Meta:
abstract = True
class Story(models.Model):
stry = models.CharField(max_length=256, primary_key=True)
def __str__(self):
return self.stry
class Section(DateTimeSlug, NameDesc):
stry = models.ForeignKey(Story,on_delete=models.CASCADE, related_name='sections')
class Chapter(DateTimeSlug, NameDesc):
sec = models.ForeignKey(Section,on_delete=models.CASCADE, related_name='chapters')
class Paragraph(DateTimeSlug):
chap = models.ForeignKey(Chapter, on_delete=models.CASCADE, related_name='paragraphs')
title = models.CharField(max_length=120)
subtitle = models.CharField(max_length=180)
body = models.TextField()
id = models.AutoField(primary_key=True) is not necessary, because Django adds id with AutoFieldautomatically. If you want to use a custom PrimaryKey, you have to make your own. I propose you can do it at Story.stry. Adding blank=False, null=False is not necessary. It is Django standard behavior.
If you want to use a model in yoru index-App, you can import it where you need it.
Can divide these into different apps or have 1 app for each genre or include genre as a model.
In my opinion, I would add a kind of "genre-tag" at your Story-model and keep it all together.

django - Runpython function to turn charfield into foreignkey

I've been strugglin to relate a csv imported data model with a spatial data model based on a CharField.
I've created both models and now im trying to transfer the data from one field to a new one to be the ForeignKey field. I made a Runpython funtion to apply on the migration but it goives the an error:
ValueError: Cannot assign "'921-5'":
"D2015ccccccc.rol_fk" must be a "D_Base_Roles" instance.
Here are the models:
class D_Base_Roles(models.Model):
predio = models.CharField(max_length=254)
dest = models.CharField(max_length=254)
dir = models.CharField(max_length=254)
rol = models.CharField(primary_key=True, max_length=254)
vlr_tot = models.FloatField()
ub_x2 = models.FloatField()
ub_y2 = models.FloatField()
instrum = models.CharField(max_length=254)
codzona = models.CharField(max_length=254)
nomzona = models.CharField(max_length=254)
geom = models.MultiPointField(srid=32719)
def __str__(self):
return str(self.rol)
class Meta():
verbose_name_plural = "Roles"
class D2015ccccccc(models.Model):
id = models.CharField(primary_key=True, max_length=80)
nombre_archivo = models.CharField(max_length=180, blank=True, null=True)
derechos = models.CharField(max_length=120, blank=True, null=True)
dir_calle = models.CharField(max_length=120, blank=True, null=True)
dir_numero = models.CharField(max_length=120, blank=True, null=True)
fecha_certificado = models.CharField(max_length=50, blank=True, null=True)
numero_certificado = models.CharField(max_length=50, blank=True, null=True)
numero_solicitud = models.CharField(max_length=50, blank=True, null=True)
rol_sii = models.CharField(max_length=50, blank=True, null=True)
zona_prc = models.CharField(max_length=120, blank=True, null=True)
##NEW EMPTY FOREIGNKEY FIELD
rol_fk = models.ForeignKey(D_Base_Roles, on_delete=models.CASCADE, blank=True, null=True)
def __str__(self):
return str(self.numero_certificado)
class Meta:
managed = True
#db_table = 'domperm2015cip'
verbose_name_plural = "2015 Certificados Informaciones Previas"
ordering = ['numero_certificado']
The Runpython function:
def pop_rol(apps, schema_editor):
roles = apps.get_model('b_dom_edificacion', 'D2015ccccccc')
for r in roles.objects.all():
rol = roles
r.rol_fk = r.rol_sii
r.save()
D_Base_Roles.rol values are all unique, and 921-5 is one of those values.
What am I missing?
You probably need to assign an object, not a string. Change the line
r.rol_fk = r.rol_sii
to
r.rol_fk = D_Base_Roles.objects.get(rol=r.rol_sii)
Maybe adjust to whatever the correct field for looking up D_Base_Roles instances is.
Note: this will make a database query for every iteration of the for-loop

Categories