As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
I'm just starting to use Django for a personal project.
What are the pros and cons of using the built-in Admin application versus integrating my administrative functions into the app itself (by checking request.user.is_staff)?
This is a community wiki because it could be considered a poll.
It really depends on the project I guess. While you can do everything in the admin, when your app gets more complex using the admin gets more complex too. And if you want to make your app really easy to manage you want control over every little detail, which is not really possible with the admin app.
I guess you should see it like this:
Using django admin: save time writing it, lose time using it.
Rolling your own admin: lose time writing it, save time using it.
I would use Django's admin app, for a number of reasons. First, writing an administration app may be quite tricky and take some time if you want to do it right, and django.contrib.admin is for free and works out of the box. Second, it is really well designed and very nice to work with (even for non-technical users). Third, it covers a lot of the common cases and it doesn't seem wise to waste time on rewriting it until you are really sure you cannot do otherwise. Fourth, it isn't really so difficult to customize. For example, adding akismet mark-as-spam and mark-as-ham buttons was really a piece of cake.
It's so easy to selectively override parts of the admin in varying degrees.
You can:
Override admin templates on an app by app basis or even model by model basis.
Override admin views by inheriting and subclassing
Catch admin url's by putting yours before it in urls.py and provide your own interfaces that are based on admin look and feel
...and lots more.
So start with the admin and then slot in whatever custom functionality you need where you need it.
There are a bunch of apps that do clever things with the admin. For example:
django-reversion takes over the
admin-log and extends it into full
history.
Tusk CMS combines the
django-mptt app with JQuery nested
sortable widget in a neat way.
Also search django-snippets for admin related snippets and this page has got a wealth of info.
I found sadly, that the while the django admin app saves a lot of time at first, it becomes a hinderence later on, as your costumer demands more features that are not easily integrated with the default admin interface. You might endup with two kinds of admin tools: the django admin (for apps that require simple data entry), and your custom rolled admin interface for other applications that require a richer interface.
Consider using the Django admin, but with your own hand-crafted widgets for particular fields. You can create sophisticated form-parts, and tell the admin to use your code for the inputs and displays of any specific field, or all fields of a type.
Jannis has done some cool stuff, and his work shows you how easy it is:
http://jannisleidel.com/2008/11/wysiwym-editor-widget-django-admin-interface/
A project that I am working on recently incorporated a time picker that uses drop-downs for the various parts of time, (h, m, s) Another field would indicate which days of the week were recurring... it would use 7 checkboxes for the days of the week, and store that in the database as a pickled dateutil.rruleset. Then, you just give the admin hints on which widgets to use for the various fields.
It involves defining your data class, your own widget which subclasses forms.Widget, your own Field which subclasses forms.Field, and a model.Field too. Each of the three classes is nice and simple and clean, and is responsible for a transition from the database to the Model, the Model to the Widget, and back through those two steps. It's really a thing of beauty.
The fields you create will be some of the most reusable, sophisticated intellectual property that you can accumulate... and you don't have to write your own admin from scratch.
I'd recommend enabling the admin site on just about every type of project. The cost of setting it up is pretty low, and it gives you a reasonably convenient mechanism for inspecting and modifying your site.
If your site has mostly a one way flow of information, from webmaster to visitors, then the admin site is probably all you need.
If, however, your site has a richer interaction among its users, you will need to compose django views that can enable that interaction while also limiting access to what users can really do.
I'd go with the Django admin functionality, over writing your own. You can customize the Django admin by adding your own templates for the admin, your own widgets, etc. I'm working on a project with a very customized Django admin. If we had decided to write it by hand, it would have taken 4 times as long to get done. I just can't see a scenario where you would want to write your own.
Related
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.
I have been facing a big challenge with django since I was assigned the task to rebuild the admin page of our platform. I started unsure of what to do and now that I am half way on, I am even more unsure.
Here is my question:
If I want to build a highly customized admin, should I do a giant hack on the source code or create a new app?
1) Giant Hack
That is how I started and got stuck. A couple of problems appeared on the way, for instance:
I had to extend the AdminSite and override every view I wanted to change
Django's admin is very modular (I mean, very very modular) and a screen might be the sum of tons of other templates
Creating a simple navbar is a pain in the ass (at least it has been for a newbie like me). This is due to the fact that app_list (the variable that contains the mapped models to show in admin's first page) not being accessible when other templates rather than base.html are injected. Thus, I would have to create a context processor, replace every TemplateResponse() by render() (technically, since I tried to do it and it didn't work as well)
The problems go on and on. Given my lack of experience with django, I might be doing crap, but it does feel like I am on the wrong way.
this guy's answer motivated me to post this.
2) Building a brand new app
Of course it will take a little while to implement this, but it seems like a robust and maintainable way of getting it done. One of the points is that I will need to give the same flexibility as the default admin site gives when adding models and promptly having their cruds and tables (I am not really sure how to accomplish this behavior).
I am pretty new to django and any guidelines will be highly appreciated. Give me your thoughts on how to make it.
There is no need to overwrite admin views. The easiest way is to overwrite the templates and add your own css & javascripts.
I have added my own navbar, sidebars and bottom. It is really easy if you overwrite the admin base templates.
If needed you can provide custom data to the template by using own templatetags.
This question has been troubling me for some days now and I've tried asking in many places for advice, but it seems that nobody can answer it clearly or even provide a reference to an answer.
I've also tried searching for tutorials, but I just cannot find any type of tutorial that explains how you would use a reusable third-party django app (most tutorials explain how to write them, none explain how to use them).
Also, I've taken a look here:
How to re-use a reusable app in Django - it doesn't explain how to actually use it IN a project itself
and here:
How to bind multiple reusable Django apps together? - the answer by aquaplanet kind of makes sense, but I thought I would ask this question to solve the mental block I am facing in trying to understand this.
In order to best explain this, let me do so by example (note, it is not something I am actually building).
I am creating a project that acts like Reddit. I will have users, links and voting/points. Based on this crude example, I will want to reuse 3 (arbitrary) third-party apps: user, voting/points and links.
I decide to use each of them as any other python package (meaning that they will be treated as a package and none of their code should be touched) [would this method actually work? Or do you have to be able to edit third-party apps to build a project??)
With these apps now within my project, I will use a main app to handle all the template stuff (meaning everything I see on the frontend will be in a single app).
I will then either use that same main app for custom logic (in views.py) or I will break up that logic among different apps (but will still use a single frontend-only app).
From the 3 paragraphs above, is this structure applicable (or can it work) ?
Now lets say that this structure is applicable and I am using a single main app for the frontend and custom logic.
What would I write in models.py? How would I integrate things from the 3 reusable apps into the main models.py file?
How would I reference the reusable apps in views.py? Lets take the example of contrib.auth
With this built-in app, for logging out I would write:
from django.contrib.auth import logout
from django.contrib.auth.decorators import login_required
from django.shortcuts import redirect
#login_required
def user_logout(request):
logout(request)
return redirect('/home/')
Although the above code is simple, is that basically how things would be done with any reusable app?
My question is very long, but I think that this reusable app issue is something a lot of developers aren't quite clear about themselves and maybe this answer will help a lot of others who have heard about the promises of reusable apps, but fail to understand how to actually use them.
TL;DR:
Nope & it depends...
Some (Very) Common Reusable Apps
django.contrib.admin
django.contrib.auth
django.contrib.staticfiles
... those are all reusable Django apps, that happen to be shipped with Django (most of them were not, at some point in time)
Ok, some other reusable apps that don't ship with Django:
django-rest-framework
django-registration
South
Those are all truly reusable apps, and nothing less. There are very many more apps like that.
How do they do it?
To me your question looks more like "how do I build reusable apps", then "how to use them". Actually using them is very different from app to app, because they do very different things. There is only one rule: RTFM No way around that either.
Often, they rely on one or more of the following:
additional value(s) in settings.py
addition (usually one include statement) to urls.py
subclassing and/or mixins for Models, Forms, Fields, Views etc.
template tags and/or filters
management commands
...
Those are all powerful ways though which your app can provide functionality to other apps. There is no recipe (AFAIK) to make a reusable app, because there are so many different scenarios to consider. It all depends on what exactly your app should do.
Reusable apps provide functionalities
I'd argue that it's important to not think of reusable apps as "working together" with other app, but instead recognize that that they "provide functionality." The details of the functionality provided should dictate the way the target developer is supposed to use your library.
Not everything should be reusable
Obviously enough, even though many apps can "in principle" be reusable, it often makes little sense to do so, because it is way faster to clump things together (and make them just "work together").
I'm not sure why you think you need a main app for the "frontend" stuff. The point of a reusable app is that it takes care of everything, you just add (usually) a single URL to include the urls.py of the app, plus your own templates and styling as required.
And you certainly don't need to wrap the app's views in your own views, unless you specifically want to override some functionality.
I don't understand at all your question about models. There's no such thing as a "main" models file, and using a reusable app's models is just the same as using models from any of your own apps.
Normally you would not edit a third-party app, that would make it very hard to integrate updates. Just install the app in your virtualenv (you are using virtualenv, of course!) with pip, which will put it in the lib directory, and you can reference it just like any other app. Make sure you add it to INSTALLED_APPS.
I am fairly new to Django, though I delved into other web frameworks in the past.
I am in a case where I need to view all instances of a model, be able to interactively sort and filter them through various criterias and execute an arbitratry treatment to the selected objects.
My initial approach would be to use the admin panel, since it seems to provide out of the box the features I'm looking for, plus authentication (as you can guess, I'm trying to set up a back office of some sort).
Nevertheless, I feel admin panels are essentially designed for another kind of use cases, and using them like that would be bad form (heh, "form"... nevermind). The end of this chapter of the Django book seems to confirm this feeling, too.
Is this the right way to go, or should I look into writing something from scratch?
I'd go django admin with no second thoughts. It provides 100% what you're looking for and it suits model-editing applications. Building something from scratch would be an extremely time intensive process. Also your final code would probably do things that admin already does, possibly in a less efficient way.
Even if you have no experience with the django admin application, the learning curve is not as high as developing a new interface + you will know how to use it in future projects.
I would just register the admin site with no admin prefix, and start from there :)
urlpatterns = patterns('',
(r'^', include(admin.site.urls)),
)
Side note: if you want to spice up the admin app you can check out various 3rd party applications that extend it, like grapelli or yawd-admin.
Admin in django is extremely powerful and flexible. You can define custom actions, validations, override the save methods, override default template etc. So it is advisable to modify the admin to suit your needs rather than writing one from scratch.
I just wanted to try to build a project with django. Therefore I have a (basic) question on how to manage such a project. Since I cannot find any guidelines or so on how to split a project into applications.
Let's take a kind of SO as an example. Which applications would you use?
I'd say there should be the applications "users" and "questions". But what if there was a topic system with static articles, too. Maybe they also could receive votes.
How to build the apps structure then? One app for "questions", "votes" and "topics" or just one app "content"?
I have no idea what to do. Maybe it's because I know not very much about Django yet, but I'm interested either...
There aren't hard-and-fast rules, but I would say it's better to err on the side of more specialized applications. Ideally an application should handle just one functional concern: i.e. "tagging" or "commenting" or "auth/auth" or "posts." This type of design will also help you reuse available open source applications instead of reinventing the wheel (i.e. Django comes with auth and comments apps, django-tagging or django-taggable can almost certainly do what you need, etc).
Generic foreign keys can help you decouple applications such as tagging or commenting that might be applied to models from several other applications.
You should try and separate the project in as much applications as possible. For most projects an application will not contain more than 5 models. For example a project like SO would have separate applications for UsersProfiles, Questions, Tags (there's a ready one in django for this), etc. If there was a system with static pages that'd be a separate application too (there are ready ones for this purpose). You should also try and make your applications as generic as possible, so you may reuse them in other projects. There's a good presentation on reusable apps.
Just like any set of dependencies... try to find the most useful stand-alone aspects of the project and make those stand-alone apps. Other Django Apps will have higher level functionality, and reuse the parts of the lowest level apps that you have set up.
In my project, I have a calendar app with its own Event object in its models. I also have a carpool database set up, and for the departure time and the duration I use the calendar's Event object right in my RideShare tables. The carpooling database is calendar-aware, and gets all the nice .ics export and calendar views from the calendar app for 'free.'
There are some tricks to getting the Apps reusable, like naming the templates directory: project/app2/templates/app2/index.html. This lets you refer to app2/index.html from any other app, and get the right template. I picked that one up looking at the built-in reusable apps in Django itself. Pinax is a bit of a monster size-wise but it also demonstrates a nice reusable App structure.
If in doubt, forget about reusable apps for now. Put all your messages and polls in one app and get through one rev. You'll discover during the process what steps feel unnecessary, and could be broken out as something stand-alone in the future.
A good question to ask yourself when deciding whether or not to write an app is "could I use this in another project?". If you think you could, then consider what it would take to make the application as independent as possible; How can you reduce the dependancies so that the app doesn't rely on anything specific to a particular project.
Some of the ways you can do this are:
Giving each app its own urls.py
Allowing model types to be passed in as parameters rather than explicitly declaring what models are used in your views. Generic views use this principle.
Make your templates easily overridden by having some sort of template_name parameter passed in your urls.py
Make sure you can do reverse url lookups with your objects and views. This means naming your views in the urls.py and creating get_absolute_url methods on your models.
In some cases like Tagging, GenericForeignKeys can be used to associate a model in your app to any other model, regardless of whether it has ForeignKeys "looking back" at it.
I'll tell you how I am approaching such question: I usually sit with a sheet of paper and draw the boxes (functionalities) and arrows (interdependencies between functionalities). I am sure there are methodologies or other things that could help you, but my approach usually works for me (YMMV, of course).
Knowing what a site is supposed to be is basic, though. ;)