Why would I put code in __init__.py files? - python

I am looking for what type of code would I put in __init__.py files and what are the best practices related to this. Or, is it a bad practice in general ?
Any reference to known documents that explain this is also very much appreciated.

Libraries and frameworks usually use initialization code in __init__.py files to neatly hide internal structure and provide a uniform interface to the user.
Let's take the example of Django forms module. Various functions and classes in forms module are defined in different files based on their classification.
forms/
__init__.py
extras/
...
fields.py
forms.py
widgets.py
...
Now if you were to create a form, you would have to know in which file each function is defined and your code to create a contact form will have to look something like this (which is incovenient and ugly).
class CommentForm(forms.forms.Form):
name = forms.fields.CharField()
url = forms.fields.URLField()
comment = forms.fields.CharField(widget=forms.widgets.Textarea)
Instead, in Django you can just refer to various widgets, forms, fields etc. directly from the forms namespace.
from django import forms
class CommentForm(forms.Form):
name = forms.CharField()
url = forms.URLField()
comment = forms.CharField(widget=forms.Textarea)
How is this possible? To make this possible, Django adds the following statement to forms/__init__.py file which import all the widgets, forms, fields etc. into the forms namespace.
from widgets import *
from fields import *
from forms import *
from models import *
As you can see, this simplifies your life when creating the forms because now you don't have to worry about in where each function/class is defined and just use all of these directly from forms namespace. This is just one example but you can see examples like these in other frameworks and libraries.

One of the best practices in that area is to import all needed classes from your library (look at mongoengine, for example). So, a user of your library can do this:
from coollibrary import OneClass, SecondClass
instead of
from coollibrary.package import OneClass
from coollibrary.anotherpackage import SecondClass
Also, good practice is include in __init__.py version constant

For convenience: The other users will not need to know your functions' exactly location.
your_package/
__init__.py
file1.py/
file2.py/
...
fileN.py
# in __init__.py
from file1 import *
from file2 import *
...
from fileN import *
# in file1.py
def add():
pass
then others can call add() by
from your_package import add
without knowing file1, like
from your_package.file1 import add
Put something for initializing. For example, the logging(this should put in the top level):
import logging.config
logging.config.dictConfig(Your_logging_config)

Related

What are the tricks about importing modules?

I am working on a django project. In views.py I invoked a function from custom.py . The problem is it is working nicely. But I didn't write something like:
from .custom import *
or
import custom
In a sentence, there is not the the word 'custom' anywhere in views.py.
Why it's working? Is there any other way to import module that i don't know about? What is it?
Or any kind of django trick?
addition:
The custom.py also did not import views.py
custom.py has imported models.py
It's possible that your views.py file is importing from another module which imports the function you are using.
models.py
from .custom import my_function
views.py
from .models import *
# my_function will be available
This occurs because the import * statement imports all functions and classes, including anything that has already been imported into that module. There is some information about it in the python docs.
You can avoid this by only importing the specific functions and classes you need, eg:
views.py
from .models import PersonModel, ProductModel

Django-Viewflow, customize archive view

I am trying to customize the default /workflow/archive/ view from Viewflow.
(as in http://demo.viewflow.io/workflow/archive/)
I need to remove some of the columns and add some additional ones specific to my task.
I can't seem to find an easy way. I have been digging and have found that I can try to override the class viewflow.frontend.views.AllArchiveListView and adding the mapping
url('^test/', AllArchiveListView.as_view())
but I get no data when doing that (seems like the flow_classes internal parameter is empty when it gets called like that)
I have also tried to create the viewflow/site_archive.html template but seems overkill.
Any ideas that may point me in the right direction would be highly appreciated!
To customize a common frontend list view, you need to replace viewflow.frontend with you own frontend application. To simplify development, you can inherit from viewflow frontend base classes
# apps.py
from django.apps import AppConfig
from viewflow.frontend.apps import ViewflowFrontendConfig
class FrontendConfig(ViewflowFrontendConfig):
viewset = 'frontend.viewset.FrontendViewSet'
def register(self, flow_class, viewset_class=None):
super().register(flow_class, viewset_class=viewset_class)
# views.py
from viewflow.frontend.views import AllTaskListView as BaseAllTaskListView
class AllTaskListView(BaseAllTaskListView):
list_display = [
'task_hash', 'description'
]
# viewset.py
from viewflow.frontend.viewset import FrontendViewSet as BaseFrontendViewSet
class FrontendViewSet(BaseFrontendViewSet):
inbox_view_class = views.AllTaskListView

Attempted relative import beyond toplevel package in django

the code is not been working due to the error in assigning the path properly please help me with that.
Try this in your models:
#Remove the import statement: from blog.models import sighinmodel
#Then, inside your model
user = models.ForeignKey('blog.sighinmodel' , on_delete = None)
Also, I would like to point out that this is not the correct way of importing other modules in your models.py .
You should do like this:
from appname.models import ModelName
#for importing from another module's models.
There is no need for relative path names in import statements in Django. from appname.module import function/class works fine for nearly all the cases until cyclic redundancy occurs, in which you have to take one among many methods. One is the way I mentioned above:
Method 1: Simply put this inside the ModelClass. Don't import anything.
user = models.ForeignKey('blog.sighinmodel' , on_delete = None)
Method 2(when cyclic import condition is not arising)
from blog.models import sighinmodel
class SomeModel(models.Model):
user = models.ForeignKey(sighinmodel , on_delete = None)
NOTE: The above will work only if a cyclic import isn't occurring. In case the cyclic import condition is occurring, switch back to the first method of declaration.
Hope this helps. Thanks.
This error is coming because relative imports are not allowed beyond top level package. Your blog is itself a module so if you import your model from there it would work.
from blog.models import User, sighinmodel
I would also suggest you to use CamelCase for your models name since they are classes for naming conventions.

Python manage classes in separate files

I have a project which uses the MVC pattern.
In folder "models" I have quite many classes, each class is now has its own file. But I feel like it's not convenient, because every time I need to use a class I have to import it separately. E.g. I have many of the followings in my app source:
from models.classX import classX
from models.classY import classY
If I want to import everything at once, something like from models import * I found that I can put all sorts of import in models/__init__.py. But is it the pythonic way to do it ? What is the convention ?
Python is not java; please avoid the one-file-per-class pattern. If you can't change it, you can import all of them from a submodule of your models package:
# all.py: convenient import of all the needed classes
from models.classX import classX
from models.classY import classY
...
Then in your code you can write:
import my.package.models.all as models # or from my.package.models.all import *
and proceed to use models.classX, models.classY, etc.
Most pythonic way is one that you're already using. You can alleviate importing by grouping your classes in modules. For example, in Django usually all application models are in a single file.
From python docs:
Although certain modules are designed to export only names that follow certain patterns when you use import *, it is still considered bad practise in production code.
Firstly, you should rename your classes and modules so that they don't match, and follow PEP8:
models/
classx.py
class ClassX
classy.py
class ClassY
Then, I'd got with this in models/__init__.py:
from models.classx import ClassX
from models.classy import ClassY
Meaning in your main code, you can do any one of:
from models import *
x = ClassX()
from models import ClassX
x = ClassX()
import models
x = models.ClassX()

How do I get the filepath for a class in Python?

Given a class C in Python, how can I determine which file the class was defined in? I need something that can work from either the class C, or from an instance off C.
The reason I am doing this, is because I am generally a fan off putting files that belong together in the same folder. I want to create a class that uses a Django template to render itself as HTML. The base implementation should infer the filename for the template based on the filename that the class is defined in.
Say I put a class LocationArtifact in the file "base/artifacts.py", then I want the default behaviour to be that the template name is "base/LocationArtifact.html".
You can use the inspect module, like this:
import inspect
inspect.getfile(C.__class__)
try:
import sys, os
os.path.abspath(sys.modules[LocationArtifact.__module__].__file__)
This is the wrong approach for Django and really forcing things.
The typical Django app pattern is:
/project
/appname
models.py
views.py
/templates
index.html
etc.

Categories

Resources