Djnago Models Design Database - python

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.

Related

How to use prefetch_related and select_related at the same time in Django?

This is a part of models.py in my django app.
class User(models.Model):
user_id = models.AutoField(primary_key=True)
uuid = models.CharField(max_length=32)
name = models.CharField(max_length=10)
phone = models.CharField(max_length=20)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class UserForm(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
access_info = models.CharField(max_length=250)
etc_comment = models.CharField(max_length=250)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class UserAddress(models.Model):
user_address_id = models.AutoField(primary_key=True)
user = models.ForeignKey(User, on_delete=models.CASCADE)
address_name = models.CharField(max_length=100)
address_name_detail = models.CharField(max_length=100)
address_type = models.CharField(max_length=11)
address_coord = models.PointField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
I am using MySQL database and linked it to django database.
My question is how to get all three data together just in a single query.
As I know, I have to use django's prefetch_related or select_related method to get them together like this
objs = User.objects.select_related('userform').get(user_id=1)
But, what about getting them from three model classes?
Please, let me know if you have any idea.

How to write a self referencing Django Model?

I have a Django model "Inspection" which has:
InspectionID (PK)
PartID
SiteID
Date
Comment
Report
Signiture
I want to be able to have a one to many relationship between the inspection ID and date. So one ID can have inspections at many dates. How would I do this? I currently have the following:
class Inspection(models.Model):
InspectionID = models.IntegerField(primary_key=True, unique=True)
PartID = models.ForeignKey('Part', on_delete=models.CASCADE)
SiteID = models.ForeignKey('Site', on_delete=models.CASCADE)
Date = models.DateField(auto_now=False, auto_now_add=False)
Comment = models.CharField(max_length=255, blank=True)
Report = models.FileField(upload_to='docs', null=True, blank=True)
Signiture = models.CharField(max_length=255, blank=True)
I thought about using models.ForeignKey but I really don't know how to implement that properly in this situation.
I want to be able to have a one to many relationship between the inspection ID and date.
You create an extra model, like:
class InspectionDate(models.Model):
inspection = models.ForeignKey(
Inspection,
on_delete=models.CASCADE,
related_name='inspectiondates'
)
date = models.DateField()
You thus can create InspectionDates for a given Inspection.
Or if you want to add extra data, it might be better to define an InspectionGroup model:
class InspectionGroup(models.Model):
pass
class Inspection(models.Model):
id = models.AutoField(primary_key=True, unique=True, db_column='InspectionId')
inspectiongroup = models.ForeignKey(InspectionGroup, on_delete=models.CASCADE, db_column='InspectionGroupId')
part = models.ForeignKey('Part', on_delete=models.CASCADE, db_column='PartId')
site = models.ForeignKey('Site', on_delete=models.CASCADE, db_column='SiteId')
date = models.DateField(db_column='Date')
comment = models.CharField(max_length=255, blank=True, db_column='CommentId')
report = models.FileField(upload_to='docs', null=True, blank=True, db_column='ReportId')
signiture = models.CharField(max_length=255, blank=True, db_column='Signature')
Note: the name of attributes are normally written in snake_case [wiki], not in PerlCase or camelCase.
you may store 'self Foriegnkey' as
class Inspection(models.Model):
InspectionID = models.IntegerField(primary_key=True, unique=True)
PartID = models.ForeignKey('Part', on_delete=models.CASCADE)
SiteID = models.ForeignKey('Site', on_delete=models.CASCADE)
Date = models.DateField(auto_now=False, auto_now_add=False)
Comment = models.CharField(max_length=255, blank=True)
Report = models.FileField(upload_to='docs', null=True, blank=True)
Signiture = models.CharField(max_length=255, blank=True)
inspection_id = models.ForeignKey('self', null=True, blank=True)

Access child model attributes in django templates

I have created model inheritance in django models like:
models.py
class Instance(models.Model):
id = models.AutoField(primary_key=True)
user = models.ForeignKey(User, related_name='instances')
name = models.CharField(max_length=255, name='name')
slug = AutoSlugField(populate_from='name', unique=True)
created_at = models.DateTimeField(default=timezone.now, editable=False)
type = models.CharField(max_length=255, name='type', default='')
class Meta:
ordering = ['-created_at']
class CustomInstance(Instance):
serverCode = models.TextField(default='', blank=False)
jsonPackageCode = models.TextField(default='', blank=False)
type = models.CharField(max_length=255, name='type', default='custom')
class AwdInstance(Instance):
archive = models.FileField(upload_to='archives', name='archive')
type = models.CharField(max_length=255, name='type', default='awd')
class AwodInstance(Instance):
archive = models.FileField(upload_to='archives', name='archive')
type = models.CharField(max_length=255, name='type', default='awod')
class GithubInstance(Instance):
archive = models.CharField(max_length=255)
type = models.CharField(max_length=255, name='type', default='github')
How can I get child model fields in django templates like user.instances.serverCode?
Help me, please!
Thanks in advance!

DRF - filter across 2 models

I'm working with a legacy database where I have a serializer setup on Table A like so -
class TblapplicationsSerializer(serializers.ModelSerializer):
class Meta:
model = Tblapplications
fields = ('applicationid', 'applicationname', 'description', 'drtierid', 'saglink', 'supportinstructions',
'defaultincidentpriorityid', 'applicationorigintypeid', 'installationtypeid', 'comments',
'lastmodifieddate', 'lastmodifiedby', 'assetstatusid', 'recordownerid', 'adl_app')
depth = 2
I'm using a standard filter -
class TblapplicationsFilter(django_filters.FilterSet):
name = django_filters.CharFilter(name="applicationname", lookup_type="exact")
env = django_filters.CharFilter(name="adl_app__environmentid__domain")
class Meta:
model = Tblapplications
fields = ['applicationname', 'name', 'env']
Here's where it goes sideways. What I want to be able to do is filter on my URL like /api/applications/?name=xxx&env=DEV. It would then return the application and any databases that are linked with the environment of DEV. The name was understandably easy, but the only was I figured out the environment was to make the api point for applications touch the middle table that links the two but it returns multiple values because it's grabbing each time application is referenced with a separate database.
I've updated the Serializer and Filter based on comments given and the serializer, without the &env=DEV returns all the appropriate data (domain is nested in a reverse relationship). I then want my filter to filter the results based on that. Which means that it needs to somehow know to limit the results on the reverse relationship to only what's provided from the nested value.
If you see my models -
class Tblapplicationdatabaselinks(models.Model):
id = models.AutoField(db_column='ID', primary_key=True)
applicationid = models.ForeignKey('Tblapplications', db_column='applicationId', to_field='applicationid',
related_name='adl_app')
dbid = models.ForeignKey('Tbldatabases', db_column='dbId', to_field='id', related_name='adl_db')
environmentid = models.ForeignKey('Tbldomaincodes', db_column='environmentId', to_field='id',
related_name='adl_envlink')
comments = models.TextField(blank=True)
lastmodifieddate = models.DateTimeField(db_column='lastModifiedDate', blank=True, null=True)
lastmodifiedby = models.CharField(db_column='lastModifiedBy', max_length=255, blank=True)
# upsize_ts = models.TextField(blank=True) # This field type is a guess.
class Meta:
managed = False
db_table = 'tblApplicationDatabaseLinks'
class Tblapplications(models.Model):
applicationid = models.AutoField(db_column='applicationId', primary_key=True)
applicationname = models.CharField(db_column='applicationName', max_length=255)
description = models.TextField(blank=True)
drtierid = models.ForeignKey(Tbldomaincodes, db_column='drTierID', blank=True, null=True, to_field='id',
related_name='app_drtier')
saglink = models.TextField(db_column='sagLink', blank=True)
supportinstructions = models.TextField(db_column='supportInstructions', blank=True)
defaultincidentpriorityid = models.IntegerField(db_column='defaultIncidentPriorityId', blank=True, null=True)
applicationorigintypeid = models.IntegerField(db_column='applicationOriginTypeId')
installationtypeid = models.ForeignKey(Tbldomaincodes, db_column='installationTypeId', to_field='id',
related_name='app_insttype')
comments = models.TextField(blank=True)
assetstatusid = models.ForeignKey(Tbldomaincodes, db_column='assetStatusId', to_field='id',
related_name='app_status')
recordownerid = models.ForeignKey(Tblusergroups, db_column='recordOwnerId', blank=True, null=True,
to_field='groupid', related_name='app_owner')
lastmodifieddate = models.DateTimeField(db_column='lastModifiedDate', blank=True, null=True)
lastmodifiedby = models.CharField(db_column='lastModifiedBy', max_length=255, blank=True)
# upsize_ts = models.TextField(blank=True) # This field type is a guess.
class Meta:
managed = False
db_table = 'tblApplications'
class Tbldatabases(models.Model):
dbid = models.AutoField(db_column='dbId', primary_key=True)
dbname = models.CharField(db_column='dbName', max_length=255)
serverid = models.ForeignKey('Tblservers', db_column='serverId', to_field='serverid', related_name='db_serv')
servicename = models.CharField(db_column='serviceName', max_length=255, blank=True)
dbtypeid = models.IntegerField(db_column='dbTypeId', blank=True, null=True)
inceptiondate = models.DateTimeField(db_column='inceptionDate', blank=True, null=True)
comments = models.TextField(blank=True)
assetstatusid = models.IntegerField(db_column='assetStatusId')
recordownerid = models.IntegerField(db_column='recordOwnerId', blank=True, null=True)
lastmodifieddate = models.DateTimeField(db_column='lastModifiedDate', blank=True, null=True)
lastmodifiedby = models.CharField(db_column='lastModifiedBy', max_length=255, blank=True)
# upsize_ts = models.TextField(blank=True) # This field type is a guess.
class Meta:
managed = False
db_table = 'tblDatabases'
class Tbldomaincodes(models.Model):
id = models.IntegerField(db_column='ID', primary_key=True)
domain = models.CharField(primary_key=True, max_length=255)
displayname = models.CharField(db_column='displayName', primary_key=True, max_length=255)
displayorder = models.IntegerField(db_column='displayOrder', blank=True, null=True)
comments = models.TextField(blank=True)
lastmodifieddate = models.DateTimeField(db_column='lastModifiedDate', blank=True, null=True)
lastmodifiedby = models.CharField(db_column='lastModifiedBy', max_length=255, blank=True)
# upsize_ts = models.TextField(blank=True) # This field type is a guess.
class Meta:
managed = False
db_table = 'tblDomainCodes'
Extend your filter set and reference the field in the other model:
class TblapplicationsFilter(django_filters.FilterSet):
name = django_filters.CharFilter(name="applicationname", lookup_type="exact")
env = django_filters.CharFilter(name="environmentid__name")
# ^^^^^^^^^^^^^^^^^^^
class Meta:
model = Tblapplications
fields = ['applicationname', 'name', 'env']
Also, you may wish to name your ForeignKey fields without the id suffix, which is the Django convention. In Django, when you access Tblapplications.environmentid, it is normally a model instance, not the actual id integer itself.

django model reduce duplicate code

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/

Categories