Django - Best way to merge two identical apps - django

I recently came onto a project in which we have two applications that are virtually identical. We are using Django 1.4 and Postgresql 8.4. Both models have the following:
class Author(models.Model):
person = models.ForeignKey(Person)
book = models.ForeignKey(Book)
order = models.PositiveIntegerField(blank=True,null=True)
institute = models.ForeignKey(Institution,blank=True, null=True)
rank = models.ForeignKey(Rank,blank=True, null=True)
class Institution(models.Model):
name = models.CharField(max_length=200)
parent_institution = models.ForeignKey('self', blank=True, null=True)
location = models.ForeignKey(Location, blank=False, null=False)
type = models.ForeignKey(InstitutionType, blank=False, null=False)
class Person(models.Model):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
middle_name = models.CharField(max_length=50,blank=True,null=True)
gender = models.CharField(max_length=1,choices=GENDER_TYPE,blank=True,null=True)
class InstitutionType(models.Model):
type = models.CharField(max_length=255)
Is there a way to easily merge the two, either through SQL or through Django? I'm not quite sure what the best approach would be. My only issue is that there is a lot of foreign key references. Is there a good way in which you could change the primary keys of one application's table to be higher than the other application (essentially reassign primary keys in the second table starting where the first table ends) and have them trickle down and then eventually merge the two tables? Any sort of feedback would be much appreciated.

If what Alexander is suggesting to you is not to your linking, you can use django multi-db support to:
Keep both apps running on the same database and models
Use a migration/sync script while you slowly decouple both models so that only one is being used
Write tests :)

Probably the most difficult thing in merging are models.
If you use Django you should use South too. If you don't - try it.
Take first application as a base. Add fields from second application and create schemamigration.
Then move your data with datamigration from second application.
Merge your code from the second app.

Related

Efficient Design of DB with several relations - Django

I want to know the most efficient way for structuring and designing a database with several relations. I will explain my problem with a toy example which is scaled up in my current situation
Here are the Models in the Django database
1.) Employee Master (biggest table with several columns and rows)
class Emp_Mast():
emp_mast_id = models.AutoField(primary_key=True)
first_name = models.CharField(max_length=50)
middle_name = models.CharField(max_length=50, blank=True)
last_name = models.CharField(max_length=50, blank=True)
desgn_mast = models.ForeignKey("hr.Desgn_Mast", on_delete=models.SET_NULL, null=True)
qual_mast = models.ForeignKey("hr.Qualification_Mast", on_delete=models.SET_NULL, null=True)
office_mast = models.ManyToManyField("company_setup.Office_Mast", ref_mast = models.ForeignKey("hr.Reference_Mast", on_delete=models.SET_NULL, null=True)
refernce_mast = models.ForeignKey("hr.Refernce_Mast", on_delete=models.SET_NULL, null=True)
This is how the data is displayed in frontend
2.) All the relational field in the Employee Master have their corresponding models
3.) Crw_Movement_Transaction
Now I need to create a table for Transaction Data that that stores each and every movement of the employees. We have several Offshore sites that the employees need to travel to and daily about 50 rows would be added to this Transaction Table called Crw_Movement_Transaction
The Crw_Movement Table will have a few additional columns of calculations of itself and rest of the columns will be static (data would not be changed from here) and will be from the employee_master such as desgn_mast, souring_mast (so not all the fields from emp_mast either)
One way to do this is just define a Nested Relation for Emp_Mast in the serializer for Crw_Movement and optimize it using select_related and prefetch_related to reduce the queries to the database. However that is still very slow, as any number of queries to Emp_Mast are unnecessary. Would it be better design to just store the fields from Emp_Mast in Crw_Movement and update them when Emp_Mast is updated as well. If yes, what is a good way of doing that. Or should I stick to using Nested Serializer?

Relating two models with same field value?

I'm new to Django, so I apologize a head of time if my verbiage is off. But I'll try my best!
I have two models :
PlayerProfile - this is updated once a day.
PlayerListing - this is updated every 5 minutes.
Here are simplified versions of those models.
class PlayerProfile(models.Model):
listings_id = models.CharField(max_length=120)
card_id = models.CharField(max_length=120)
first_name = models.CharField(max_length=120)
last_name = models.CharField(max_length=120)
overall = models.IntegerField()
class PlayerListing(models.Model):
listings_id = models.CharField(max_length=120, unique=True)
buy = models.IntegerField()
sell = models.IntegerField()
Currently, we just make queries based on the matching listings_id - but I'd like to have a more traditional relationship setup if possible.
How do you relate two models that have the same value for a specific field (in this case, the listings_id)?
Some potentially relevant information:
Data for both models is brought in from an external API, processed and then saved to the database.
Each PlayerListing relates to a single PlayerProfile. But not every PlayerProfile will have a PlayerListing.
When we create PlayerListings (every 5 minutes), we don't necessarily have access to the correct PlayerProfile model. listings_id's are generated last (as we have to do some extra logic to make sure they're correct).

Using ForeignKey to sort with order_by and distinct not working

I'm trying to sort model Game by each title and most recent update(post) without returning duplicates.
views.py
'recent_games': Game.objects.all().order_by('title', '-update__date_published').distinct('title')[:5],
The distinct method on the query works perfectly however the update__date_published doesn't seem to be working.
models.py
Model - Game
class Game(models.Model):
title = models.CharField(max_length=100)
slug = models.SlugField(unique=True)
description = models.TextField()
date_published = models.DateTimeField(default=timezone.now)
cover = models.ImageField(upload_to='game_covers')
cover_display = models.ImageField(default='default.png', upload_to='game_displays')
developer = models.CharField(max_length=100)
twitter = models.CharField(max_length=50, default='')
reddit = models.CharField(max_length=50, default='')
platform = models.ManyToManyField(Platform)
def __str__(self):
return self.title
Model - Update
class Update(models.Model):
author = models.ForeignKey(User, models.SET_NULL, blank=True, null=True,) # If user is deleted keep all updates by said user
article_title = models.CharField(max_length=100, help_text="Use format: Release Notes for MM/DD/YYYY")
content = models.TextField(help_text="Try to stick with a central theme for your game. Bullet points is the preferred method of posting updates.")
date_published = models.DateTimeField(db_index=True, default=timezone.now, help_text="Use date of update not current time")
game = models.ForeignKey(Game, on_delete=models.CASCADE)
article_image = models.ImageField(default='/media/default.png', upload_to='article_pics', help_text="")
platform = ChainedManyToManyField(
Platform,
horizontal=True,
chained_field="game",
chained_model_field="game",
help_text="You must select a game first to autopopulate this field. You can select multiple platforms using Ctrl & Select (PC) or ⌘ & Select (Mac).")
See this for distinct reference Examples (those after the first will only work on PostgreSQL)
See this one for Reverse Query - See this one for - update__date_published
Example -
Entry.objects.order_by('blog__name', 'mod_date').distinct('blog__name', 'mod_date')
Your Query-
Game.objects.order_by('title', '-update__date_published').distinct('title')[:5]
You said:
The -update__date_published does not seem to be working as the Games are only returning in alphabetical order.
The reason is that the first order_by field is title; the secondary order field -update__date_published would only kick in if you had several identical titles, which you don't because of distinct().
If you want the Game objects to be ordered by latest update rather their title, omitting title from the ordering seems the obvious solution until you get a ProgrammingError that DISTINCT ON field requires field at the start of the ORDER BY clause.
The real solution to sorting games by latest update is:
games = (Game.objects
.annotate(max_date=Max('update__date_published'))
.order_by('-update__date_published'))[:5]
The most probable misunderstanding here is the join in your orm query. They ussually lazy-loading, so the date_published field is not yet available, yet you are trying to sort against it. You need the select_related method to load the fk relation as a join.
'recent_games': Game.objects.select_related('update').all().order_by('title', '-update__date_published').distinct('title')[:5]

How to save Django model instances with circular dependency?

models.py:
class Server(models.Model):
name = models.CharField(max_length=100, unique=True)
last_interaction = models.OneToOneField('Interaction',
on_delete=models.CASCADE,
related_name='server')
class Interaction(models.Model):
client = models.CharField(max_length=100)
time = models.DateTimeField()
server = models.ForeignKey(Server,
on_delete=models.CASCADE,
related_name="interactions")
How do I save instances? (When I want to save one, the other isn't saved yet, so it can't be saved)
Notes:
I been there. The accepted answer doesn't provide a solution to the problem. Indeed at runtime there will be new servers and clients.
I know this schema makes little sense, but I still want to find a way to work with this.
I know the on_delete=cascade in Server is dangerous. I plan to fix it once I solve this problem.
Fundamentally, if you create a circular foreign key relationship, at least one of them must be nullable. For example:
class Interaction(models.Model):
client = models.CharField(max_length=100)
time = models.DateTimeField()
server = models.ForeignKey(Server,
on_delete=models.CASCADE,
related_name="interactions",
null=True
)
You'll be able to create Interaction objects without having the corresponding Server instance ready.

Django - How to build an intermediate m2m model that fits? / best practice

First of all I have to admit that I'm quite new to all this coding stuff but as I couldn't find a proper solution doing it myself and learning to code is probably the best way.
Anyway, I'm trying to build an app to show different titleholders, championships and stuff like that. After reading the Django documentation I figured out I have to use intermediate models as a better way. My old models.py looks like this:
class Person(models.Model):
first_name = models.CharField(max_length=64)
last_name = models.CharField(max_length=64)
[...]
class Team(models.Model):
name = models.CharField(max_length=64)
team_member_one = models.ForeignKey(Person)
team_member_two = models.ForeignKey(Person)
class Championship(models.Model):
name = models.CharField(max_length=128)
status = models.BooleanField(default=True)
class Titleholder(models.Model):
championship = models.ForeignKey(Championship)
date_won = models.DateField(null=True,blank=True)
date_lost = models.DateField(null=True,blank=True)
titleholder_one = models.ForeignKey(Person,related_name='titleholder_one',null=True,blank=True)
titleholder_two = models.ForeignKey(Person,related_name='titleholder_two',null=True,blank=True)
Championships can be won by either individuals or teams, depending if it's a singles or team championship, that's why I had to foreign keys in the Titleholder class. Looking at the Django documentation this just seems false. On the other hand, for me as a beginner, the intermediate model in the example just doesn't seem to fit my model in any way.
Long story short: can anyone point me in the right direction on how to build the model the right way? Note: this is merely a question on how to build the models and displaying it in the Django admin, I don't even talk about building the templates as of now.
Help would be greatly appreciated! Thanks in advance guys.
So I will take it up from scratch. You seem to be somewhat new to E-R Database Modelling. If I was trying to do what you do, I would create my models the following way.
Firstly, Team would've been my "corner" model (I use this term to mean models that do not have any FK fields), and then Person model would come into play as follows.
class Team(models.Model):
name = models.CharField(max_length=64)
class Person(models.Model):
first_name = models.CharField(max_length=64)
last_name = models.CharField(max_length=64)
team = models.ForeignKey(to=Team, null=True, blank=True, related_name='members')
This effectively makes the models scalable, and even if you are never going to have more than two people in a team, this is good practice.
Next comes the Championship model. I would connect this model directly with the Person model as a many-to-many relationship with a 'through' model as follows.
class Championship(models.Model):
name = models.CharField(max_length=64)
status = models.BooleanField(default=False) # This is not a great name for a field. I think should be more meaningful.
winners = models.ManyToManyField(to=Person, related_name='championships', through='Title')
class Title(models.Model):
championship = models.ForeignKey(to=Championship, related_name='titles')
winner = models.ForeignKey(to=Person, related_name='titles')
date = models.DateField(null=True, blank=True)
This is just the way I would've done it, based on what I understood. I am sure I did not understand everything that you're trying to do. As my understanding changes, I might modify these models to suit my need.
Another approach that can be taken is by using a GenericForeignKey field to create a field that could be a FK to either the Team model or the Person model. Or another thing that can be changed could be you adding another model to hold details of each time a championship has been held. There are many ways to go about it, and no one correct way.
Let me know if you have any questions, or anything I haven't dealt with. I will try and modify the answer as per the need.