Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to bind multiple reusable Django apps together?

Tags:

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 ?

like image 454
JasonTS Avatar asked Jul 20 '12 12:07

JasonTS


People also ask

What is the relationship between Django projects and Django apps?

Django application consists of project and app, it also generates an automatic base directory for the app, so we can focus on writing code (business logic) rather than creating app directories.


2 Answers

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).

like image 129
Aquaplanet Avatar answered Oct 18 '22 06:10

Aquaplanet


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).

like image 34
Chris Pratt Avatar answered Oct 18 '22 05:10

Chris Pratt