User Tools

Site Tools


python:django

Django

refer:

docs:

With Django, you can take Web applications from concept to launch in a matter of hours. Django takes care of much of the hassle of Web development, so you can focus on writing your app without needing to reinvent the wheel. It’s free and open source.

Install and Run django

Setup lib python django

latest official version: 1.8 Previous releases

  • Django 1.7.7: Django-1.7.7.tar.gz
  • Django 1.4.20 (LTS): Django-1.4.20.tar.gz

Unsupported previous releases (no longer receive security updates or bug fixes):

  • Django 1.6.11: Django-1.6.11.tar.gz
  • Django 1.5.12: Django-1.5.12.tar.gz

⇒ You should use version 1.7.7

Install from source

Go to django source and run below commands:

set PATH=%PATH%;"d:\tools\Python27"
python setup.py install

→ recheck:

/usr/lib/python2.7/site-packages (Unix, Python 2.7)
d:\tools\Python27\Lib\site-packages\Django-xxx         (Windows)

Install with pip

pip install Django==1.8

check django version installed

python -c "import django; print(django.get_version())"

⇒ output:

1.8

create project mysite

(Linux: Put your code in some directory outside of the document root, such as /home/mycode)

windows:

d:\tools\Python27\Scripts\django-admin.exe startproject mysite

linux:

django-admin.py startproject mysite

run

cd mysite
python manage.py runserver
python manage.py runserver 8080 -> run another port

Create virtual environment and run django

Why create virtual environment?Because with each django source, they compatible with each other version of django, so you must create the virtual enviornment for that version of django and not affect the other django source which run other django version

  1. Step1: Install virtualenv:
    pip install virtualenv
  2. Step2: Create new virtualenv and install django
    virtualenv django1.8
    django1.8\Scripts\activate
    pip install Django==1.8
  3. Step3: Create new project on virtualenv
    django-admin startproject mysite
    cd mysite
    python manage.py runserver

config apps(model) in django

  • config apps:
    [mysite/settings.py]
      INSTALLED_APPS = (
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
      )
  • sync app config to auto generate db
      python manage.py syncdb
    
    -> The syncdb command looks at the INSTALLED_APPS setting and creates any necessary database tables according to the database settings in your  file

create models in django

Run script create polls model

python manage.py startapp polls

edit [mysite\polls\models.py]

from django.db import models
 
# Create your models here.
class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')
class Choice(models.Model):
    question = models.ForeignKey(Question)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

config to install polls model

[mysite/settings.py]

INSTALLED_APPS = (
  ..................
  'polls',
)

generate scripts for polls from model config in [mysite\polls\models.py]

python manage.py makemigrations

output:

Migrations for 'polls':
  0001_initial.py:
    - Create model Question
    - Create model Choice

generate database for polls model

python manage.py syncdb

config generate admin for polls model

edit [mysite\polls\admin.py]

from polls.models import Question
# Register your models here.
admin.site.register(Question)

write routing urls(URL Dispatcher) and view for poll

refer: https://docs.djangoproject.com/en/1.7/intro/tutorial03/

  1. Step1: Open the file polls/views.py and put the following Python code in it:
    from django.shortcuts import render
    from django.http import HttpResponse
     
    # Create your views here.
    def index(request):
        return HttpResponse("Hello, world. You're at the polls index.")
  2. Step2: To create a URLconf in the polls directory, create a file called urls.py. Your app directory should now look like:
    polls/
        __init__.py
        admin.py
        models.py
        tests.py
        urls.py
        views.py
  3. Step3: include code to polls/urls.py
    from django.conf.urls import patterns, url
     
    from polls import views
     
    urlpatterns = patterns('',
        url(r'^$', views.index, name='index'),
    )
  4. Step4: In mysite/urls.py(root URLconf) insert an include() of polls/urls.py:
    from django.conf.urls import patterns, include, url
    from django.contrib import admin
     
    urlpatterns = patterns('',
        # Examples:
        # url(r'^$', 'firstdjango.views.home', name='home'),
        # url(r'^blog/', include('blog.urls')),
        url(r'^polls/', include('polls.urls')),
        url(r'^admin/', include(admin.site.urls)),
    )
  5. Step4: run server and go to link http://127.0.0.1:8000/polls/ to test the polls

Mysql to django models

python manage.py inspectdb

Django Template Language

refer:

A template is simply a text file. It can generate any text-based format (HTML, XML, CSV, etc.).

A template contains variables, which get replaced with values when the template is evaluated, and tags, which control the logic of the template:

  • variables: Syntax
    {{ variable }}

    . For example:

    {{ section.title }}
  • tags: Tags are surrounded by {% and %} like this:{% csrf_token %} . Refer https://docs.djangoproject.com/en/1.6/ref/templates/builtins/#ref-templates-builtins-tags
    • filters: You can modify variables for display by using filters.
    • if: condition control tag
    • for: loop control tag
    • block and extends: Set up template inheritance , a powerful way of cutting down on “boilerplate” in templates.

Below is a minimal template that illustrates a few basics. Each element will be explained later in this document.

{% extends "base_generic.html" %}
 
{% block title %}{{ section.title }}{% endblock %}
 
{% block content %}
<h1>{{ section.title }}</h1>
 
{% for story in story_list %}
<h2>
  <a href="{{ story.get_absolute_url }}">
    {{ story.headline|upper }}
  </a>
</h2>
<p>{{ story.tease|truncatewords:"100" }}</p>
{% endfor %}
{% endblock %}

Basic example for template inheritance:

  • we have base.html:
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <link rel="stylesheet" href="style.css" />
        <title>{% block title %}My amazing site{% endblock %}</title>
    </head>
     
    <body>
        <div id="sidebar">
            {% block sidebar %}
            <ul>
                <li><a href="/">Home</a></li>
                <li><a href="/blog/">Blog</a></li>
            </ul>
            {% endblock %}
        </div>
     
        <div id="content">
            {% block content %}{% endblock %}
        </div>
    </body>
    </html>
  • we create the child template which extend from base.html:
    {% extends "base.html" %}
     
    {% block title %}My amazing blog{% endblock %}
     
    {% block content %}
    {% for entry in blog_entries %}
        <h2>{{ entry.title }}</h2>
        <p>{{ entry.body }}</p>
    {% endfor %}
    {% endblock %}

    At that point, the template engine will notice the three block tags in base.html and replace those blocks with the contents of the child template. Depending on the value of blog_entries, the output might look like:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <link rel="stylesheet" href="style.css" />
        <title>My amazing blog</title>
    </head>
     
    <body>
        <div id="sidebar">
            <ul>
                <li><a href="/">Home</a></li>
                <li><a href="/blog/">Blog</a></li>
            </ul>
        </div>
     
        <div id="content">
            <h2>Entry one</h2>
            <p>This is my first entry.</p>
     
            <h2>Entry two</h2>
            <p>This is my second entry.</p>
        </div>
    </body>
    </html>

django packages

Mezzanine cms

Dependencies

Mezzanine makes use of as few libraries as possible (apart from a standard Django environment), with the following dependencies:

  • Python 2.6 / 2.7 / 3.3
  • Django 1.4 / 1.5 / 1.6 ⇒ Best match: Django 1.6.11(We must re-install Django 1.6.11 to run mezzanine)
  • Pillow - for image resizing (Python Imaging Library fork)
  • grappelli-safe - admin skin (Grappelli fork)
  • filebrowser-safe - for managing file uploads (FileBrowser fork)
  • bleach and BeautifulSoup - for sanitizing markup in content
  • pytz and tzlocal - for timezone support
  • South - for database migrations (optional)
  • django-compressor - for merging JS/CSS assets (optional)
  • requests and requests_oauthlib - for interacting with external APIs
  • pyflakes and pep8 - for running the test suite (optional)

Auto install these dependencies when we install mezzanine

install

Install on windows:

easy_install.exe mezzanine

Install on linux:

pip install mezzanine

Create project and run

  • Step1: Create project:
    mezzanine-project mezzcms
  • Step2: sync db
    python manage.py syncdb
  • Step3: Run
    python manage.py runserver

Config using mezzcms in settings.py

  1. INSTALLED_APPS
    INSTALLED_APPS = (
        "django.contrib.admin",
        "django.contrib.auth",
        "django.contrib.contenttypes",
        "django.contrib.redirects",
        "django.contrib.sessions",
        "django.contrib.sites",
        "django.contrib.sitemaps",
        "django.contrib.staticfiles",
        "mezzanine.boot",
        "mezzanine.conf",
        "mezzanine.core",
        "mezzanine.generic",
        "mezzanine.blog",
        "mezzanine.forms",
        "mezzanine.pages",
        "mezzanine.galleries",
        "mezzanine.twitter",
        #"mezzanine.accounts",
        #"mezzanine.mobile",
    )

    with mezzaine apps

        "mezzanine.boot",
        "mezzanine.conf",
        "mezzanine.core",
        "mezzanine.generic",
        "mezzanine.blog",
        "mezzanine.forms",
        "mezzanine.pages",
        "mezzanine.galleries",
        "mezzanine.twitter",
        #"mezzanine.accounts",
        #"mezzanine.mobile",
  2. TEMPLATE_CONTEXT_PROCESSORS:
    TEMPLATE_CONTEXT_PROCESSORS = (
        "django.contrib.auth.context_processors.auth",
        "django.contrib.messages.context_processors.messages",
        "django.core.context_processors.debug",
        "django.core.context_processors.i18n",
        "django.core.context_processors.static",
        "django.core.context_processors.media",
        "django.core.context_processors.request",
        "django.core.context_processors.tz",
        "mezzanine.conf.context_processors.settings",
        "mezzanine.pages.context_processors.page",
    )

    with TEMPLATE_CONTEXT_PROCESSORS for mezzaine:

        "mezzanine.conf.context_processors.settings",
        "mezzanine.pages.context_processors.page",
  3. MIDDLEWARE_CLASSES:
    MIDDLEWARE_CLASSES = (
        "mezzanine.core.middleware.UpdateCacheMiddleware",
        "django.contrib.sessions.middleware.SessionMiddleware",
        "django.middleware.locale.LocaleMiddleware",
        "django.contrib.auth.middleware.AuthenticationMiddleware",
        "django.middleware.common.CommonMiddleware",
        "django.middleware.csrf.CsrfViewMiddleware",
        "django.contrib.messages.middleware.MessageMiddleware",
        "mezzanine.core.request.CurrentRequestMiddleware",
        "mezzanine.core.middleware.RedirectFallbackMiddleware",
        "mezzanine.core.middleware.TemplateForDeviceMiddleware",
        "mezzanine.core.middleware.TemplateForHostMiddleware",
        "mezzanine.core.middleware.AdminLoginInterfaceSelectorMiddleware",
        "mezzanine.core.middleware.SitePermissionMiddleware",
        # Uncomment the following if using any of the SSL settings:
        # "mezzanine.core.middleware.SSLRedirectMiddleware",
        "mezzanine.pages.middleware.PageMiddleware",
        "mezzanine.core.middleware.FetchFromCacheMiddleware",
    )

    with MIDDLEWARE_CLASSES for mezzanine:

        "mezzanine.core.request.CurrentRequestMiddleware",
        "mezzanine.core.middleware.RedirectFallbackMiddleware",
        "mezzanine.core.middleware.TemplateForDeviceMiddleware",
        "mezzanine.core.middleware.TemplateForHostMiddleware",
        "mezzanine.core.middleware.AdminLoginInterfaceSelectorMiddleware",
        "mezzanine.core.middleware.SitePermissionMiddleware",
        # Uncomment the following if using any of the SSL settings:
        # "mezzanine.core.middleware.SSLRedirectMiddleware",
        "mezzanine.pages.middleware.PageMiddleware",
        "mezzanine.core.middleware.FetchFromCacheMiddleware",

Config route in urls.py

PROJ_NAME/urls.py

urlpatterns = i18n_patterns("",
    # Change the admin prefix here to use an alternate URL for the
    # admin interface, which would be marginally more secure.
    ("^admin/", include(admin.site.urls)),
)
 
urlpatterns += patterns('',
 
    # We don't want to presume how your homepage works, so here are a
    # few patterns you can use to set it up.
 
    # HOMEPAGE AS STATIC TEMPLATE
    # ---------------------------
    # This pattern simply loads the index.html template. It isn't
    # commented out like the others, so it's the default. You only need
    # one homepage pattern, so if you use a different one, comment this
    # one out.
 
    url("^$", direct_to_template, {"template": "index.html"}, name="home"),
 
    # HOMEPAGE AS AN EDITABLE PAGE IN THE PAGE TREE
    # ---------------------------------------------
    # This pattern gives us a normal ``Page`` object, so that your
    # homepage can be managed via the page tree in the admin. If you
    # use this pattern, you'll need to create a page in the page tree,
    # and specify its URL (in the Meta Data section) as "/", which
    # is the value used below in the ``{"slug": "/"}`` part.
    # Also note that the normal rule of adding a custom
    # template per page with the template name using the page's slug
    # doesn't apply here, since we can't have a template called
    # "/.html" - so for this case, the template "pages/index.html"
    # should be used if you want to customize the homepage's template.
 
    # url("^$", "mezzanine.pages.views.page", {"slug": "/"}, name="home"),
 
    # HOMEPAGE FOR A BLOG-ONLY SITE
    # -----------------------------
    # This pattern points the homepage to the blog post listing page,
    # and is useful for sites that are primarily blogs. If you use this
    # pattern, you'll also need to set BLOG_SLUG = "" in your
    # ``settings.py`` module, and delete the blog page object from the
    # page tree in the admin if it was installed.
 
    # url("^$", "mezzanine.blog.views.blog_post_list", name="home"),
 
    # MEZZANINE'S URLS
    # ----------------
    # ADD YOUR OWN URLPATTERNS *ABOVE* THE LINE BELOW.
    # ``mezzanine.urls`` INCLUDES A *CATCH ALL* PATTERN
    # FOR PAGES, SO URLPATTERNS ADDED BELOW ``mezzanine.urls``
    # WILL NEVER BE MATCHED!
 
    # If you'd like more granular control over the patterns in
    # ``mezzanine.urls``, go right ahead and take the parts you want
    # from it, and use them directly below instead of using
    # ``mezzanine.urls``.
    ("^", include("mezzanine.urls")),
 
    # MOUNTING MEZZANINE UNDER A PREFIX
    # ---------------------------------
    # You can also mount all of Mezzanine's urlpatterns under a
    # URL prefix if desired. When doing this, you need to define the
    # ``SITE_PREFIX`` setting, which will contain the prefix. Eg:
    # SITE_PREFIX = "my/site/prefix"
    # For convenience, and to avoid repeating the prefix, use the
    # commented out pattern below (commenting out the one above of course)
    # which will make use of the ``SITE_PREFIX`` setting. Make sure to
    # add the import ``from django.conf import settings`` to the top
    # of this file as well.
    # Note that for any of the various homepage patterns above, you'll
    # need to use the ``SITE_PREFIX`` setting as well.
 
    # ("^%s/" % settings.SITE_PREFIX, include("mezzanine.urls"))
 
)
 
# Adds ``STATIC_URL`` to the context of error pages, so that error
# pages can use JS, CSS and images.
handler404 = "mezzanine.core.views.page_not_found"
handler500 = "mezzanine.core.views.server_error"

And below are config route and view of module mezzanine.accounts:

  • in mezzanine/urls.py
    if _old_accounts_enabled or "mezzanine.accounts" in settings.INSTALLED_APPS:
        # We don't define a URL prefix here such as /account/ since we want
        # to honour the LOGIN_* settings, which Django has prefixed with
        # /account/ by default. So those settings are used in accounts.urls
        urlpatterns += patterns("",
            ("^", include("mezzanine.accounts.urls")),
        )
  • and route in mezzanine.accounts.urls
    from __future__ import unicode_literals
     
    from django.conf.urls import patterns, url
     
    from mezzanine.conf import settings
     
     
    ACCOUNT_URL = getattr(settings, "ACCOUNT_URL", "/accounts/")
    OLD_ACCOUNT_URL = "/account/"
    SIGNUP_URL = getattr(settings, "SIGNUP_URL",
                         "/%s/signup/" % ACCOUNT_URL.strip("/"))
    SIGNUP_VERIFY_URL = getattr(settings, "SIGNUP_VERIFY_URL",
                                "/%s/verify/" % ACCOUNT_URL.strip("/"))
    LOGIN_URL = settings.LOGIN_URL
    LOGOUT_URL = settings.LOGOUT_URL
    PROFILE_URL = getattr(settings, "PROFILE_URL", "/users/")
    PROFILE_UPDATE_URL = getattr(settings, "PROFILE_UPDATE_URL",
                                 "/%s/update/" % ACCOUNT_URL.strip("/"))
    PASSWORD_RESET_URL = getattr(settings, "PASSWORD_RESET_URL",
                                 "/%s/password/reset/" % ACCOUNT_URL.strip("/"))
    PASSWORD_RESET_VERIFY_URL = getattr(settings, "PASSWORD_RESET_VERIFY_URL",
                                        "/%s/password/verify/" %
                                        ACCOUNT_URL.strip("/"))
     
    _verify_pattern = "/(?P<uidb36>[-\w]+)/(?P<token>[-\w]+)"
    _slash = "/" if settings.APPEND_SLASH else ""
     
    urlpatterns = patterns("mezzanine.accounts.views",
        url("^%s%s$" % (LOGIN_URL.strip("/"), _slash),
            "login", name="login"),
        url("^%s%s$" % (LOGOUT_URL.strip("/"), _slash),
            "logout", name="logout"),
        url("^%s%s$" % (SIGNUP_URL.strip("/"), _slash),
            "signup", name="signup"),
        url("^%s%s%s$" % (SIGNUP_VERIFY_URL.strip("/"), _verify_pattern, _slash),
            "signup_verify", name="signup_verify"),
        url("^%s%s$" % (PROFILE_UPDATE_URL.strip("/"), _slash),
            "profile_update", name="profile_update"),
        url("^%s%s$" % (PASSWORD_RESET_URL.strip("/"), _slash),
            "password_reset", name="mezzanine_password_reset"),
        url("^%s%s%s$" %
            (PASSWORD_RESET_VERIFY_URL.strip("/"), _verify_pattern, _slash),
            "password_reset_verify", name="password_reset_verify"),
        url("^%s%s$" % (ACCOUNT_URL.strip("/"), _slash),
            "account_redirect", name="account_redirect"),
        url("^%s(/(?P<url_suffix>.*))?%s$" % (OLD_ACCOUNT_URL.strip("/"), _slash),
            "old_account_redirect", name="old_account_redirect"),
    )
     
    if settings.ACCOUNTS_PROFILE_VIEWS_ENABLED:
        urlpatterns += patterns("mezzanine.accounts.views",
            url("^%s%s$" % (PROFILE_URL.strip("/"), _slash),
                "profile_redirect", name="profile_redirect"),
            url("^%s/(?P<username>.*)%s$" % (PROFILE_URL.strip("/"), _slash),
                "profile", name="profile"),
        )
  • And login, logout view in mezzaine.accounts.views
    def login(request, template="accounts/account_login.html"):
        """
        Login form.
        """
        form = LoginForm(request.POST or None)
        if request.method == "POST" and form.is_valid():
            authenticated_user = form.save()
            info(request, _("Successfully logged in"))
            auth_login(request, authenticated_user)
            return login_redirect(request)
        context = {"form": form, "title": _("Log in")}
        return render(request, template, context)
     
     
    def logout(request):
        """
        Log the user out.
        """
        auth_logout(request)
        info(request, _("Successfully logged out"))
        return redirect(next_url(request) or get_script_prefix())

update new theme for mezzanine

  • config templates in the project:
    TEMPLATE_DIRS = (os.path.join(PROJECT_ROOT, "templates"),)
    TEMPLATE_LOADERS = (
        "django.template.loaders.filesystem.Loader",
        "django.template.loaders.app_directories.Loader",
    )

    ⇒ we will override the original template of mezzanine by create new template on directory templates

  • download new theme:

django shop

django forms

Experiences about django framework

django and software pattern

  1. Loose Coupling:
    • One key feature of the MVC architecture, and of Django’s slightly modified form, is the notion that sections of code that perform significantly different functions shouldn’t rely on how the others operate. This is called loose coupling. Contrast this with tight coupling, where modules often rely heavily on the internal details of other modules’implementations.
    • Tight coupling causes a whole host of problems with long-term code maintenance, as significant changes to one section will invariably affect others. This creates a mountain of extra work for the programmer, having to change code that has little—if anything—to do with the work that needs to be done. This extra work doesn’t only affect the programmer; it's often quite costly for the employers as well. Tight coupling also makes testing more difficult because it’s harder to isolate individual behaviors.
    • It may seem that loose coupling advocates that no code should ever know anything about any other code, but that’s hardly the case, as a program written like that couldn’t do anything at all. Some sections of code will always need to reference others; that’s unavoidable. The key is to rely on implementation details as little as possible.
    • In Python, loose coupling is typically provided in a number of ways, some of which are shown in the following list. There are countless others, which could fill a book on their own, but the techniques shown here are described in detail in Chapter 2.
      • Duck typing
      • Operator overloading
      • Signals and dispatching
      • Plugins
  2. Don’t Repeat Yourself (DRY):
    • If you’ve been around the block a few times, you know all too well how easy it is to write “boilerplate” code. You code once for one purpose, then again for another, and again, and again, and again. After a while, you realize how much
    • code has been duplicated, and if you’re lucky, you have the time, energy and presence of mind to look at what’s common and move those pieces into a common location. This process is one of the primary reasons for a framework to exist. Frameworks provide much of this common code, while attempting to make it easier to avoid duplicating your own code in the future. This combines to represent a common programming practice: Don’t Repeat Yourself.
    • The basic idea is that you should only write something once. That reduces the risk of accidentally introducing inconsistency between two pieces of code that should match. It should also be as reusable as possible, and if other code needs to know something about what you’ve already written, you should be able to get the necessary information automatically using Python, without requiring the programmer to repeat any of that information.
    • To facilitate this, Python provides a wealth of resources for peeking inside your code, a process called introspection. Many of these resources, covered in Chapter 2, are incredibly useful when supporting DRY in your code.
  3. Failing Loudly: “Errors should never pass silently. / Unless explicitly silenced.” This may seem like a simple sentiment, but at two lines, it comprises over 10 percent of the Zen of Python, and there’s something to be said for that. Dealing with exceptions is an important part of programming, and this is especially true in Python. All programming languages can generate errors, and most have a way to handle them gracefully, but each language has its own best practices for dealing with them.
  4. django.contrib package: An interesting gray area is the django.contrib package. It’s distributed inside with the main Django distribution, and thus would qualify as being part of core, but they’re designed as if they could be third-party applications. The goal was that if a third-party application was written well enough, gained enough traction in the community and had a promise of continued support, it could be pulled into core eventually. In practice, though, it’s more commonly gone the other direction, with django.contrib packages removed from core and maintained as third-party applications instead. Below are some django.contrib packages:
    • admin
    • admindocs
    • auth
    • comments
    • contenttypes
    • flatpages
    • formtools
    • gis
    • humanize
    • messages
    • redirects
    • sessions
    • sitemaps
    • sites
    • staticfiles
    • syndication
    • webdesign
  5. Reusable Applications: One of the most valuable aspects of Django is its focus on application-based development. Rather than building each site from scratch, developers should write applications for specific purposes, and then combine them to build a site.
    • This philosophy encourages many community members to release their applications to the public, as open source, so that others can benefit from their features.Developers are free to host their applications anywhere they wish, but many choose GitHub,6 due to its rich features and very active developer community. In fact, it’s where Django itself is hosted. GitHub incorporates its own issue-tracking system, making it easy to maintain everything in one place. Many applications7 are hosted there, so it’s definitely a good idea to spend a few minutes looking around to see if someone has already written something you need. You can also find and compare third-party applications at Django Packages.8
    • After all, that’s one of the primary goals of open source software: a larger community can produce better, cleaner, more functional code than a smaller group of dedicated programmers. The Django community both exhibits this behavior and encourages others to take advantage of it.

Những module mà opensource có và cách sử dụng trong django

django có sẵn những tính năng mặc định sẽ được cài bên dưới:

'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',

Bên dưới ta sẽ liệt kê một số tính năng mà opensource có sẵn và cách hỗ trợ những tính năng này trong django:

  • admin, auth, sessions: django.contrib.admin, django.contrib.auth, django.contrib.sessions
  • Cache: core.cache
  • Định tuyến cho URL: urls.py trong django
  • mail: core.mail
  • search engine
  • Đa ngôn ngữ cho text
  • Đa ngôn ngữ cho nội dung lưu trong database
  • Banner
  • Danh mục
  • Plugin: facebook, SEO, Google Analytics, Google Maps
  • CMS
  • Layout and Block

Kinh nghiệm sử dụng lại những module đã được phát triển bởi cộng đồng django: django là framework được thiết kế với chuẩn DRY, vì thế những module mà cộng đồng phát triển có thể sử dụng lại và được tích hợp vào ứng dụng của mình một cách dễ dàng. Thông thường khi cộng đồng phát triển module như thế, ngoài việc đưa module đó vào INSTALLED_APPS cho việc load module và install những table cần thiết liên quan đến module, cần cung cấp một đối tượng dạng Manager, hoặc file cấu hình của module để giúp module đó tương tác với module khác

Django themes

python/django.txt · Last modified: 2017/01/12 09:12 (external edit)