Django

Code

Show
Ignore:
Timestamp:
06/17/07 17:18:54 (1 year 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.clea