Django: Structure to import file - django

I have a general question about project structure in Django. I have several apps on my website. Let's say App A & App B
I have now an API code which I want to import in both apps. I couldn't find a page answering me this question so I want to ask you here. Where in the project folder should I store this SOMEAPI.py file to import it in both app?

Don't overthink it, it's not that important and it can be changed easily. If the file is mostly related to A, I'll put in A and use import some_api from A wherever you need it. Same thing if it's mostly related to B. If it's really independent from both apps, what I often do is create another app common which contains all the code common to the other apps (usually some function helpers), like common.some_api, common.helpers etc...

Related

Moving admin-related files out of their models and controller folders and into a separate admin folder in Rails. How to organize this code?

I am working on a legacy app with 100s of related admin models, controllers, services, jobs, etc. We decided to move all of these files in a folder at the top-level of the app directory called admin. So our ideal file structure would be:
app/admin/models/admin.rb
app/admin/controllers/admin_controller.rb
app/admin/services/admin_service_of_some_kind.rb
app/admin/models/audit.rb
etc
We want the call sites in our code to be:
Admin::Admin.create...
Admin::AdminService.retrieve_all_audit_logs...
Admin::Audit.scope_by_admin...
etc
The problem is that after reading these links:
http://urbanautomaton.com/blog/2013/08/27/rails-autoloading-hell/
http://guides.rubyonrails.org/autoloading_and_reloading_constants.html
I understand that Rails infers file path names from the constants. So if I want to call Admin::AdminService.some_task... Rails will believe the Admin constant and the nested AdminService constant would exist in a file at (assuming that app/admin is autoloaded... which I believe it is) app/admin/admin_service.rb which is not true... they exist in app/admin/services/admin_service.rb.
How can I make this happen given that I want the call site to be Admin::AdminService.some_task?
Given the folder structure of app/admin/services/admin_service.rb, the call site would have to be Services::AdminService.some_task right? (this assumes that app/admin is autoloaded) right? However, this is not what I want.
Why not just move them into
app/models/admin/*.rb
app/services/admin/*.rb

How to make a reusable Django apps if there are some modules which have a dependencies in another apps?

Should a component be its own application?. So we have separate our apps for that reason.
Now reusability does matter in Django. It is trivial to make our apps reusable when each module in the apps does not depends on another apps.
However, It is common to refer a model in another apps by adding ForeignKey('appname.MyModel'). It creates a hard dependency of the Django apps with another apps.
The same thing happened with import of another apps (i.e. from appname import MyModel). It creates a dependencies of the apps to another apps.
If the app contains such dependency of another apps, then it does not seems to be viable to share our apps (i.e. Not reusable).
What do I have to do to make the dependencies loose. And allow me to share my apps without having to hardcode another apps in the app.
So, it's worth noting that we don't really need to depend on your specific apps. We depend instead on having something that satisfies the same interfaces your apps expose.
This is the 'Pythonic' way to do things (sometimes referred to as duck typing as 'if it walks like a duck and quacks like a duck... it must be a duck').
You've had in comments how to solve the ForeignKey problem
To summarise, you can just add the value in settings.py:
MY_FK_MODEL = 'someapp.SomeModel'
and then use it in your models.py like so:
from django.conf import settings
class ReusableAppModel(models.Model):
some_model = models.ForeignKey(settings.MY_FK_MODEL)
So far, so easy; now to solve the import.
We actually already have an example of this from Django itself. Which is the get_user_model() method.
We could make something like that by adding the following in settings.py:
MY_APP_DEPENDENCY = 'myapp.my_module.MyClass'
along with a helper function similar to get_user_model() somewhere in your reusable app. Let's say reusable_app/helpers.py for the sake of argument:
from django.conf import settings
from pydoc import locate
def get_my_app_dependency():
dependency = locate(settings.MY_APP_DEPENDENCY)
# locate() returns None if the class is not found,
# so you could return a default class instead if you wished.
return dependency
Then you can get that class wherever you need it by calling the method:
from reusable_app.helpers import get_my_app_dependency
MyAppDependency = get_my_app_dependency()
app_dep_instance = MyAppDependency()
The summary here is that you can allow users to specify a class/method/whatever as a string in settings.py and then use that to refer to your dependency.
This lets users 'inject' a dependency into your app.
One final note:
Whenever you have an app/module that has lots of dependencies on others, it's worth double checking to see if they really should be separate. You want to avoid creating one giant module satisfying lots of disparate responsibilities, but likewise you want to avoid artificially breaking code up when it doesn't make sense. It's a careful balance.

django - reusing functions in many views

I have a bunch of functions that I created in some views that must be reused in many other views. Do I need to create a class and put those functions in a class? If yes how exactly has to be done in Django and then how do I call and initiate them in the new views?
Django views are just Python functions. You can call other Python functions from them just as you can from any other Python code. Put your functions into a .py file, import it, and invoke the functions.
Of course, it may make sense for other reasons to create a class to hold the functions, but you certainly don't need to in order to call them from views.
The solution would be to create the myfunctions.py file in your app folder and import it in your views. Your views file would look like:
import myfunctions
def my_view(request):
.....
foo = myfunctions.bar()
....
You look to complicated to Django. Django is just another Python application and lives in the Python world. For example you can create file library.py and import this file where is needed (in modules where the function from library is needed). If you need you library's functions to get data from database, just import models in the library.py and use them.
Django doesn't have such a big think as "module". You creating the architecture, you can define what in your case is module. In general this is just simple directory with init.py file inside to be able to import files from there.
Hope that helped.
From my point of view, if you have a lot of functions that are widely used in your project it make sense put all this in some separate application. I create some module named 'contrib' for this purposes. It can avoid some time for maintaining this code in future

Django and Eclipse, making a portable project

I like Eclipse for a number of reasons. One of them is, when I'm doing a java project, I can copy and paste my project or rename it, to make a new one, and it will update all the names of everything.
I'm trying to do something similar for a django project.
I can set an APPNAME variable with the following code
APPNAME = os.path.basename(os.path.dirname(__file__))
and then I could import this in any file that needed to know the name of the application. This isn't an ideal solution however but it would work for my settings.py file as well as my urls.py files.
It won't work for situations where I need to import something from somewhere like so:
from myproject.someapp import forms
Is there a way for django/python to know what "myproject" is? Or can I use an import statement relative to the current app?
Or maybe there's a better way to copy django projects.
EDIT: I imagine there are also database dependencies as well that I'd have to deal with.
I follow a couple of rules to keep my applications portable. I'll list them below in the hope that someone finds them useful.
Include my apps in the PYTHONPATH rather than my projects. This way I can execute from app import forms rather than from project.app ....
Following #1, I always import from app only. This means I can reuse my apps in other projects without having to change import statements within the app or in other dependent apps.
If you stick to #1 and #2 you can generally copy and paste projects without too much trouble. You'll still have to modify settings.py though.

Django code organization

I am working on a Django app and I have a class which reads the contents of a file and returns a Django model. My question is where do I store this class in the file system? All this does is reads the file, populates a Django model and returns it.
Thanks
There is nothing special about a Django application: it's just a Python package. Technically you can put the class anywhere you can import.
With that being said, it's best to keep related code bundled together. It sounds like a good place for this particular class is in the file that declares the Model it returns.
On the other hand it might be logical to throw it into the application's __init__.py file.
You could also make a utils, etc, admin, scripts . . . folder/package to put utility classes and scripts if it's meant to be used for administration and site maintenance.
In the end it's more about how you want to organize your project, but technically it can live just about anywhere.