I'd like to move my models to a separate directory, similar to the way it's done with Rails to cut down on code clutter. Is there any way to do this easily?
Thanks,
Collin
I assume you're using the basic webkit and not Django or something fancy. In that case just create a subdirectory called models. Put any python files you use for your models in here. Create also one blank file in this folder called __init__.py.
Then in your main.py or "controller" or what have you, put:
import models
at the top.
You just created a python package.
Brandon's answer is what I do. Furthermore, I rather like Rails's custom of one model per file. I don't stick to it completely but that is my basic pattern, especially since Python tends to encourage more-but-simpler lines of code than Ruby.
So what I do is I make models a package too:
models/
models/__init__.py
models/user.py
models/item.py
models/blog_post.py
In the main .py files I put my basic class definition, plus perhaps some helper functions (Python's module system makes it much safer to keep quickie helper functions coupled to the class definition). And my __init__.py stitches them all together:
"""The application models"""
from user import User
from item import Item
from blog_post import BlogPost
It's slightly redundant but I have lots of control of the namespace.
Related
Since I am a beginner in Django and Python world and I am currently trying to make a real project in it Django but being a java programmer by heart and I generally believe in breaking down application in parts as small as possible.
So I was trying to move /models.py file to /models/myModels.py, but when I try to do the migrations it was an unsuccessful attempt, so I want to ask whether we could relocate and break default models.py, views.py(like we could break tests files and also put them in specific packages following the naming conventions) or we have to accommodate all code in a single file. Although I firmly believe that we could do this but right now I am unable to find any way to do this.
Any help is greatly appreciated.
The trick here is that you cannot directly replace:
models.py
class ModelOne(...):
...
class ModelTwo(...):
...
with:
/models
model_one.py
class ModelOne(...):
...
model_two.py
class ModelTwo(...):
...
as now from models import ModelOne will fail, Python doesn't know how to find ModelOne within the directory. One fix is to change the imports, to e.g.
from models.model_one import ModelOne
but this may mean lots of changes throughout your app; it's much easier to use an __init__.py to determine what should be importable from models, making the directory a package that appears to Python to be identical to the single file you had before:
/models
__init__.py
from model_one import ModelOne
from model_two import ModelTwo
model_one.py
class ModelOne(...):
...
model_two.py
class ModelTwo(...):
...
See e.g. https://docs.python.org/2/tutorial/modules.html#packages for more information.
I try my best to write reusable Django apps. Now I'm puzzled how to put them all together to get the final project.
Here is an example of what I mean:
I have a picture app that stores, resizes and displays images. Also I have a weblog app that stores, edits and displays texts. Now I want to combine these two to show blog posts with images.
To do that I could put foreign key fields in the blog to point at pictures. But then the blog could not be used without the picture app. Also I could create a third app, which is responsible to connect both.
What is the 'best practice' way of doing it ?
EDIT: Thank you for your very good answers, but I'm still looking for more practical example of how to solve this problem. To complete my example: Sometimes it would be nice to use the blog app without the picture app. But if I hard code the dependency it is no longer possible. So how about 3rd app to combine both ?
Introduction talk in the bottom of the answer (more straight to the answer). I will assume that you have one app for text handling called Text and one app for picture handling called Pictures and a third app for blogging called Blog.
Big picture
You will need to study the manual about the template language for python programmers. The idea is that each thing is in its own app and that you have a third app that connects everything. The apps should then supply its models and views as you like them (just remember to keep you focus on what the app should do) and also supply a set of templatetags.
How to make inclusion tags
Make inclusion tags and it is really easy! It will remind you of writing normal views.
Create a directory templatetags in you app folder. Also create a __init__.py file in this templatetags (so the directory becomes a python package).
Then create a python file. The name is important, you will use this in {% load xyz %} in the templates that will use your app. For instance if call the file picturestags.py, you will call
{% load picturestags %} in all templates that will use it.
First in the file add some politics you need not to think much about, just include this before anything else:
from django.template import Library
register = Library()
Then add the tags by defining functions with the same name as your tag. I will call it display_picture in the example and it will take one argument url. The function should create a dictionary that you will use in a template. My example will just display the picture the url is pointing to.
#register.inclusion_tag('pictures/display_picture.html')
def display_picture(url):
return {'picture': url}
Create the path templates/pictures in your app and create the file display_picture.html inside containing:
<img src="{{ picture }}" />
As you probably understand, the #register makes this a tag, what is inside the dictionary display_picture returns are what you can use in display_picture.html. Very much like your normal view functions.
In the end you will end up with these files:
pictures/
__init__.py
models.py
views.py
tests.py
templates/
pictures/
display_picture.html
templatetags/
picturetags.py
That is all you need to add to your Picture app. To use this in your Blog app, you need to add Pictures to your INSTALLED_APPS. Then in the templates, where you need to use your own newly home baked tag first load it: {% load picturestags %} then just add the tag {% display_picture https://www.google.com/intl/sv_ALL/images/logos/images_logo_lg.gif %} like this:
{% load picturestags %}
<html>
<body>
{% display_picture https://www.google.com/intl/sv_ALL/images/logos/images_logo_lg.gif %}
</body>
</html>
Results
This is just a small example but you can see that it is very easy to expand this. Your blog could connect the Text and Pictures app by importing their models and foreign key them. There is you connection Text and Pictures for a certain blog post. Your blog_post.html-template could look like (simplified):
{% load picturestags %}
{% load texttags %}
<html>
<body>
<h1>{{ subject }}</h1>
<div class="article">{% article_to_html articleid %}</div>
<div class="article_picture">{% display_picture %}</div>
</body>
</html>
Notice that only the Blog has dependencies and it is dependencies it should have (no blog without text and pictures...but pictures can live without text). The look and placement should be and can be controlled by CSS and DIV/SPAN-tags. In this way you can take your Picture app and give it to someone who has no idea about Text app and use it, displaying pictures in different ways probably without ever touching your code!
Inclusion tags is the only thing I know of since I just learned this yesterday. I think it is a convenience provided by Django to make life simple. On the documentation page there are a whole lot more (including how to make "real" tags the hard way without "shortcuts"). So if you find this method to limited, read the documentation...it has lots of examples. It also discusses how to make filters, simple_tags, thread considerations and other advanced stuff.
Introduction
I had this exactly this problem as you and I also wanted something different than the answers I read (I don't say the answers was bad, they helped me learn a lot and gave me insights, but I wanted this I am writing now). I managed to figure something out that is not very obvious, thanks to your question and definitely thanks to Stack Overflow so this is my contribution back even to a half year old question that is probably abandoned (might help a googler or two)!
I also got a lot of inspiration from Google Tech Talk Reusable Apps. In the end (43 minutes) he mentions some good examples like django-tagging which is what he says a model for how to write reusable apps. That gave me the idea for all this, because that is the way django-tagging solves this very problem we had/have.
Now after I written all this (took an hour), I feel for the first time that I might contribute instead of just google and follow what others are doing or complaining that others are not writing how I need to do things. For the first time I am taking my responsibility of writing my view so others can google this (just had to write this paragraph :-) because it feels really great, even if it might be shredded to pieces or ignored and forgotten).
Think of it in the same way that you would use any 3rd-party app in your project. "Re-usable" doesn't mean "without dependencies". On the contrary, you'd be hard-pressed to find an app that doesn't have at least one dependency, even if it's just dependent on Django or core Python libraries. (While core Python libraries are usually thought of as "safe" dependencies, i.e. everyone will have it, things do sometimes change between versions of Python, so you're still locking your app into a specific point in time).
The goal of re-usuable is the same as that of DRY: you don't want to write the same code over and over again. As a result, it makes sense to break out functionality like a picture app, because you can then use it over and over again in other apps and projects, but your picture app will have dependencies and other packages will depend on it, as long as there are no circular dependencies, you're good (a circular dependency would mean that you haven't actually separated the functionality).
This is a good question, and something I find quite difficult to manage also. But - do you imagine these applications being released publicly, or are you only using them yourself? If you're not releasing, I wouldn't worry too much about it.
The other thing is, dependencies are fine to have. The pictures app in your example sounds like a good candidate to be a 'reusable' app. It's simple, does one thing, and can be used by other apps.
A blog app on the other hand usually needs to consume other apps like a picture app or a tagging app. I find this dependency fine to have. You could try to abstract it a little, by simply linking to a media resource that was put there by your picture app.
It's all just a little bit of common sense. Can you make your apps slim? If yes, then try to create them so they can be reused. But don't be afraid to take dependencies when they make sense. Also, try to allow extension points so you can potentially swap out dependencies for other ones. A direct foreign key isn't going to help here, but perhaps something like signals or Restful APIs can.
I am a Django newbie and I faced the same problem. It is shameful how there's so much buzz about reusable apps in the Django community, but not a single authoritative reference on how to connect them
in a project without hard coded dependencies.
I have been working on a new Django project and I wanted to set up my models to avoid hard coding as much as possible. This is the pattern that I used.
Layout
project_root/
core/
models/
mixinmodels1.py
mixinmodels2.py
...
utils.py
...
app1/
models/
__init__.py
base.py
basemixins.py
mixins.py
concrete.py
/signals
__init__.py
handlers.py
utils.py
...
app2/
...
...
App models
base.py : This module implements only the 'reason for existence' of that app in abstract classes.
Rules are:
This module usually only imports from the core app. It usually does not import anything from other apps in the same project.
An exception to the above rule is when the 'reason for existence' assumes the existence of another app. For example, a group app assumes that there is an user app somewhere. In this case, the way to link them is:
# project_root/settings.py
AUTH_USER_MODEL = 'app_label.UserModel'
# project_root/groups/models/base.py
from django.conf import settings
and then using settings.AUTH_USER_MODEL to refer to the user model
Use this pattern for all apps, not just the user app. For example, you should also do
# project_root/settings.py
GROUP_MODEL = 'app_label.GroupModel'
If using the above pattern, only assume the functionality provided by base.py of the other app
to which you are linking. Do not assume the functionality of elaborate concrete classes (I will discuss where to put concrete classes shortly)
Of course, importing from django, third party apps and python packages is allowed.
Make sure that the assumptions that you make in base.py of any app is rock solid and would not
change much in the future. A good example is django-registration by James Bennett. Its an old app, but its appeal did not wane because it made rock solid assumptions. Since good reusable apps do one thing well, it is not difficult to find that set of assumptions.
basemixins.py: This module should implements plugs to the concrete models of that app. A 'plug' to a model M is any model that contains a foreign key to the model M. For example:
# project_root/groups/models/basemixins.py
from django.conf import settings
from django.db import models
class BaseOwnedByGroup(models.Model):
"""
This is a plug to the group model. Use this
to implement ownership like relations with
the group model
"""
owner = models.ForeignKey(settings.GROUP_MODEL,
related_name = '%(app_label)s_%(class)s_owner',
verbose_name = 'owner')
# functionality and manager definitions go here.
class Meta:
abstract = True
app_label = 'groups'
BaseOwnedByGroup is a 'plug' to the group model. The rules here are the same as 'base.py`
While defining 'plugs' in basemixins.py, only assume functionality provided by base.py.
Import only from core, django, third party apps and python packages.
mixins.py : This module should be used for two purposes
To define elaborate 'plugs', which assumes the functionality of the elaborate concrete classes but not the relationships with other apps. The elaborate plugs should ideally inherit one of the 'base plugs' defined in basemixins.py.
To define mixin models (that are not 'plugs') which can be used by the concrete classes of that app.
concrete.py : This module should be used to define (you guessed it) concrete classes of that apps and to set up relationships with other apps. In short, this module assumes your project and all the
functionality you want to provide in it.
Relationships to other apps should be set up as follows:
To establish a one to one or many to one relationship with model M of app another_app, do the following:
# project_root/another_app/utils.py
def plug_to_M_factory(version_label):
"""
This is a factory method which returns
the plug to model M specified by
version_label
"""
if version_label == 'first_version':
from another_app.models.basemixins import BasePlugToM
return BasePlugToM
if version_label == 'second_version':
from another_app.models.mixins import PlugToM
return PlugToM
...
# project_root/groups/models/concrete.py
from groups.models.base import BaseGroup
from another_app.utils import plug_to_M_factory
PlugToMClass = plug_to_M_factory(version_label = 'second_version')
class ConcreteGroup(BaseGroup, PlugToMClass):
# define your concrete model
class Meta:
app_label = 'groups'
To establish a many to many relationship, the recommended way is to use a through model. Inherit the correct plug in the through model in the exact same way (as we did in the ConcreteGroup model)
signals : While setting up relationships, often we have to perform operations on a model M of app app1, when model N of app app2 changes. You can use signals to handle that. Your handlers can assume the functionality of the concrete sender, but often they don't need to. Assumption of the base version of the sender in base.py is enough. This is why it is a good idea to always use settings.ModelName to refer to a concrete model. You can extract out the model class from the settings.ModelName string by either using ContentType or using a project wide get_model_for_settings function as follows:
# project_root/project/utils.py
from django.db.models import get_model
from django.core.exceptions import ImproperlyConfigured
def get_model_from_settings(model_string):
"""
Takes a string of the form 'app_label.model' as input, returns the
appropriate model class if it can find it.
"""
try:
app_label, model_name = model_string.split('.')
except ValueError:
raise ImproperlyConfigured("function argument must be of the "
"form 'app_label.model_name', got '%s'" % model_string)
model = get_model(app_label, model_name)
if model is None:
raise ImproperlyConfigured("function argument refers to model "
"'%s' that has not been installed" % model_string)
return model
core : The core app is a special app which stores project wide mixin functions.
These mixins should not assume anything about any other app. Only exception to this rule is mixins that rely on base functionality of settings.AUTH_USER_MODEL. This is because you can safely assume that most projects will have an user model.
Of course imports from django, third party and python packages are still allowed
Remember that all base.py and basemixins.py modules are allowed to import from core.
Finally for everything to work as intended, import your models in models/__init__.py of every app.
The advantages that I find from following this scheme is:
The models are reusable. Anyone can use the abstract base models and mixins to design their own concrete model. base.py, basemixins.py and related factory methods can be bundled together with a bare bones concrete model and shipped in a reusable app.
The apps are extendable. All mixins are versioned and there is a clear inheritance scheme.
The apps are loosely coupled. External mixins are accessed via factory methods and external models are referred to using django.conf.settings.
The apps are self contained. Any changes in an app will most likely break that app and that app only. Other apps will most likely remain unscathed. Even if external apps break, the place where this
could happen is clearly marked.
I have been using this scheme to reduce coupling between my apps. I am not an experienced Django programmer, and I have a lot to learn, so any feedback is appreciated.
I have a very long forms.py and I'd like to split it to smaller parts with as few as possible changes in the code.
Any ideas?
I can't comment, so I'm writing answer. The other thing you can do is to create a forms
directory(remember about __init__.py) in an app directory and split your forms to formone.py, form2.py,...
Then you can import form like that from myapp.forms.formone import FormOne
Or in the __init__.py you can place code:
from formone import *
from form2 import *
And you can import forms with from myapp.forms import FormOne
The main reason that we put Django form classes into a forms.py file is convention. It makes it easy for others to look at your application and know what kinds of things he or she will find in any given file. It's good to follow conventions, but it's not the law and you're free to organize your code as you please.
Here's what I'd do:
First of all, see if you can reduce the amount of code by factoring out duplicated code. Common validation logic could be pulled into custom validators. Forms that share fields or functionality could inherit from a common parent.
If you have created custom field classes, you could separate all those into a file called something like formfields.py in the application directory, and simply import them into forms.py. Likewise, if you have custom validators, you can take those out and import them.
If none of that reduces filesize enough for you, I would split up my form classes by function into several files, e.g. forms_user.py, forms_products.py, forms_data_entry.py or whatever. That way, it's still obvious what we will find in a given file. You will have to change import statements wherever your old forms are referenced, but those should be the only changes necessary.
If you really want to make as few changes as possible, splitting forms.py into multiple files by function (forms_user.py, forms_product.py) is the easiest.
If you have time to refactor or are starting a new project, the best solution is to make a new django app for each component of your project (e.g. users, projects...) each with its own forms.py file. If a single django app gets too big lots of things stop scaling (models.py, views.py etc.) and maintenance gets harder across the board.
I've been developing in Pylons for a little while now and have recently learned they're merging with another framework to create Pyramid.
I've been looking over example code to see the differences and it's causing a bit of confusion...
For example, Controllers have been replaced by Views. Not a big problem... But what I find interesting is there's no directories for these. It's simply one file: views.py.
How does this new MVC structure work? Do I write all my actions into this one file? That could get rather annoying when I have similarly named actions (multiple indexes, for example) :/
Could you point me in the direction of some good tutorials/documentation on how to use this framework?
Since the various view-related configuration methods (config.add_view, config.add_handler) require you to pass a dotted name as the class or function to be used as a view or handler, you can arrange your code however you like.
For example, if your project package name were myproject and wanted to arrange all your views in a Python subpackage within the myproject package named "views" (see http://docs.python.org/tutorial/modules.html#packages) instead of a single views file, you might:
Create a views directory inside your mypackage package.
Move the existing views.py file to a file inside the new views directory named, say,
blog.py.
Create a file within the new views directory named __init__.py (it can be empty,
this just tells Python that the views directory is a package.
Then change the __init__.py of your myproject project (not the __init__.py you just created in the views directory, the one in its parent directory) from something like:
config.add_handler('myhandler', '/my/handler', handler='mypackage.views.MyHandler')
To:
config.add_handler('myhandler', '/my/handler', handler='mypackage.views.blog.MyHandler')
You can then continue to add files to the views directory, and refer to views or handler classes/functions within those files via the dotted name passed as handler= or view=.
Here is one answer that should be pretty straight forward. This question was asked when Pyramid 1.3 wasn't yet out. So forget about python handlers since the new decorator do a pretty good job now.
But just to start: Pyramid doesn't have any common structure. You could possibly write a whole app in one single file if you wanted. In other words, if you liked how pylons was structured, you can go with it. If you prefer to setup your own structure then go for it.
If your site doesn't need more than one file then...GO FOR IT!!! All you really need is that it works.
I personally have a structure like that
- root
- __init__.py # all setup goes there
- security.py # where functions related to ACL and group_finder
- models.py or models/ # where all my models go
- views.py or views/ # where all my views go
- templates
- modelname
- all template related to this resource type
- scripts # where I put my scripts like backup etc
- lib # all utilities goes there
- subscribers # where all events are defined
My view package might sometimes be splitted up in many files where I'd group views by ResourceType.
If you happen to use context to match views instead of routes. You can do some pretty nice things with view_defaults and view_config.
view_defaults sets some default for the class, and view_config sets some more configurations for the defs using defaults provided by view_defaults if present.
This is a pretty simple django patterns question. My manager code usually lives in models.py, but what happens when models.py is really huge? Is there any other alternative pattern to letting your manager code live in models.py for maintainability and to avoid circular imports?
A question may be asked as to why models.py is so huge, but let's just assume it's size and breadth of utility is justified.
I prefer to keep my models in models.py and managers in managers.py (forms in forms.py) all within the same app. For more generic managers, I prefer to keep them in core.managers if they can be re-used for other apps. In some of our larger apps with models/modelname.py that will contains a manager and the model code which doesn't seem bad.
Your best bet with a large set of models is to use django modules to your advantage, and simply create a folder named models. Move your old models.py into this models folder, and rename it __init__.py. This will allow you to then separate each model into more specific files inside of this model folder.
You would then only need to import each model into your __init__.py's namespace.
So, for instance, you might want to separate it into:
yourapp/
models/
__init__.py # This file should import anything from your other files in this directory
basic.py # Just an example name
morespecificmodels.py # Just an example name
managers.py # Might want to separate your manager into this
Then your __init__.py can just be:
from basic import * # You should replace * with each models name, most likely.
from managers import YourManager # Whatever your manager is called.
This is the structure that I use when my model files get huge, however I try to separate things into more pluggable apps as often as possible - so this is rarely used by me.
Hope this helps.
I always place mine in managers.py. If you have a circular import issue remember that a) You can reference the model class for a manager at self.model, and b) You can do imports inside of functions.
What I did when building Django apps was to create a [modelname].py file with just the specific model code, manager code and sometimes form code and used an __init__.py file to import then all in the models directory. This helped me atleast in keeping it managable.