mirror of https://github.com/django/django.git
Finished proofreading docs/model-api.txt
git-svn-id: http://code.djangoproject.com/svn/django/trunk@2833 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
a79cbb5fe8
commit
a8ccdd0fcd
|
@ -1298,16 +1298,22 @@ user searches for ``john lennon``, Django will do the equivalent of this SQL
|
||||||
Managers
|
Managers
|
||||||
========
|
========
|
||||||
|
|
||||||
The Manager is the interface through which database query operations
|
A ``Manager`` is the interface through which database query operations are
|
||||||
are provided to Django applications. At least one Manager exists for
|
provided to Django models. At least one ``Manager`` exists for every model in
|
||||||
every model in a Django application.
|
a Django application.
|
||||||
|
|
||||||
By default, Django will add a Manager with the name of ``objects`` to
|
The way ``Manager`` classes work is documented in the `Retrieving objects`_
|
||||||
every Django model. However, if you wish to use ``objects`` as a field
|
section of the database API docs, but this section specifically touches on
|
||||||
name, or if you wish to use a name other than ``objects`` for the Manager,
|
model options that customize ``Manager`` behavior.
|
||||||
you can rename the Manager on a per-model basis. To rename the Manager
|
|
||||||
for a given class, define a class attribute of type models.Manager()
|
Manager names
|
||||||
on that model. For example::
|
-------------
|
||||||
|
|
||||||
|
By default, Django adds a ``Manager`` with the name ``objects`` to every Django
|
||||||
|
model class. However, if you want to use ``objects`` as a field name, or if you
|
||||||
|
want to use a name other than ``objects`` for the ``Manager``, you can rename
|
||||||
|
it on a per-model basis. To rename the ``Manager`` for a given class, define a
|
||||||
|
class attribute of type ``models.Manager()`` on that model. For example::
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
|
@ -1315,38 +1321,118 @@ on that model. For example::
|
||||||
#...
|
#...
|
||||||
people = models.Manager()
|
people = models.Manager()
|
||||||
|
|
||||||
In this example, ``Person.objects.all()`` will generate an error, but
|
Using this example model, ``Person.objects`` will generate an
|
||||||
``Person.people.all()`` will provide a list of all ``Person`` objects.
|
``AttributeError`` exception, but ``Person.people.all()`` will provide a list
|
||||||
|
of all ``Person`` objects.
|
||||||
|
|
||||||
Managers can also be customized. This is achieved by extending the
|
Custom Managers
|
||||||
base Manager class, and instantiating the new Manager on your model.
|
---------------
|
||||||
There are two reasons that you may want to customize a Manager: firstly,
|
|
||||||
to add utility methods to the Manager, and secondly, to modify the
|
|
||||||
initial Query Set provided by the Manager.
|
|
||||||
|
|
||||||
To modify the initial Query Set provided by a Manager, override the
|
You can use a custom ``Manager`` in a particular model by extending the base
|
||||||
``get_query_set()`` method to return a Query Set with the properties
|
``Manager`` class and instantiating your custom ``Manager`` in your model.
|
||||||
you require. For example::
|
|
||||||
|
|
||||||
class PersonManager(models.Manager):
|
There are two reasons you might want to customize a ``Manager``: to add extra
|
||||||
# Add some custom behavior to the Manager
|
``Manager`` methods, and/or to modify the initial ``QuerySet`` the ``Manager``
|
||||||
def move_house(self):
|
returns.
|
||||||
# Some logic to help a person move house
|
|
||||||
|
|
||||||
# Modify the initial Query Set provided by the manager
|
Adding extra Manager methods
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Adding extra ``Manager`` methods is the preferred way to add "table-level"
|
||||||
|
functionality to your models. (For "row-level" functionality -- i.e., functions
|
||||||
|
that act on a single instance of a model object -- use _`Model methods`, not
|
||||||
|
custom ``Manager`` methods.)
|
||||||
|
|
||||||
|
A custom ``Manager`` method can return anything you want. It doesn't have to
|
||||||
|
return a ``QuerySet``.
|
||||||
|
|
||||||
|
For example, this custom ``Manager`` offers a method ``with_counts()``, which
|
||||||
|
returns a list of all ``OpinionPoll`` objects, each with an extra
|
||||||
|
``num_responses`` attribute that is the result of an aggregate query::
|
||||||
|
|
||||||
|
class PollManager(models.Manager):
|
||||||
|
def with_counts(self):
|
||||||
|
from django.db import connection
|
||||||
|
cursor = connection.cursor()
|
||||||
|
cursor.execute("""
|
||||||
|
SELECT p.id, p.question, p.poll_date, COUNT(*)
|
||||||
|
FROM polls_opinionpoll p, polls_response r
|
||||||
|
WHERE p.id = r.poll_id
|
||||||
|
GROUP BY 1, 2, 3
|
||||||
|
ORDER BY 3 DESC""")
|
||||||
|
result_list = []
|
||||||
|
for row in cursor.fetchall():
|
||||||
|
p = self.model(id=row[0], question=row[1], poll_date=row[2])
|
||||||
|
p.num_responses = row[3]
|
||||||
|
result_list.append(p)
|
||||||
|
return result_list
|
||||||
|
|
||||||
|
class OpinionPoll(models.Model):
|
||||||
|
question = models.CharField(maxlength=200)
|
||||||
|
poll_date = models.DateField()
|
||||||
|
objects = PollManager()
|
||||||
|
|
||||||
|
class Response(models.Model):
|
||||||
|
poll = models.ForeignKey(Poll)
|
||||||
|
person_name = models.CharField(maxlength=50)
|
||||||
|
response = models.TextField()
|
||||||
|
|
||||||
|
With this example, you'd use ``OpinionPoll.objects.with_counts()`` to return
|
||||||
|
that list of ``OpinionPoll`` objects with ``num_responses`` attributes.
|
||||||
|
|
||||||
|
Another thing to note about this example is that ``Manager`` methods can
|
||||||
|
access ``self.model`` to get the model class to which they're attached.
|
||||||
|
|
||||||
|
Modifying initial Manager QuerySets
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
A ``Manager``'s base ``QuerySet`` returns all objects in the system. For
|
||||||
|
example, using this model::
|
||||||
|
|
||||||
|
class Book(models.Model):
|
||||||
|
title = models.CharField(maxlength=100)
|
||||||
|
author = models.CharField(maxlength=50)
|
||||||
|
|
||||||
|
...the statement ``Book.objects.all()`` will return all books in the database.
|
||||||
|
|
||||||
|
You can override a ``Manager``'s base ``QuerySet`` by overriding the
|
||||||
|
``Manager.get_query_set()`` method. ``get_query_set()`` should return a
|
||||||
|
``QuerySet`` with the properties you require.
|
||||||
|
|
||||||
|
For example, the following model has *two* ``Manager``s -- one that returns
|
||||||
|
all objects, and one that returns only the books by Roald Dahl::
|
||||||
|
|
||||||
|
# First, define the Manager subclass.
|
||||||
|
class DahlBookManager(models.Manager):
|
||||||
def get_query_set(self):
|
def get_query_set(self):
|
||||||
return super(Manager, self).get_query_set().filter(name__startswith="Fred")
|
return super(Manager, self).get_query_set().filter(author='Roald Dahl')
|
||||||
|
|
||||||
class Person(models.Model):
|
# Then hook it into the Book model explicitly.
|
||||||
#...
|
class Book(models.Model):
|
||||||
objects = PersonManager()
|
title = models.CharField(maxlength=100)
|
||||||
|
author = models.CharField(maxlength=50)
|
||||||
|
|
||||||
In this example, ``Person.objects.all()`` will only return people whose name starts
|
objects = models.Manager() # The default manager.
|
||||||
with "Fred"; ``Person.objects.move_house()`` will also be available.
|
dahl_objects = DahlBookManager() # The Dahl-specific manager.
|
||||||
|
|
||||||
If required, you can add multiple Managers to a model. Every Manager attribute
|
With this sample model, ``Book.objects.all()`` will return all books in the
|
||||||
added to a model can be accessed and used as a manager. This is an easy way
|
database, but ``Book.dahl_objects.all()`` will only return the ones written by
|
||||||
to define common filters types for your models. For example, the model::
|
Roald Dahl.
|
||||||
|
|
||||||
|
Of course, because ``get_query_set()`` returns a ``QuerySet`` object, you can
|
||||||
|
use ``filter()``, ``exclude()`` and all the other ``QuerySet`` methods on it.
|
||||||
|
So these statements are all legal::
|
||||||
|
|
||||||
|
Book.dahl_objects.all()
|
||||||
|
Book.dahl_objects.filter(title='Matilda')
|
||||||
|
Book.dahl_objects.count()
|
||||||
|
|
||||||
|
This example also pointed out another interesting technique: using multiple
|
||||||
|
managers on the same model. You can attach as many ``Manager()`` instances to
|
||||||
|
a model as you'd like. This is an easy way to define common "filters" for your
|
||||||
|
models.
|
||||||
|
|
||||||
|
For example::
|
||||||
|
|
||||||
class MaleManager(models.Manager):
|
class MaleManager(models.Manager):
|
||||||
def get_query_set(self):
|
def get_query_set(self):
|
||||||
|
@ -1357,126 +1443,130 @@ to define common filters types for your models. For example, the model::
|
||||||
return super(Manager, self).get_query_set().filter(sex='F')
|
return super(Manager, self).get_query_set().filter(sex='F')
|
||||||
|
|
||||||
class Person(models.Model):
|
class Person(models.Model):
|
||||||
#...
|
first_name = models.CharField(maxlength=50)
|
||||||
|
last_name = models.CharField(maxlength=50)
|
||||||
|
sex = models.CharField(maxlength=1, choices=(('M', 'Male'), ('F', 'Female')))
|
||||||
people = models.Manager()
|
people = models.Manager()
|
||||||
men = MaleManager()
|
men = MaleManager()
|
||||||
women = FemaleManager()
|
women = FemaleManager()
|
||||||
|
|
||||||
... will allow end users to request ``Person.men.all()``, ``Person.women.all()``,
|
This example allows you to request ``Person.men.all()``, ``Person.women.all()``,
|
||||||
and ``Person.people.all()``, yielding predictable results.
|
and ``Person.people.all()``, yielding predictable results.
|
||||||
|
|
||||||
If you are going to install a customized Manager, be warned that the first
|
If you use custom ``Manager`` objects, take note that the first ``Manager``
|
||||||
Manager that Django encounters in a model definition has special status.
|
Django encounters (in order by which they're defined in the model) has a
|
||||||
Django interprets the first Manager defined in a class as the default Manager.
|
special status. Django interprets the first ``Manager`` defined in a class as
|
||||||
Certain operations use the default Manager to obtain lists of objects, so it
|
the "default" ``Manager``. Certain operations -- such as Django's admin site --
|
||||||
is generally a good idea for the first Manager to be relatively unfiltered.
|
use the default ``Manager`` to obtain lists of objects, so it's generally a
|
||||||
In the last example, ``people`` is defined first - so the default Manager
|
good idea for the first ``Manager`` to be relatively unfiltered. In the last
|
||||||
will include everyone.
|
example, the ``people`` ``Manager`` is defined first -- so it's the default
|
||||||
|
``Manager``.
|
||||||
|
|
||||||
Model methods
|
Model methods
|
||||||
=============
|
=============
|
||||||
|
|
||||||
There are a number of methods you can define on model objects to control the
|
Define custom methods on a model to add custom "row-level" functionality to
|
||||||
object's behavior. First, any methods you define will be available as methods
|
your objects. Whereas ``Manager`` methods are intended to do "table-wide"
|
||||||
of object instances. For example::
|
things, model methods should act on a particular model instance.
|
||||||
|
|
||||||
class Pizza(models.Model):
|
This is a valuable technique for keeping business logic in one place -- the
|
||||||
# ...
|
model.
|
||||||
|
|
||||||
def is_disgusting(self):
|
For example, this model has a few custom methods::
|
||||||
return "anchovies" in [topping.name for topping in self.toppings.all()]
|
|
||||||
|
|
||||||
Now, every ``Pizza`` object will have a ``is_disgusting()`` method.
|
class Person(models.Model):
|
||||||
|
first_name = models.CharField(maxlength=50)
|
||||||
|
last_name = models.CharField(maxlength=50)
|
||||||
|
birth_date = models.DateField()
|
||||||
|
address = models.CharField(maxlength=100)
|
||||||
|
city = models.CharField(maxlength=50)
|
||||||
|
state = models.USStateField() # Yes, this is America-centric...
|
||||||
|
|
||||||
See `Giving models custom methods`_ for a full example.
|
def baby_boomer_status(self):
|
||||||
|
"Returns the person's baby-boomer status."
|
||||||
|
import datetime
|
||||||
|
if datetime.date(1945, 8, 1) <= self.birth_date <= datetime.date(1964, 12, 31):
|
||||||
|
return "Baby boomer"
|
||||||
|
if self.birth_date < datetime.date(1945, 8, 1):
|
||||||
|
return "Pre-boomer"
|
||||||
|
return "Post-boomer"
|
||||||
|
|
||||||
.. _Giving models custom methods: http://www.djangoproject.com/documentation/models/custom_methods/
|
def is_midwestern(self):
|
||||||
|
"Returns True if this person is from the Midwest."
|
||||||
|
return self.state in ('IL', 'WI', 'MI', 'IN', 'OH', 'IA', 'MO')
|
||||||
|
|
||||||
|
def _get_full_name(self):
|
||||||
|
"Returns the person's full name."
|
||||||
|
return '%s %s' % (self.first_name, self.last_name)
|
||||||
|
full_name = property(_get_full_name)
|
||||||
|
|
||||||
|
The last method in this example is a *property*. `Read more about properties`_.
|
||||||
|
|
||||||
|
.. _Read more about properties: http://www.python.org/download/releases/2.2/descrintro/#property
|
||||||
|
|
||||||
A few object methods have special meaning:
|
A few object methods have special meaning:
|
||||||
|
|
||||||
``__str__``
|
``__str__``
|
||||||
Django uses ``str(obj)`` in a number of places, most notably as the value
|
-----------
|
||||||
inserted into a template when it displays an object. Thus, you should always
|
|
||||||
return a nice, human-readable string for the object's ``__str__``.
|
|
||||||
|
|
||||||
Although defining ``__str__()`` isn't required, it's strongly encouraged.
|
``__str__()`` is a Python "magic method" that defines what should be returned
|
||||||
|
if you call ``str()`` on the object. Django uses ``str(obj)`` in a number of
|
||||||
|
places, most notably as the value displayed to render an object in the Django
|
||||||
|
admin site and as the value inserted into a template when it displays an
|
||||||
|
object. Thus, you should always return a nice, human-readable string for the
|
||||||
|
object's ``__str__``. Although this isn't required, it's strongly encouraged.
|
||||||
|
|
||||||
See `Adding str`_ for a full example.
|
For example::
|
||||||
|
|
||||||
.. _Adding str: http://www.djangoproject.com/documentation/models/repr/
|
class Person(models.Model):
|
||||||
|
first_name = models.CharField(maxlength=50)
|
||||||
|
last_name = models.CharField(maxlength=50)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return '%s %s' % (self.first_name, self.last_name)
|
||||||
|
|
||||||
``get_absolute_url``
|
``get_absolute_url``
|
||||||
Define a ``get_absolute_url`` method to tell Django how to calculate the
|
|
||||||
URL for an object. For example::
|
|
||||||
|
|
||||||
def get_absolute_url(self):
|
|
||||||
return "/pizzas/%i/" % self.id
|
|
||||||
|
|
||||||
Django uses this in its admin interface. If an object defines
|
|
||||||
``get_absolute_url``, the object detail page will have a "View on site"
|
|
||||||
link that will jump you directly to the object's public view.
|
|
||||||
|
|
||||||
It's good practice to use ``get_absolute_url()`` in templates, instead of
|
|
||||||
hard-coding your objects' URLs.
|
|
||||||
|
|
||||||
Module-level methods
|
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
If you want to add a method to the Model, rather than instances of the model,
|
Define a ``get_absolute_url()`` method to tell Django how to calculate the
|
||||||
you can use the Python ``staticmethod`` and ``classmethod`` operators. For
|
URL for an object. For example::
|
||||||
example::
|
|
||||||
|
|
||||||
class Pizza(models.Model):
|
def get_absolute_url(self):
|
||||||
# ...
|
return "/people/%i/" % self.id
|
||||||
|
|
||||||
def get_pizzas_to_deliver():
|
Django uses this in its admin interface. If an object defines
|
||||||
return get_list(delivered__exact=False)
|
``get_absolute_url()``, the object-editing page will have a "View on site"
|
||||||
get_pizzas_to_deliver = staticmethod(get_pizzas_to_deliver)
|
link that will jump you directly to the object's public view, according to
|
||||||
|
``get_absolute_url()``.
|
||||||
|
|
||||||
Or, using Python 2.4 decorators::
|
Also, a couple of other bits of Django, such as the syndication-feed framework,
|
||||||
|
use ``get_absolute_url()`` as a convenience to reward people who've defined the
|
||||||
|
method.
|
||||||
|
|
||||||
# ...
|
It's good practice to use ``get_absolute_url()`` in templates, instead of
|
||||||
@staticmethod
|
hard-coding your objects' URLs. For example, this template code is bad::
|
||||||
def get_pizzas_to_deliver():
|
|
||||||
# ...
|
|
||||||
|
|
||||||
This will make the top-level ``pizzas`` module have a ``get_pizzas_to_deliver()``
|
<a href="/people/{{ object.id }}/">{{ object.name }}</a>
|
||||||
method::
|
|
||||||
|
|
||||||
>>> from pizza_hut.models import Pizza
|
But this template code is good::
|
||||||
>>> Pizza.get_pizzas_to_deliver()
|
|
||||||
[ ... ]
|
|
||||||
|
|
||||||
Manipulator methods
|
<a href="{{ object.get_absolute_url }}">{{ object.name }}</a>
|
||||||
-------------------
|
|
||||||
|
|
||||||
(The functionality in this section is going away soon. This documentation is
|
(Yes, we know ``get_absolute_url()`` couples URLs to models, which violates the
|
||||||
provided only for legacy purposes at this point.)
|
DRY principle, because URLs are defined both in a URLconf and in the model.
|
||||||
|
This is a rare case in which we've intentionally violated that principle for
|
||||||
Similarly, you can add methods to the object's manipulators by defining methods
|
the sake of convenience. With that said, we're working on an even cleaner way
|
||||||
that being with "_manipulator_". This is most useful for providing custom
|
of specifying URLs in a more DRY fashion.)
|
||||||
validators for certain fields, because manipulators automatically call any
|
|
||||||
method that begins with "validate"::
|
|
||||||
|
|
||||||
class Pizza(models.Model):
|
|
||||||
# ...
|
|
||||||
|
|
||||||
def _manipulator_validate_customer_id(self, field_data, all_data):
|
|
||||||
from django.core import validators
|
|
||||||
from django.conf.settings import BAD_CUSTOMER_IDS
|
|
||||||
|
|
||||||
if int(field_data) in BAD_CUSTOMER_IDS:
|
|
||||||
raise validators.ValidationError, "We don't deliver to this customer."
|
|
||||||
|
|
||||||
Executing custom SQL
|
Executing custom SQL
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
Feel free to write custom SQL statements in custom model methods and
|
Feel free to write custom SQL statements in custom model methods and
|
||||||
module-level methods. The object ``django.db.connection`` object represents
|
module-level methods. The object ``django.db.connection`` represents the
|
||||||
the current database connection. To use it, call ``connection.cursor()`` to
|
current database connection. To use it, call ``connection.cursor()`` to get a
|
||||||
get a cursor object. Then, call ``cursor.execute(sql, [params])``
|
cursor object. Then, call ``cursor.execute(sql, [params])`` to execute the SQL
|
||||||
to execute the SQL and ``cursor.fetchone()`` or ``cursor.fetchall()`` to return
|
and ``cursor.fetchone()`` or ``cursor.fetchall()`` to return the resulting
|
||||||
the resulting rows. Example::
|
rows. Example::
|
||||||
|
|
||||||
def my_custom_sql(self):
|
def my_custom_sql(self):
|
||||||
from django.db import connection
|
from django.db import connection
|
||||||
|
@ -1494,12 +1584,14 @@ via a ``DELETE`` or ``UPDATE`` -- you'll need to call ``db.commit()``. Example::
|
||||||
cursor.execute("DELETE FROM bar WHERE baz = %s", [self.baz])
|
cursor.execute("DELETE FROM bar WHERE baz = %s", [self.baz])
|
||||||
connection.commit()
|
connection.commit()
|
||||||
|
|
||||||
``connection`` and ``cursor`` simply use the standard `Python DB-API`_. If you're not
|
``connection`` and ``cursor`` simply use the standard `Python DB-API`_. If
|
||||||
familiar with the Python DB-API, note that the SQL statement in
|
you're not familiar with the Python DB-API, note that the SQL statement in
|
||||||
``cursor.execute()`` uses placeholders, ``"%s"``, rather than adding parameters
|
``cursor.execute()`` uses placeholders, ``"%s"``, rather than adding parameters
|
||||||
directly within the SQL. If you use this technique, the underlying database
|
directly within the SQL. If you use this technique, the underlying database
|
||||||
library will automatically add quotes and escaping to your parameter(s) as
|
library will automatically add quotes and escaping to your parameter(s) as
|
||||||
necessary.
|
necessary. (Also note that Django expects the ``"%s"`` placeholder, *not* the
|
||||||
|
``"?"`` placeholder, which is used by the SQLite Python bindings. This is for
|
||||||
|
the sake of consistency and sanity.)
|
||||||
|
|
||||||
A final note: If all you want to do is a custom ``WHERE`` clause, you can just
|
A final note: If all you want to do is a custom ``WHERE`` clause, you can just
|
||||||
just the ``where``, ``tables`` and ``params`` arguments to the standard lookup
|
just the ``where``, ``tables`` and ``params`` arguments to the standard lookup
|
||||||
|
@ -1508,32 +1600,35 @@ API. See `Other lookup options`_.
|
||||||
.. _Python DB-API: http://www.python.org/peps/pep-0249.html
|
.. _Python DB-API: http://www.python.org/peps/pep-0249.html
|
||||||
.. _Other lookup options: http://www.djangoproject.com/documentation/db_api/#extra-params-select-where-tables
|
.. _Other lookup options: http://www.djangoproject.com/documentation/db_api/#extra-params-select-where-tables
|
||||||
|
|
||||||
Using models
|
|
||||||
============
|
|
||||||
|
|
||||||
Once you have created your model, you have to tell Django about your new application.
|
|
||||||
This is done by editing your settings file and adding the name of the module that
|
|
||||||
contains your models module to the ``INSTALLED_APPS`` tuple.
|
|
||||||
|
|
||||||
For example, if the models for your application are contained in the module
|
|
||||||
``project.myapp.models`` (the package structure that is created for an application
|
|
||||||
by the ``django-admin.py startapp`` script), ``INSTALLED_APPS`` should read, in part::
|
|
||||||
|
|
||||||
INSTALLED_APPS = (
|
|
||||||
#...
|
|
||||||
project.myapp,
|
|
||||||
#...
|
|
||||||
)
|
|
||||||
|
|
||||||
Models across files
|
Models across files
|
||||||
===================
|
===================
|
||||||
|
|
||||||
It's perfectly OK to relate a model to one from another module. To do this,
|
It's perfectly OK to relate a model to one from another app. To do this, just
|
||||||
just import the model module at the top of your model module. Then, just
|
import the related model at the top of the model that holds your model. Then,
|
||||||
refer to the other model class wherever needed. For example::
|
just refer to the other model class wherever needed. For example::
|
||||||
|
|
||||||
from myproject.otherapp import Site
|
from mysite.geography.models import ZipCode
|
||||||
|
|
||||||
class MyModel(models.Model):
|
class Restaurant(models.Model):
|
||||||
# ...
|
# ...
|
||||||
sites = models.ManyToManyField(Site)
|
zip_code = models.ForeignKey(ZipCode)
|
||||||
|
|
||||||
|
Using models
|
||||||
|
============
|
||||||
|
|
||||||
|
Once you have created your models, the final step is to tell Django you're
|
||||||
|
going to *use* those models.
|
||||||
|
|
||||||
|
Do this by editing your settings file and changing the ``INSTALLED_APPS``
|
||||||
|
setting to add the name of the module that contains your ``models.py``.
|
||||||
|
|
||||||
|
For example, if the models for your application live in the module
|
||||||
|
``mysite.myapp.models`` (the package structure that is created for an
|
||||||
|
application by the ``manage.py startapp`` script), ``INSTALLED_APPS`` should
|
||||||
|
read, in part::
|
||||||
|
|
||||||
|
INSTALLED_APPS = (
|
||||||
|
#...
|
||||||
|
'mysite.myapp',
|
||||||
|
#...
|
||||||
|
)
|
||||||
|
|
Loading…
Reference in New Issue