Django

Code

Show
Ignore:
Timestamp:
06/17/07 17:18:54 (2 years ago)
Author:
clong
Message:

per-object-permissions: Merged to trunk [5486] NOTE: Not fully tested, will be working on this over the next few weeks.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/branches/per-object-permissions/tests/modeltests/basic/models.py

    r4242 r5488  
    1313    class Meta: 
    1414        ordering = ('pub_date','headline') 
    15          
     15 
    1616    def __str__(self): 
    1717        return self.headline 
     
    320320>>> Article.objects.all() 
    321321[<Article: Article 6>, <Article: Default headline>, <Article: Article 7>, <Article: Updated article 8>] 
    322  
    323322"""} 
    324323 
     
    359358>>> Article.objects.get(headline="Article 10") 
    360359<Article: Article 10> 
    361 """ 
     360 
     361# Edge-case test: A year lookup should retrieve all objects in the given 
     362year, including Jan. 1 and Dec. 31. 
     363>>> a11 = Article.objects.create(headline='Article 11', pub_date=datetime(2008, 1, 1)) 
     364>>> a12 = Article.objects.create(headline='Article 12', pub_date=datetime(2008, 12, 31, 23, 59, 59, 999999)) 
     365>>> Article.objects.filter(pub_date__year=2008) 
     366[<Article: Article 11>, <Article: Article 12>] 
     367""" 
  • django/branches/per-object-permissions/tests/modeltests/custom_columns/models.py

    r3669 r5488  
    11""" 
    2 17. Custom column names 
     217. Custom column/table names 
    33 
    44If your database column name is different than your model attribute, use the 
    55``db_column`` parameter. Note that you'll use the field's name, not its column 
    66name, in API usage. 
     7 
     8If your database table name is different than your model name, use the 
     9``db_table`` Meta attribute. This has no effect on the API used to  
     10query the database. 
     11 
     12If you need to use a table name for a many-to-many relationship that differs  
     13from the default generated name, use the ``db_table`` parameter on the  
     14ManyToMany field. This has no effect on the API for querying the database. 
     15 
    716""" 
    817 
    918from django.db import models 
    1019 
    11 class Person(models.Model): 
     20class Author(models.Model): 
    1221    first_name = models.CharField(maxlength=30, db_column='firstname') 
    1322    last_name = models.CharField(maxlength=30, db_column='last') 
     
    1625        return '%s %s' % (self.first_name, self.last_name) 
    1726 
     27    class Meta: 
     28        db_table = 'my_author_table' 
     29        ordering = ('last_name','first_name') 
     30 
     31class Article(models.Model): 
     32    headline = models.CharField(maxlength=100) 
     33    authors = models.ManyToManyField(Author, db_table='my_m2m_table') 
     34 
     35    def __str__(self): 
     36        return self.headline 
     37 
     38    class Meta: 
     39        ordering = ('headline',) 
     40         
    1841__test__ = {'API_TESTS':""" 
    19 # Create a Person
    20 >>> p = Person(first_name='John', last_name='Smith') 
    21 >>> p.save() 
     42# Create a Author
     43>>> a = Author(first_name='John', last_name='Smith') 
     44>>> a.save() 
    2245 
    23 >>> p.id 
     46>>> a.id 
    24471 
    2548 
    26 >>> Person.objects.all() 
    27 [<Person: John Smith>] 
     49# Create another author 
     50>>> a2 = Author(first_name='Peter', last_name='Jones') 
     51>>> a2.save() 
    2852 
    29 >>> Person.objects.filter(first_name__exact='John') 
    30 [<Person: John Smith>] 
     53# Create an article 
     54>>> art = Article(headline='Django lets you build web apps easily') 
     55>>> art.save() 
     56>>> art.authors = [a, a2] 
    3157 
    32 >>> Person.objects.get(first_name__exact='John') 
    33 <Person: John Smith> 
     58# Although the table and column names on Author have been set to  
     59# custom values, nothing about using the Author model has changed... 
    3460 
    35 >>> Person.objects.filter(firstname__exact='John') 
     61# Query the available authors 
     62>>> Author.objects.all() 
     63[<Author: Peter Jones>, <Author: John Smith>] 
     64 
     65>>> Author.objects.filter(first_name__exact='John') 
     66[<Author: John Smith>] 
     67 
     68>>> Author.objects.get(first_name__exact='John') 
     69<Author: John Smith> 
     70 
     71>>> Author.objects.filter(firstname__exact='John') 
    3672Traceback (most recent call last): 
    3773    ... 
    38 TypeError: Cannot resolve keyword 'firstname' into field 
     74TypeError: Cannot resolve keyword 'firstname' into field. Choices are: article, id, first_name, last_name 
    3975 
    40 >>> p = Person.objects.get(last_name__exact='Smith') 
    41 >>> p.first_name 
     76>>> a = Author.objects.get(last_name__exact='Smith') 
     77>>> a.first_name 
    4278'John' 
    43 >>> p.last_name 
     79>>> a.last_name 
    4480'Smith' 
    45 >>> p.firstname 
     81>>> a.firstname 
    4682Traceback (most recent call last): 
    4783    ... 
    48 AttributeError: 'Person' object has no attribute 'firstname' 
    49 >>> p.last 
     84AttributeError: 'Author' object has no attribute 'firstname' 
     85>>> a.last 
    5086Traceback (most recent call last): 
    5187    ... 
    52 AttributeError: 'Person' object has no attribute 'last' 
     88AttributeError: 'Author' object has no attribute 'last' 
     89 
     90# Although the Article table uses a custom m2m table,  
     91# nothing about using the m2m relationship has changed... 
     92 
     93# Get all the authors for an article 
     94>>> art.authors.all() 
     95[<Author: Peter Jones>, <Author: John Smith>] 
     96 
     97# Get the articles for an author 
     98>>> a.article_set.all() 
     99[<Article: Django lets you build web apps easily>] 
     100 
     101# Query the authors across the m2m relation 
     102>>> art.authors.filter(last_name='Jones') 
     103[<Author: Peter Jones>] 
     104 
    53105"""} 
  • django/branches/per-object-permissions/tests/modeltests/empty/models.py

    r3669 r5488  
    11""" 
    2 Empty model tests 
     239. Empty model tests 
    33 
    44These test that things behave sensibly for the rare corner-case of a model with 
  • django/branches/per-object-permissions/tests/modeltests/field_defaults/models.py

    r3669 r5488  
    11""" 
    2 31. Callable defaults 
     232. Callable defaults 
    33 
    44You can pass callable objects as the ``default`` parameter to a field. When 
  • django/branches/per-object-permissions/tests/modeltests/generic_relations/models.py

    r3669 r5488  
    11""" 
    2 33. Generic relations 
     234. Generic relations 
    33 
    44Generic relations let an object have a foreign key to any object through a 
     
    1212from django.db import models 
    1313from django.contrib.contenttypes.models import ContentType 
     14from django.contrib.contenttypes import generic 
    1415 
    1516class TaggedItem(models.Model): 
     
    1920    object_id = models.PositiveIntegerField() 
    2021     
    21     content_object = models.GenericForeignKey() 
     22    content_object = generic.GenericForeignKey() 
    2223     
    2324    class Meta: 
     
    3132    latin_name = models.CharField(maxlength=150) 
    3233     
    33     tags = models.GenericRelation(TaggedItem) 
     34    tags = generic.GenericRelation(TaggedItem) 
    3435 
    3536    def __str__(self): 
     
    4041    is_yucky = models.BooleanField(default=True) 
    4142     
    42     tags = models.GenericRelation(TaggedItem) 
     43    tags = generic.GenericRelation(TaggedItem) 
    4344     
    4445    def __str__(self): 
     
    6667# Objects with declared GenericRelations can be tagged directly -- the API 
    6768# mimics the many-to-many API. 
     69>>> bacon.tags.create(tag="fatty") 
     70<TaggedItem: fatty> 
     71>>> bacon.tags.create(tag="salty") 
     72<TaggedItem: salty> 
    6873>>> lion.tags.create(tag="yellow") 
    6974<TaggedItem: yellow> 
    7075>>> lion.tags.create(tag="hairy") 
    7176<TaggedItem: hairy> 
    72 >>> bacon.tags.create(tag="fatty") 
    73 <TaggedItem: fatty> 
    74 >>> bacon.tags.create(tag="salty") 
    75 <TaggedItem: salty> 
    7677 
    7778>>> lion.tags.all() 
     
    106107>>> TaggedItem.objects.filter(content_type__pk=ctype.id, object_id=quartz.id) 
    107108[<TaggedItem: clearish>] 
     109 
     110# If you delete an object with an explicit Generic relation, the related 
     111# objects are deleted when the source object is deleted. 
     112# Original list of tags: 
     113>>> [(t.tag, t.content_type, t.object_id) for t in TaggedItem.objects.all()] 
     114[('clearish', <ContentType: mineral>, 1), ('fatty', <ContentType: vegetable>, 2), ('hairy', <ContentType: animal>, 1), ('salty', <ContentType: vegetable>, 2), ('shiny', <ContentType: animal>, 2), ('yellow', <ContentType: animal>, 1)] 
     115 
     116>>> lion.delete() 
     117>>> [(t.tag, t.content_type, t.object_id) for t in TaggedItem.objects.all()] 
     118[('clearish', <ContentType: mineral>, 1), ('fatty', <ContentType: vegetable>, 2), ('salty', <ContentType: vegetable>, 2), ('shiny', <ContentType: animal>, 2)] 
     119 
     120# If Generic Relation is not explicitly defined, any related objects  
     121# remain after deletion of the source object. 
     122>>> quartz.delete() 
     123>>> [(t.tag, t.content_type, t.object_id) for t in TaggedItem.objects.all()] 
     124[('clearish', <ContentType: mineral>, 1), ('fatty', <ContentType: vegetable>, 2), ('salty', <ContentType: vegetable>, 2), ('shiny', <ContentType: animal>, 2)] 
     125 
     126# If you delete a tag, the objects using the tag are unaffected  
     127# (other than losing a tag) 
     128>>> tag = TaggedItem.objects.get(id=1) 
     129>>> tag.delete() 
     130>>> bacon.tags.all() 
     131[<TaggedItem: salty>] 
     132>>> [(t.tag, t.content_type, t.object_id) for t in TaggedItem.objects.all()] 
     133[('clearish', <ContentType: mineral>, 1), ('salty', <ContentType: vegetable>, 2), ('shiny', <ContentType: animal>, 2)] 
     134 
    108135"""} 
  • django/branches/per-object-permissions/tests/modeltests/get_or_create/models.py

    r3669 r5488  
    11""" 
    2 32. get_or_create() 
     233. get_or_create() 
    33 
    44get_or_create() does what it says: it tries to look up an object with the given 
  • django/branches/per-object-permissions/tests/modeltests/invalid_models/models.py

    r3810 r5488  
    99class FieldErrors(models.Model): 
    1010    charfield = models.CharField() 
    11     floatfield = models.FloatField() 
     11    decimalfield = models.DecimalField() 
    1212    filefield = models.FileField() 
    1313    prepopulate = models.CharField(maxlength=10, prepopulate_from='bad') 
     
    8888    selfclashm2m = models.CharField(maxlength=10) 
    8989 
    90     # Non-symmetrical M2M fields _do_ have related accessors, so  
     90    # Non-symmetrical M2M fields _do_ have related accessors, so 
    9191    # there is potential for clashes. 
    9292    selfclashm2m_set = models.ManyToManyField("SelfClashM2M", symmetrical=False) 
    93      
     93 
    9494    m2m_1 = models.ManyToManyField("SelfClashM2M", related_name='id', symmetrical=False) 
    9595    m2m_2 = models.ManyToManyField("SelfClashM2M", related_name='src_safe', symmetrical=False) 
     
    9898    m2m_4 = models.ManyToManyField('self', symmetrical=False) 
    9999 
     100class Model(models.Model): 
     101    "But it's valid to call a model Model." 
     102    year = models.PositiveIntegerField() #1960 
     103    make = models.CharField(maxlength=10) #Aston Martin 
     104    name = models.CharField(maxlength=10) #DB 4 GT 
     105 
     106class Car(models.Model): 
     107    colour = models.CharField(maxlength=5) 
     108    model = models.ForeignKey(Model) 
     109 
    100110model_errors = """invalid_models.fielderrors: "charfield": CharFields require a "maxlength" attribute. 
    101 invalid_models.fielderrors: "floatfield": FloatFields require a "decimal_places" attribute. 
    102 invalid_models.fielderrors: "floatfield": FloatFields require a "max_digits" attribute. 
     111invalid_models.fielderrors: "decimalfield": DecimalFields require a "decimal_places" attribute. 
     112invalid_models.fielderrors: "decimalfield": DecimalFields require a "max_digits" attribute. 
    103113invalid_models.fielderrors: "filefield": FileFields require an "upload_to" attribute. 
    104114invalid_models.fielderrors: "prepopulate": prepopulate_from should be a list or tuple. 
  • django/branches/per-object-permissions/tests/modeltests/lookup/models.py

    r3669 r5488  
    59590L 
    6060 
     61# count() should respect sliced query sets. 
     62>>> articles = Article.objects.all() 
     63>>> articles.count() 
     647L 
     65>>> articles[:4].count() 
     664 
     67>>> articles[1:100].count() 
     686L 
     69>>> articles[10:100].count() 
     700 
     71 
    6172# Date and date/time lookups can also be done with strings. 
    6273>>> Article.objects.filter(pub_date__exact='2005-07-27 00:00:00').count() 
     
    120131[('headline', 'Article 7'), ('id', 7)] 
    121132[('headline', 'Article 1'), ('id', 1)] 
     133 
     134 
     135# you can use values() even on extra fields 
     136>>> for d in Article.objects.extra( select={'id_plus_one' : 'id + 1'} ).values('id', 'id_plus_one'): 
     137...     i = d.items() 
     138...     i.sort() 
     139...     i 
     140[('id', 5), ('id_plus_one', 6)] 
     141[('id', 6), ('id_plus_one', 7)] 
     142[('id', 4), ('id_plus_one', 5)] 
     143[('id', 2), ('id_plus_one', 3)] 
     144[('id', 3), ('id_plus_one', 4)] 
     145[('id', 7), ('id_plus_one', 8)] 
     146[('id', 1), ('id_plus_one', 2)] 
     147 
     148# however, an exception FieldDoesNotExist will still be thrown  
     149# if you try to access non-existent field (field that is neither on the model nor extra) 
     150>>> Article.objects.extra( select={'id_plus_one' : 'id + 1'} ).values('id', 'id_plus_two') 
     151Traceback (most recent call last): 
     152    ... 
     153FieldDoesNotExist: Article has no field named 'id_plus_two' 
    122154 
    123155# if you don't specify which fields, all are returned 
     
    192224[<Article: Article with \ backslash>] 
    193225 
     226# none() returns an EmptyQuerySet that behaves like any other QuerySet object 
     227>>> Article.objects.none() 
     228[] 
     229>>> Article.objects.none().filter(headline__startswith='Article') 
     230[] 
     231>>> Article.objects.none().count() 
     2320 
     233>>> [article for article in Article.objects.none().iterator()] 
     234[] 
     235 
     236# using __in with an empty list should return an empty query set 
     237>>> Article.objects.filter(id__in=[]) 
     238[] 
     239 
     240>>> Article.objects.exclude(id__in=[]) 
     241[<Article: Article with \ backslash>, <Article: Article% with percent sign>, <Article: Article_ with underscore>, <Article: Article 5>, <Article: Article 6>, <Article: Article 4>, <Article: Article 2>, <Article: Article 3>, <Article: Article 7>, <Article: Article 1>] 
     242 
     243# Programming errors are pointed out with nice error messages 
     244>>> Article.objects.filter(pub_date_year='2005').count() 
     245Traceback (most recent call last): 
     246    ... 
     247TypeError: Cannot resolve keyword 'pub_date_year' into field. Choices are: id, headline, pub_date 
     248 
     249>>> Article.objects.filter(headline__starts='Article') 
     250Traceback (most recent call last): 
     251    ... 
     252TypeError: Cannot resolve keyword 'headline__starts' into field. Choices are: id, headline, pub_date 
     253 
    194254"""} 
  • django/branches/per-object-permissions/tests/modeltests/m2m_and_m2o/models.py

    r3669 r5488  
    11""" 
    2 28. Many-to-many and many-to-one relationships to the same table 
     229. Many-to-many and many-to-one relationships to the same table 
    33 
    44Make sure to set ``related_name`` if you use relationships to the same table. 
  • django/branches/per-object-permissions/tests/modeltests/m2m_recursive/models.py

    r3669 r5488  
    11""" 
    2 27. Many-to-many relationships between the same two tables 
     228. Many-to-many relationships between the same two tables 
    33 
    44In this example, A Person can have many friends, who are also people. Friendship is a 
  • django/branches/per-object-permissions/tests/modeltests/manipulators/models.py

    r3669 r5488  
    11""" 
    2 26. Default manipulators 
     227. Default manipulators 
    33 
    44Each model gets an AddManipulator and ChangeManipulator by default. 
  • django/branches/per-object-permissions/tests/modeltests/many_to_many/models.py

    r4242 r5488  
    204204[<Article: Oxygen-free diet works wonders>] 
    205205 
    206 # Recreate the article and Publication we just deleted. 
     206# Relation sets can also be set using primary key values 
     207>>> p2.article_set = [a4.id, a5.id] 
     208>>> p2.article_set.all() 
     209[<Article: NASA finds intelligent life on Earth>, <Article: Oxygen-free diet works wonders>] 
     210>>> a4.publications.all() 
     211[<Publication: Science News>] 
     212>>> a4.publications = [p3.id] 
     213>>> p2.article_set.all() 
     214[<Article: Oxygen-free diet works wonders>] 
     215>>> a4.publications.all() 
     216[<Publication: Science Weekly>] 
     217 
     218# Recreate the article and Publication we have deleted. 
    207219>>> p1 = Publication(id=None, title='The Python Journal') 
    208220>>> p1.save() 
  • django/branches/per-object-permissions/tests/modeltests/many_to_one/models.py

    r3669 r5488  
    175175Traceback (most recent call last): 
    176176    ... 
    177 TypeError: Cannot resolve keyword 'reporter_id' into field 
     177TypeError: Cannot resolve keyword 'reporter_id' into field. Choices are: id, headline, pub_date, reporter 
    178178 
    179179# You need to specify a comparison clause 
     
    181181Traceback (most recent call last): 
    182182    ... 
    183 TypeError: Cannot resolve keyword 'reporter_id' into field 
     183TypeError: Cannot resolve keyword 'reporter_id' into field. Choices are: id, headline, pub_date, reporter 
    184184 
    185185# You can also instantiate an Article by passing 
  • django/branches/per-object-permissions/tests/modeltests/model_forms/models.py

    r4242 r5488  
    11""" 
    2 34. Generating HTML forms from models 
    3  
    4 Django provides shortcuts for creating Form objects from a model class. 
     236. Generating HTML forms from models 
     3 
     4Django provides shortcuts for creating Form objects from a model class and a 
     5model instance. 
    56 
    67The function django.newforms.form_for_model() takes a model class and returns 
    78a Form that is tied to the model. This Form works just like any other Form, 
    8 with one additional method: create(). The create() method creates an instance 
     9with one additional method: save(). The save() method creates an instance 
    910of the model and returns that newly created instance. It saves the instance to 
    10 the database if create(save=True), which is default. If you pass 
    11 create(save=False), then you'll get the object without saving it. 
     11the database if save(commit=True), which is default. If you pass 
     12commit=False, then you'll get the object without committing the changes to the 
     13database. 
     14 
     15The function django.newforms.form_for_instance() takes a model instance and 
     16returns a Form that is tied to the instance. This form works just like any 
     17other Form, with one additional method: save(). The save() 
     18method updates the model instance. It also takes a commit=True parameter. 
     19 
     20The function django.newforms.save_instance() takes a bound form instance and a 
     21model instance and saves the form's cleaned_data into the instance. It also takes 
     22a commit=True parameter. 
    1223""" 
    1324 
    1425from django.db import models 
     26 
     27ARTICLE_STATUS = ( 
     28    (1, 'Draft'), 
     29    (2, 'Pending'), 
     30    (3, 'Live'), 
     31) 
    1532 
    1633class Category(models.Model): 
     
    2138        return self.name 
    2239 
     40class Writer(models.Model): 
     41    name = models.CharField(maxlength=50, help_text='Use both first and last names.') 
     42 
     43    def __str__(self): 
     44        return self.name 
     45 
    2346class Article(models.Model): 
    2447    headline = models.CharField(maxlength=50) 
    25     pub_date = models.DateTimeField() 
    26     categories = models.ManyToManyField(Category) 
     48    pub_date = models.DateField() 
     49    created = models.DateField(editable=False) 
     50    writer = models.ForeignKey(Writer) 
     51    article = models.TextField() 
     52    categories = models.ManyToManyField(Category, blank=True) 
     53    status = models.IntegerField(choices=ARTICLE_STATUS, blank=True, null=True) 
     54 
     55    def save(self): 
     56        import datetime 
     57        if not self.id: 
     58            self.created = datetime.date.today() 
     59        return super(Article, self).save() 
    2760 
    2861    def __str__(self): 
    2962        return self.headline 
    3063 
     64class PhoneNumber(models.Model): 
     65    phone = models.PhoneNumberField() 
     66    description = models.CharField(maxlength=20) 
     67 
     68    def __str__(self): 
     69        return self.phone 
     70 
    3171__test__ = {'API_TESTS': """ 
    32 >>> from django.newforms import form_for_model, BaseForm 
     72>>> from django.newforms import form_for_model, form_for_instance, save_instance, BaseForm, Form, CharField 
     73>>> import datetime 
    3374 
    3475>>> Category.objects.all() 
     
    5293 
    5394>>> f = CategoryForm({'name': 'Entertainment', 'url': 'entertainment'}) 
    54 >>> f.errors 
    55 {} 
    56 >>> f.clean_data 
     95>>> f.is_valid() 
     96True 
     97>>> f.cleaned_data 
    5798{'url': u'entertainment', 'name': u'Entertainment'} 
    58 >>> obj = f.create() 
     99>>> obj = f.save() 
    59100>>> obj 
    60101<Category: Entertainment> 
     
    63104 
    64105>>> f = CategoryForm({'name': "It's a test", 'url': 'test'}) 
    65 >>> f.errors 
    66 {} 
    67 >>> f.clean_data 
     106>>> f.is_valid() 
     107True 
     108>>> f.cleaned_data 
    68109{'url': u'test', 'name': u"It's a test"} 
    69 >>> obj = f.create() 
     110>>> obj = f.save() 
    70111>>> obj 
    71112<Category: It's a test> 
     
    73114[<Category: Entertainment>, <Category: It's a test>] 
    74115 
     116If you call save() with commit=False, then it will return an object that 
     117hasn't yet been saved to the database. In this case, it's up to you to call 
     118save() on the resulting model instance. 
    75119>>> f = CategoryForm({'name': 'Third test', 'url': 'third'}) 
    76 >>> f.errors 
    77 {} 
    78 >>> f.clean_data 
     120>>> f.is_valid() 
     121True 
     122>>> f.cleaned_data 
    79123{'url': u'third', 'name': u'Third test'} 
    80 >>> obj = f.create(save=False) 
     124>>> obj = f.save(commit=False) 
    81125>>> obj 
    82126<Category: Third test> 
     
    87131[<Category: Entertainment>, <Category: It's a test>, <Category: Third test>] 
    88132 
     133If you call save() with invalid data, you'll get a ValueError. 
    89134>>> f = CategoryForm({'name': '', 'url': 'foo'}) 
    90135>>> f.errors 
    91136{'name': [u'This field is required.']} 
    92 >>> f.clean_data 
    93 >>> f.create() 
     137>>> f.cleaned_data 
     138Traceback (most recent call last): 
     139... 
     140AttributeError: 'CategoryForm' object has no attribute 'cleaned_data' 
     141>>> f.save() 
    94142Traceback (most recent call last): 
    95143... 
    96144ValueError: The Category could not be created because the data didn't validate. 
    97  
    98145>>> f = CategoryForm({'name': '', 'url': 'foo'}) 
    99 >>> f.create() 
     146>>> f.save() 
    100147Traceback (most recent call last): 
    101148... 
    102149ValueError: The Category could not be created because the data didn't validate. 
     150 
     151Create a couple of Writers. 
     152>>> w = Writer(name='Mike Royko') 
     153>>> w.save() 
     154>>> w = Writer(name='Bob Woodward') 
     155>>> w.save() 
     156 
     157ManyToManyFields are represented by a MultipleChoiceField, ForeignKeys and any 
     158fields with the 'choices' attribute are represented by a ChoiceField. 
     159>>> ArticleForm = form_for_model(Article) 
     160>>> f = ArticleForm(auto_id=False) 
     161>>> print f 
     162<tr><th>Headline:</th><td><input type="text" name="headline" maxlength="50" /></td></tr> 
     163<tr><th>Pub date:</th><td><input type="text" name="pub_date" /></td></tr> 
     164<tr><th>Writer:</th><td><select name="writer"> 
     165<option value="" selected="selected">---------</option> 
     166<option value="1">Mike Royko</option> 
     167<option value="2">Bob Woodward</option> 
     168</select></td></tr> 
     169<tr><th>Article:</th><td><textarea rows="10" cols="40" name="article"></textarea></td></tr> 
     170<tr><th>Status:</th><td><select name="status"> 
     171<option value="" selected="selected">---------</option> 
     172<option value="1">Draft</option> 
     173<option value="2">Pending</option> 
     174<option value="3">Live</option> 
     175</select></td></tr> 
     176<tr><th>Categories:</th><td><select multiple="multiple" name="categories"> 
     177<option value="1">Entertainment</option> 
     178<option value="2">It&#39;s a test</option> 
     179<option value="3">Third test</option> 
     180</select><br /> Hold down "Control", or "Command" on a Mac, to select more than one.</td></tr> 
     181 
     182You can restrict a form to a subset of the complete list of fields 
     183by providing a 'fields' argument. If you try to save a 
     184model created with such a form, you need to ensure that the fields 
     185that are _not_ on the form have default values, or are allowed to have 
     186a value of None. If a field isn't specified on a form, the object created 
     187from the form can't provide a value for that field! 
     188>>> PartialArticleForm = form_for_model(Article, fields=('headline','pub_date')) 
     189>>> f = PartialArticleForm(auto_id=False) 
     190>>> print f 
     191<tr><th>Headline:</th><td><input type="text" name="headline" maxlength="50" /></td></tr> 
     192<tr><th>Pub date:</th><td><input type="text" name="pub_date" /></td></tr> 
    103193 
    104194You can pass a custom Form class to form_for_model. Make sure it's a 
     
    111201>>> f.say_hello() 
    112202hello 
     203 
     204Use form_for_instance to create a Form from a model instance. The difference 
     205between this Form and one created via form_for_model is that the object's 
     206current values are inserted as 'initial' data in each Field. 
     207>>> w = Writer.objects.get(name='Mike Royko') 
     208>>> RoykoForm = form_for_instance(w) 
     209>>> f = RoykoForm(auto_id=False) 
     210>>> print f 
     211<tr><th>Name:</th><td><input type="text" name="name" value="Mike Royko" maxlength="50" /><br />Use both first and last names.</td></tr> 
     212 
     213>>> art = Article(headline='Test article', pub_date=datetime.date(1988, 1, 4), writer=w, article='Hello.') 
     214>>> art.save() 
     215>>> art.id 
     2161 
     217>>> TestArticleForm = form_for_instance(art) 
     218>>> f = TestArticleForm(auto_id=False) 
     219>>> print f.as_ul() 
     220<li>Headline: <input type="text" name="headline" value="Test article" maxlength="50" /></li> 
     221<li>Pub date: <input type="text" name="pub_date" value="1988-01-04" /></li> 
     222<li>Writer: <select name="writer"> 
     223<option value="">---------</option> 
     224<option value="1" selected="selected">Mike Royko</option> 
     225<option value="2">Bob Woodward</option> 
     226</select></li> 
     227<li>Article: <textarea rows="10" cols="40" name="article">Hello.</textarea></li> 
     228<li>Status: <select name="status"> 
     229<option value="" selected="selected">---------</option> 
     230<option value="1">Draft</option> 
     231<option value="2">Pending</option> 
     232<option value="3">Live</option> 
     233</select></li> 
     234<li>Categories: <select multiple="multiple" name="categories"> 
     235<option value="1">Entertainment</option> 
     236<option value="2">It&#39;s a test</option> 
     237<option value="3">Third test</option> 
     238</select>  Hold down "Control", or "Command" on a Mac, to select more than one.</li> 
     239>>> f = TestArticleForm({'headline': u'Test headline', 'pub_date': u'1984-02-06', 'writer': u'1', 'article': 'Hello.'}) 
     240>>> f.is_valid() 
     241True 
     242>>> test_art = f.save() 
     243>>> test_art.id 
     2441 
     245>>> test_art = Article.objects.get(id=1) 
     246>>> test_art.headline 
     247'Test headline' 
     248 
     249You can create a form over a subset of the available fields  
     250by specifying a 'fields' argument to form_for_instance.  
     251>>> PartialArticleForm = form_for_instance(art, fields=('headline','pub_date')) 
     252>>> f = PartialArticleForm({'headline': u'New headline', 'pub_date': u'1988-01-04'}, auto_id=False) 
     253>>> print f.as_ul() 
     254<li>Headline: <input type="text" name="headline" value="New headline" maxlength="50" /></li> 
     255<li>Pub date: <input type="text" name="pub_date" value="1988-01-04" /></li> 
     256>>> f.is_valid() 
     257True 
     258>>> new_art = f.save() 
     259>>> new_art.id 
     2601 
     261>>> new_art = Article.objects.get(id=1) 
     262>>> new_art.headline 
     263'New headline' 
     264 
     265Add some categories and test the many-to-many form output. 
     266>>> new_art.categories.all() 
     267[] 
     268>>> new_art.categories.add(Category.objects.get(name='Entertainment')) 
     269>>> new_art.categories.all() 
     270[<Category: Entertainment>] 
     271>>> TestArticleForm = form_for_instance(new_art) 
     272>>> f = TestArticleForm(auto_id=False) 
     273>>> print f.as_ul() 
     274<li>Headline: <input type="text" name="headline" value="New headline" maxlength="50" /></li> 
     275<li>Pub date: <input type="text" name="pub_date" value="1988-01-04" /></li> 
     276<li>Writer: <select name="writer"> 
     277<option value="">---------</option> 
     278<option value="1" selected="selected">Mike Royko</option> 
     279<option value="2">Bob Woodward</option> 
     280</select></li> 
     281<li>Article: <textarea rows="10" cols="40" name="article">Hello.</textarea></li> 
     282<li>Status: <select name="status"> 
     283<option value="" selected="selected">---------</option> 
     284<option value="1">Draft</option> 
     285<option value="2">Pending</option> 
     286<option value="3">Live</option> 
     287</select></li> 
     288<li>Categories: <select multiple="multiple" name="categories"> 
     289<option value="1" selected="selected">Entertainment</option> 
     290<option value="2">It&#39;s a test</option> 
     291<option value="3">Third test</option> 
     292</select>  Hold down "Control", or "Command" on a Mac, to select more than one.</li> 
     293 
     294>>> f = TestArticleForm({'headline': u'New headline', 'pub_date': u'1988-01-04', 
     295...     'writer': u'1', 'article': u'Hello.', 'categories': [u'1', u'2']}) 
     296>>> new_art = f.save() 
     297>>> new_art.id 
     2981 
     299>>> new_art = Article.objects.get(id=1) 
     300>>> new_art.categories.all() 
     301[<Category: Entertainment>, <Category: It's a test>] 
     302 
     303Now, submit form data with no categories. This deletes the existing categories. 
     304>>> f = TestArticleForm({'headline': u'New headline', 'pub_date': u'1988-01-04', 
     305...     'writer': u'1', 'article': u'Hello.'}) 
     306>>> new_art = f.save() 
     307>>> new_art.id 
     3081 
     309>>> new_art = Article.objects.get(id=1) 
     310>>> new_art.categories.all() 
     311[] 
     312 
     313Create a new article, with categories, via the form. 
     314>>> ArticleForm = form_for_model(Article) 
     315>>> f = ArticleForm({'headline': u'The walrus was Paul', 'pub_date': u'1967-11-01', 
     316...     'writer': u'1', 'article': u'Test.', 'categories': [u'1', u'2']}) 
     317>>> new_art = f.save() 
     318>>> new_art.id 
     3192 
     320>>> new_art = Article.objects.get(id=2) 
     321>>> new_art.categories.all() 
     322[<Category: Entertainment>, <Category: It's a test>] 
     323 
     324Create a new article, with no categories, via the form. 
     325>>> ArticleForm = form_for_model(Article) 
     326>>> f = ArticleForm({'headline': u'The walrus was Paul', 'pub_date': u'1967-11-01', 
     327...     'writer': u'1', 'article': u'Test.'}) 
     328>>> new_art = f.save() 
     329>>> new_art.id 
     3303 
     331>>> new_art = Article.objects.get(id=3) 
     332>>> new_art.categories.all() 
     333[] 
     334 
     335Here, we define a custom Form. Because it happens to have the same fields as 
     336the Category model, we can use save_instance() to apply its changes to an 
     337existing Category instance. 
     338>>> class ShortCategory(Form): 
     339...     name = CharField(max_length=5) 
     340...     url = CharField(max_length=3) 
     341>>> cat = Category.objects.get(name='Third test') 
     342>>> cat 
     343<Category: Third test> 
     344>>> cat.id 
     3453 
     346>>> sc = ShortCategory({'name': 'Third', 'url': '3rd'}) 
     347>>> save_instance(sc, cat) 
     348<Category: Third> 
     349>>> Category.objects.get(id=3) 
     350<Category: Third> 
     351 
     352Here, we demonstrate that choices for a ForeignKey ChoiceField are determined 
     353at runtime, based on the data in the database when the form is displayed, not 
     354the data in the database when the form is instantiated. 
     355>>> ArticleForm = form_for_model(Article) 
     356>>> f = ArticleForm(auto_id=False) 
     357>>> print f.as_ul()