Django Structures: Many apps VS one large app - python

I hope this is not a opinion based question but more like a solutions to a complicated django website. fyi, i am quite a beginner in django.
first of all, i am doing a complicated accounting django website where there are features like:
purchases (purchase order, quotation request, quotation, invoice, do)
Custom user roles and permissions, because we want user to setup their own roles and permissions system
sales (POS, stocks, too many to mentions)
user and registrations
incomes & expenses tracking and reporting.
There are articles and SO's answers about 'many apps vs 1 large app'. My confusion started. I figured out django allows seperating views.py and models.py into multiple file in app/views and app/models with init.py imports.
I personally do not like large app file as it is hard to locate things. I prefer neat structures. But the confusion keeps attacking. I want to do one thing and do it well but it seem like having one large app makes more sense because all the mentioned features are ForeignKey dependent.
So, according to your experience. what's your ideal folder structures and solutions to deal with this?
If you could provide performance difference that would be helpful.
UPDATE:
Since most people said multi apps, I have last question regarding this.
Since Django app can have models/ & views/ folder with multiple models.py & views.py inside, that means one large app can be seperated into multiple views files inside a views/ folder. What yall think about this?
since this will put all migrations in one place, does it provide long term safety in term of messy things like foreign keys across apps.

This kind of question I have asked long time back, on different platform. Common answer is
If you want to reuse that, then create an app or if you don't want
then you no need to make a separate app
Let me give you an example. If your project has features like
Sharing an Image
Sharing text
Comment on Media and Text
Upvote and Downvote options
Here an user can share either a image or text and other can comment on it or Upvote/Downvote it. In this case If you make Comment a separate app and Upvote/Downvote a separate app, then in future if you have to add Video along with Image and Text, then all you have to link Video to Comment app and Upvote/DOwnvote app, that will be less task comparing to a big app with all things inside. Also You can manage your database accordingly.
In your case, you can make (for example),
Custom User (help you add extra permission in future)
Product Category (help you to add more category or subcategory)
Products or Sales etc.
For many admins, when you add those apps to your settings.py, and if you edit admin.py separately in each app, everything will appear your admin panel without any hassle.
For many views, you can import all the models to views.py of any app or use it separately in their apps. It will not cause any problem. Same for urls.py and forms.py etc.

For your solution, i will recommend that you create multiple apps, with each app containing it's own view.py, models.py and urls.py. What you can do is, create a separate app for user that will contain User model (if you decide to override the existing user model provided by django) and all user related views (such as login, registration etc.). I will recommend that you create a separate model for Role as well that will contain all roles in your system. Make a management command that will add roles in that table, whenever you decide to add a new role. Create an enum type class like:
class Role(enum.Enum):
ADMIN = 1
USER= 2
labels = {
ADMIN: "Admin",
USER: "User"
}
So the first entry in Role table will be Admin with pk=1 and so on.
This was an idea as to how you can create models and keep things separate. You can associate user from a separate app to a table in your sales app as that won't cause you any problem and keep the code readable and things neat.

For your own sanity go for multiple apps.
just lay them out first and figure out what should logically go together in one app and what should go to the next.
You want to avoid running into circular imports!
Foreign keys across apps is no problem at all. Basically as soon as u use the USER anywhere in your models, you'll reference across app boundaries already.

Related

Django: how to fully decouple apps when it seems they are coupled? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
Note: I am not a proper python programmer... but I use python extensively. I do things like write classes with inheritance, use iterators and comprehension, etc. My point is that I do not have a full grasp of the language, e.g. what exactly constitutes an python object, why __init__.py is needed other than to specify a module, etc. In relation to Django, I have written multi-app sites (with the help of S.O.) and have really enjoyed Django's templating system, blocks, and how they can be nested. Now are my apps fully decoupled and reusable? That this is subject of this post.
I state this disclaimer because a lot of the Django resources seem to assume that one knows these things. This makes understanding some of the documentation and S.O. questions difficult for a person who is just an (subpower)-user. So please answer this question with that in mind.
Question
These questions are inspired by both the question When to create a new app with startapp in django? by #håkan and the answer given by #antti rasinen which links to James Bennett's 2008 PyCon presentation
A few key points from Bennett's presentation are:
sites are a collection of apps
an app does one thing and one thing well
Which directs me to his section "Project coupling kills re-use" that mentions:
Single module directly on Python path (registration, tagging, etc.)
Related modules under a package (ellington.events, ellington.podcasts, etc.)
Question 0
A "module" in this case is just an app made of other apps?
Question 1
(Apps with related functionality and shared models )
What should I do when apps share models?
In Barrett's slides he implies that user registration and user profiles are distinct and should be distinct apps. (He certainly states that profiles have nothing to do with user registration).
So if I wanted both, would my project have two apps like:
user-registration
user-profile
even though the app user-profile will need the user model from user-registration? Or do I make a single app (module):
user-app
registration
profile
which contains both?
Question 2
(Apps with distinct functions but shared models)
Extending the example from question 1, lets say that my main app (or some other app that is used by the main app) utilizes some aspect of the user model (e.g. recently active members if it was a chat site).
Clearly my main app gets this information from the user model. Does my main app now get bundled under the user-app module?
This may not be the best example, but the point is as follows:
I have two apps app-dependency and app-needs-dependency, where each app does its one thing and one thing well... It is just that app-needs-dependency needs information from app-dependency. What do I do in this case, if everything else about app-needs-dependency is completely decoupled from app-dependency (so it could be used in other projects)?
Question 3
(writing apps for flexibility)
Now I have my site with its couple of apps. Each app does its one thing and does it well. The main app serves as the landing page/ overview in this case.
I want all my other apps to use / inherit the static and template files of the main app.
Where do I store all the static files and templates? In the main app and set that as the default for the other apps? Or where should these static files / templates (e.g. base.css, base.html) go?
Do I make a copy of these files for each other app, so they can be run even though this is redundant?
Which makes my app more flexible?
Question 0
A "module" in the Python context is simply a file that contains definitions and statements. So "related modules under a package" really just means "split your code into separate files based on what the code is doing".
Describing it as "an app made of other apps" is to start confusing Django's concept of an app with Python's concept of a module (which, as stated above is just a file that houses some code).
Question 1
What should I do when apps share models?
You should still try and stick to the "apps do one thing and do it well" maxim. In this case separate profile and registration apps seems like a good idea - because they have quite different functions. A registration app is going to contain the logic for allowing users to register on your site. A profile app is all about what information you will store about a user.
There is nothing wrong with these two apps having a relationship to each other - see below.
Question 2
Let's say that my main app (or some other app that is used by the main app) utilizes some aspect of the user model (e.g. recently active members if it was a chat site). Clearly my main app gets this information from the user model. Does my main app now get bundled under the user-app?
No. It should still be a separate app, with links to the other app.
The user model is actually a good example. Django allows you to specify a custom user model that lets you store whatever additional data you want about a user.
Now, there are loads of third party apps out there that do things like registration, authentication, etc for users. They are designed to work with any user model, not just Django's default one. The way they do that is to use get_user_model() wherever they need to reference the User model, instead of directly importing django.contrib.auth.models.User.
This means that you can use those third party apps with whatever user model you have defined for your own project.
Django's get_user_model() utility is there to serve a very common use case. However the same principle can be extended to your own apps. If there is a dependency between your apps that you think should be swappable, then you can provide a way to swap it out - e.g., a setting/configuration that allows any other project using your app to specify an alternative.
There are hundreds of examples of this kind of configurability in the Django ecosystem. For example, Django itself ships with its own django.contrib.auth authentication app. However if you want to implement your own authentication logic, you don't have to reimplement the entire auth app again yourself (that would be a huge pain). Instead you specify an an authentication backend that it's auth app will use to authenticate. The auth app is designed to allow any project to swap out a core piece of its functionality with minimal effort.
So in your main app, you might define a setting that controls which profile model to use. This means that if someone else wants to use a different profile model, they simply change this setting and they're all set. They are no longer tied to your profile app.
For example - let's say you have a main app that has a view that displays some user data, but also provides a link to a registration view that is provided by a different app. You want anyone else to be able to use that app regardless of what registration app they are using. So you can make this view resuable like so:
In main/views.py:
from django.contrib.auth import get_user_model
from django.conf import settings
from django.urls import reverse
class UserDetailView(DetailView):
# First of all, we're using get_user_model so that a project
# can specify whatever user model it wants, and still use this
# view.
model = get_user_model()
def get_context_data(self, *args, *kwargs):
ctx = super().get_context_data(*args, **kwargs)
# We want to add a link to a registration view into this template context.
# But we want this to be configurable.
# Your REGISTRATION_URL would be something like 'profile:registration'
ctx['registration_link'] = reverse(settings.REGISTRATION_URL)
return ctx
Question 3
The main app serves as the landing page/ overview in this case. I want all my other apps to use / inherit the static and template files of the main app. Where do I store all the static files and templates?
You should store the templates in each respective app. If your main app is providing the base templates, then those should reside in the main app.
If your profile app is then providing a registration view, then the template for that should live in the profile app. There is nothing wrong with it extending the base template from the main app - this can easily be overridden by a project that wants to.
It's fine to make assumptions about how two apps are related to each other - as long as you're careful to allow overriding of those assumptions.
I have to admit your question is not a technical one but rather a conceptual and dogmatic one.
No answer is absolute and universally valid and every detail about how you project is structured and should behave can change the perspective.
As you wrote, each Django app does one thing and it does it well.
I would extend that to the point that each app should contain no more than one Model and at most, it's closets dependents.
Ex: the Product with it's Category, Color, Image
"What Changes together, stay together"
You will have plenty of logic to cover inside that app with only these ones.
Try to look at Django framework as a tool to create your project..this is the final goal...but if you want also to create reusable apps try to create them as independent as possible, or at least dependent to some Django features:
ex: a reusable app and totally independent would be an app that only requires User Model, Sessions, Groups included in Django. You get the idea of dependent but still autonomous app.
An app is part of a project after all...either here or in other part after you build it. Look at it as if it would be a simple function...can run alone or can depend on other functions result...at what point you keep everything inside one function and when you decide to split them in 2 separate ones.
So:
Question 0:
An app is the smallest piece that can run by it's own...having models, views, templates, urls, static files.
It can depend also on other apps...so answer is YES
Question 1:
Always keep things separate by functionality...
User Auth is dealing with user creation and their authentication
User Profile is dealing with personal data of the User
Question 2:
Nothing gets bundled. Everything stays at the same level as 2 different but dependents apps
Question 3:
You can do as you wish.
You can do static as a central place and templates specific for each app or everything central.
No right answer here but only what scales well for your project.
This is a great question and it covers all the questions associated to structuring the project I asked myself when i started working with Django.
Question 0:
Yes, in that case, a module is an app which consists of serveral apps (ellington.events, ellington.podcasts).
Question 1, Question 2, Question 3:
Django is a general purpose, full stack web framework. Since it is general purpose, a lot of it depends on your particular use case. You need not have an entire Django project follow a particular structure (if you want to achieve code reuse AND functional decoupling AND relational decoupling).
With that said, if you can prioritize what you want to achieve, you can go with one pattern over the other.
Let's take the example of Blog.
Code Reuse:
For achieving maximum code reuse, you have to identify what parts of your project is worthy of reuse. Once you have done that, you can set your project structure accordingly.
Project Structure:
BlogProject
-CommonApps
--AbstractUser(abstract class (just like it's java counterpart) )
--AbstractActivity
--AbstractComment
--AbstractArticle
-ProjectApps
--BlogUser (extends AbstractUser)
--BlogActivity (extends AbstractActivity)
--BlogComment (extends AbstractComment)
--BlogArticle (extends AbstractArticle)
The functionalities that can be shared across multiple projects should be implemented in abstract apps, and the ones specific to project can be implemented in Project apps.
Relational Decoupling:
You can create apps to represent the relations between two other apps, and implement all the functionality involving two different apps in that relation.
Project Structure:
BlogProject
-User
-UserActivityRelation
-Activity
-Article
-ArticleCommentRelation
-Comment
-UserCommentRelation
-and so on
Functional Decoupling:
This is the most common practice - create apps for particular functionality.
Project Structure:
BlogProject
-Article
-Activity
-User
-Comment
The point I am trying to make here is that the choice is yours. In more complex projects, it won't be so white and black.
You, depending on what an "app" means to you, and what you want it to do in a particular project and other projects, can decide on a particular structure.
Django keeps it abstract to give you the ability to do that.
I always go for an app setup that makes sense to that particular project. In a project not all apps are reusable. And having flexible/reusable apps does not make sense in all the cases.
As a general rule of thumb, Django devs say an App should be something whose functionality can be described with one sentence. But Django is designed so that you can bend the rules for your projects if you have to.
DISCLAIMER: Functional decoupling and relational decoupling aren't textbook terms. I just used them to describe what I meant here.

When to make a django app, rather than just a model

Recently I've been making a few test projects in Django and while I've found the structure to be better than that of other Web Frameworks, I am a little confused on the concept of different 'apps'.
Here is a test case example:
Suppose I have a simple CRUD application where users post a picture and a title, with a small description, but I want other users to have the ability to create a review of this picture.
Seeing as both the "Post" and "Review" models in this case require CRUD functionality, would I just have two models in the same app, and associate them with one another? Or have two separate apps with different urls.py and views.py files?
I have a hunch I've been doing it wrong and it should be just two models, if this is the case how would I go about writing the urls and views for two models in the same app?
Thanks and any input is appreciated!
The term application describes a Python package that provides some
set of features. Applications may be reused in various projects.
So in this case, better to have both Post and Review as two models in one app, since both of them apply to pictures.
how would I go about writing the urls and views for two models in the same app
The Django project provides a near perfect documentation on how to structure urls and views.
In your case, I think the better is to put your two models in one app.

rookie questions : code structure ,writing my own admin/auth/registration from scratch , global functions and variables

I'm a LAMP developer and i've just started learning/writing code in python/django ... i like it so far but i have problem with couple of pre-built in apps/components and i like to write them from scratch on my own .
most notably admin section AND authentication/registration
i have lots of reason for that but mostly because my native language is not english and the END USER doesn't speak any.i dont like the way admin looks and represents the data , i like to use ajax for most of my forms , i need lots of extra functionality in admin which django doesn't offer out of box and i don't like to hack into it and ...
so with that in mind i'm going to ask my questions
1 - how should i structure my admin section ?
admin section basically has the same apps as the user section but with different functions so ,
should i add those functions in the same view as user functions ?
can i make like 2 views in a app ! or a sub directory containing admin view in each app ?
or create a directory in the root and copy all the apps there for admin ? ( the last resort would be split them in 2 different websites with the same app and put them in 2 host on the same server )
basically 2 websites (1 for admins / 1 for users) using 1 database
2 - auth/registration , i want to write my own code for handling these mostly becuz i dont want my admins and users to be stored in the same table(in database) also they have different columns and different data needs to be stored on registration
i've seen django contrib.auth in action it seems nice and easy , but can i easily modify it to have 2 different sets of login/register form working with 2 different tables?
if not i have to write my own code , so i have this sub-questions ( i like to know answer to these anyway)
2-1 i need to check if users is logged and if so read it from database on every view , how can i make a function run before every other functions in any view ?
something like
from .models import user
def currentUser(request):
thisUser = user.objects.get(id= request.session.get('user_id') )
can i run currentUser function on every reques and make thisUser available like a global variable to every other function/variable ( i guess i can somehow attach it to request which is passed on to every other functions in views ) or should i switch to use classes for views and solve this by inheritance/constructor function
2-2 the basic mechanic of authentication on other technologies (im a LAMP developer) is to store logged user id in a session and in each httprequest check that session to see if contains user id if so he/she is logged and would be red from database and if not user is not logged ... is there anything different in python/django that i should know or it's the same here ?
2-3 if i create 2 different app that work with the same table(database) for example auth app for registration and login , user app for editing user information and other stuff
what is the right/preferred way to create models ? should i define them in 1 app like user app
user/models.py
class user(models.Model):
username = models.CharField(max_length=20)
name = models.CharField(max_length=100)
and include them on the auth views ?
auth/views.py
from .models import user
def login():
loggedUser = user.objects.get(username=request.POST['username'])
if so does authapp needs a model at all ?
There are a lot of Django admin plugins that exist. Some might do everything you need or only require minor modification. If you still want to write your own from scratch I suggest you study a few of them to get ideas. Check out this page for a good list.
As for the specific things you want to accomplish those are more specific questions than "what is best" format. I suggest you try to implement it and open a new question when you run into trouble.
I will help you with the first question by saying I have never been a fan of two sites for frontend/admin and even Django admin agrees by name spacing everything under the url /admin so routes don't collide.
Also the second, use the Django auth and simply extend it to do what you want. It ties into a lot more than you think. Admin/user accounts in the same table is not inherently a risk, separating actually requires more code which is where risk is introduced.
The last thing you want to do when adopting a framework is to immediately start throwing away huge parts of it. Try to get it to do what you want, then customize. I am sure you will find the framework to be malleable to your needs.

django app organization

I have been reading some django tutorial and it seems like all the view functions have to go in a file called "views.py" and all the models go in "models.py". I fear that I might end up with a lot of view functions in my view.py file and the same is the case with models.py.
Is my understanding of django apps correct?
Django apps lets us separate common functionality into different apps and keep the file size of views and models to a minimum? For example: My project can contain an app for recipes (create, update, view, and search) and a friend app, the comments app, and so on.
Can I still move some of my view functions to a different file? So I only have the CRUD in one single file?
First, large files are pretty common in python. Python is not java, which has one class per file, rather one module per file.
Next, views, even as the standard used, is a python module. A module need not be a single file. It can be a directory containing many files, and __init__.py
And then, views.py is only a convention. You, the application programmer are referring to it, and django itself doesn't refer anywhere. So, you are free to put it in as many files and refer appropriate functions to be handed over, the request to, in the urls.py
They don't have to go in views.py. They have to be referenced there.
views.py can include other files. So, if you feel the need, you can create other files in one app that contain your view functions and just include them in views.py.
The same applies to models.py.
Django apps lets us separate common
functionality into different apps and
keep the file size of views and models
to a minimum? For example: My project
can contain an app for recipes
(create, update, view, and search) and
a friend app, the comments app, and so
on.
I don't know about the "to a minimum" part - some apps are just big in views, others big in models. You should strive to partition things well, but sometimes there is just a lot of code. But other than that, this is a fair summary of Django apps, yes.
I also very much dislike long files.
Of course what you read in the other answers is true, but I exploit some very nifty python equivalence:
views.py
and
views/__init__.py
are pretty much functionally equal - by that I mean that if the both contain def my_view() then
from views import my_view
will work the same in both cases!
From there it's easy to structure your long files into smaller ones, yet keeping the naming convention that every django developer is used to:
views/__init__.py
views/largemodel_view.py
then in __init__.py don't forget to import the views from largemodel_view.py.
With large applications I do the same with models though you must remember to set the Meta.app_name:
class MyModel(models.Model):
...
class Meta:
app_name = 'yourappname'
because django will not pick it up magically otherwise for the Admin (but it will still load it, thanks to Python!)
so my apps usually end up looking something like:
project/settings/__init__.py
/..othersettings..
/app_1/models/__init__.py
/...
/views/__init__.py
/...
/templates/
/static/
urls.py
/urls.py
etc.
though of course there's no limit (urls could be split too, etc.etc.)

About 20 models in 1 django app

I have started work on a local app for myself that runs through the browser. Having recently gone through the django tutorial I'm thinking that it might be better to use django rather than just plain python.
There's one problem: I have at least 20 models and each will have many functions. Quite simply it's going to create one huge models file and probably huge views too. How do I split them up?
The models are all related so I can't simply make them into separate apps can I?
This is a pretty common need... I can't imagine wading through a models.py file that's 10,000 lines long :-)
You can split up the models.py file (and views.py too) into a pacakge. In this case, your project tree will look like:
/my_proj
/myapp
/models
__init__.py
person.py
The __init__.py file makes the folder into a package. The only gotcha is to be sure to define an inner Meta class for your models that indicate the app_label for the model, otherwise Django will have trouble building your schema:
class Person(models.Model):
name = models.CharField(max_length=128)
class Meta:
app_label = 'myapp'
Once that's done, import the model in your __init__.py file so that Django and sync db will find it:
from person import Person
This way you can still do from myapp.models import Person
"I have at least 20 models" -- this is probably more than one Django "app" and is more like a Django "project" with several small "apps"
I like to partition things around topics or subject areas that have a few (1 to 5) models. This becomes a Django "app" -- and is the useful unit of reusability.
The overall "project" is a collection of apps that presents the integrated thing built up of separate pieces.
This also helps for project management since each "app" can become a sprint with a release at th end.
The models are all related so I cant's
simply make them into separate apps
can I?
You can separate them into separate apps. To use a model in one app from another app you just import it in the same way you would import django.contrib apps.
Having 20 models in one app might be a sign that you should break it up in smaller ones.
The purpose of a Django app is to have a small single-purpose piece of code, that fits nicelly together.
So, if you had a e-commerce site, you might have a shopping_cart app, a billing app, and so on.
Keep in mind that there is really no problem in apps depending on each other (although it's always better if they can be decoupled), but you should not have an app doing two very distinct things.
The article Django tips: laying out an application might help you. As always, take everything you read with a grain of salt (including this answer).
You can break up the models over multiple files. This goes for views as well.
You can split them into separate files and simply have imports at the top of your main models.py field.
Whether you'd really want to is another question.

Categories