How to avoid duplicate models in django project? - django

i'm learning django so i've many questions, and one is how i can reuse a model? i mean the models live in the application folder, but some models are exactly the same between two differents applications.
So should i rewrite the model every time that i write a new app?

Yes, this is wrong when you have the same names of yours apps
You also can use abstract models
class CommonInfo(models.Model):
name = models.CharField(max_length=100)
age = models.PositiveIntegerField()
class Meta:
abstract = True
class Student(CommonInfo):
home_group = models.CharField(max_length=5)

If your models are exactly the same in different applications, you're doing something wrong. Don't forget that an application is basically just a set of models, and you can use one application's models within another application just by importing them.
Can you give an example of two applications with exactly the same models?

How do I reuse a Model.
Best way to reuse model is to Inherit the parent Model class. This is how you must be doing it. Inheriting from models.Model.
from django.db import models
class trial(models.Model):
# override the parent class methods here or define your own
Also make sure that you import your apps models in the appropriate models.py file.

Related

Importing model classes from other apps without causing circular reference in Django

I have 3 apps products, sales, purchases. each app has a correspondingly named Model class, Product, Sale, and Purchase.
products/models.py
class Product(models.Model):
Name = models.CharField(max_length=32)
sales/models.py
class Sale(models.Model):
Product = models.ForeignKey('products.Product', on_delete=models.CASCADE)
purchases/models.py
class Purchase(models.Model):
Product = models.ForeignKey('products.Product', on_delete=models.CASCADE)
And I decided to make custom managers for the Model classes so that I can keep all the logic in the model files (by overriding objects attr for each class) when I'm writing the methods in the custom manager I imported Sale model In products.models and Product model in sales.models which creates a circular reference, I was able to get away with it by performing the imports in the methods themselves but I remember reading online that circular imports are sign of bad code writing.
So my question is how can I avoid circular imports in this case and have access to the Product Model in sales.models and Sale in products.models.
You can import a model by name to avoid circular imports. When you need to use the model, import it like this:
from django.apps import apps
ModelName = apps.get_model(app_label='app_name', model_name='ModelName')
Running into circular importing means you are fighting against the separation you've created, or you're not writing appropriately decoupled code. In your case, I think you may be trying too hard to separate these models into separate apps. Surely sales and purchases are part of the same set of functionality and share lots of business logic. Even products could live in the same app, although you might have more of an argument there.
If you're coming from another language where it's customary not to have multiple classes in a single file, you should know that is not a best practice in python. Note in the official Django tutorial, the polls app has both Question and Answer models in the same file.
I think a single app named commerce with all three models in the same models.py file would make sense.
# commerce/models.py
class Product(models.Model):
name = models.CharField(max_length=32)
class Sale(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
class Purchase(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)

Is it possible to define views and templates for abstract models to be used for actual models?

Let's say I have a myapp django app and that I need to define 2 specific contact-related models, e.g.
myapp.PersonContact
myapp.CompanyContact
Somewhat obvious thing to do is to create a new contacts app and define an abstract contacts.Contact model which can then be reused in myapp.models, e.g.:
# contacts/models.py
from django.db import models
class Contact(models.Model):
name = models.CharField(max_length=80)
...
class Meta:
abstract = True
# myapp/models.py
from contacts.models import Contact
class PersonContact(Contact):
person = ...
class CompanyContact(Contact):
company = ...
My goal is to abstract as much logic as possible to the contacts app but the only thing that comes to mind is to define an Abstract class contacts.Contact and use that so that I don't have to redefine the same fields in myapp.PersonContact and myapp.CompanyContact.
Is is somehow possible to define contacts.Contact related views and/or templates within the contacts app so that I don't have to create almost identical CRUD-ish views and templates for both PersonContact and CompanyContact?

Managing Django Apps for Inter-related models

For Django, the best practice is apparently to have 1 app to do only 1 thing and to do 1 thing right...and so they can be "plugged and played" to other projects
Consider I have a library application and there are 3 apps. book, member and loan. Each of them has their own model.
So in, say forms.py in loan, I will need to do something like this:
from book.models import Book
from member.models import Model
from .models import Loan
#Other key imports
class CreateLoanForm(forms.Form):
# Some fields
def save(self):
# Retrieve fields
selected_book = self.cleaned_data.get('selected_book')
selected_member = self.cleaned_data.get('selected_member')
new_loan = Loan(
book=Book.objects.get(id=selected_book),
member=Member.objects.get(id=selected_member),
date_start=self.cleaned_data.get('date_start'),
date_end=self.cleaned_data.get('date_end')
)
My questions are:
Doesn't the above from book.models ... violate the ability to plug and play apps?
Is there a better way to import these models? Am I violating best practices when doing so?
For "one app to do one thing, and one thing right" does not mean that it has to have only one model. If you are writing a Library Application then it should have the book, member, and loan models in the same app.
In the context of you question, however, one possible practice to use models from application A in application B would be to define the model as a pluggable setting in app B. See for example what the auth module is doing here: https://docs.djangoproject.com/en/1.9/topics/auth/customizing/#substituting-a-custom-user-model

What is the best approach to organize classes in models?

I have one app, is called "perms" - some custom permission system. Inside the model's file I have this class "Role".
# perms models.py
class Role(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL)
perms = models.ManyToManyField(Perm)
class Meta:
abstract = True
#def ... some custom functions
Next, I have some apps in my project e.g. app1, app2, app2 etc. were I am using this Role class. E.g.
# app1 models.py
from perms.models import Role
class App1Role(Role):
# some custom fields
The question is if this is good approach or should I organize everything in a different way: to put all "AppXRole" classes in perms.models and then in appX.models import this particular AppXRole class?
What is the best way to manage this kind of app's dependencies in Django?

Sharing Django Models with Foreign Fields across apps

I have a Django project with two apps that are almost identical but for a number of reasons, I'd like to keep them separate. To keep things DRY, I created a base_model file.
# base_model.py
from django.db import models
class ModelOne(models.Model):
name = models.CharField()
class ModelTwo(models.Model):
name = models.CharField()
friend = models.ForeignKey(ModelOne)
My two apps are called app1 & app2.
How do I import these models so that essentially I'll have 4 tables for these two models?
Thanks.
UPDATE 1
The reason why I need two versions of these 2 models is that I want to keep them in a separate database as they have separate uses.
For example, let's say I own a home with furniture and as well as a furniture store. I want to keep a separate list for both sets of furniture. The furniture in my home will be kept on a home server, while my store furniture will be kept on a work server. In addition, I'll also like to keep track of the color of the furniture, so that will be a separate table.
# base_model.py
from django.db import models
class Color(models.Model):
name = models.CharField()
class FurnitureBase(models.Model):
name = models.CharField()
color = models.ForeignKey(Color)
For the store app, I need to keep track of pricing, manufacturer, etc. For the home app, I'll need to keep track of usage, age, etc.
These two models should be defined as abstract = True under Meta. Then in each of your two apps, sub-class to create concrete versions in each app. Something like:
app1/models.py:
class App1ModelOne(base_models.ModelOne):
pass
class App1ModelTwo(base_models.ModelTwo):
pass
Read abstract base classes and model inheritance in django's docs for more information: https://docs.djangoproject.com/en/1.7/topics/db/models/#abstract-base-classes