Code

Ticket #3557: slugfield.2.patch

File slugfield.2.patch, 9.9 KB (added by Russell Cloran <russell@…>, 7 years ago)

Patch to fix SlugField in newforms. Incl new tests.

  • django/db/models/fields/__init__.py

     
    762762    def get_manipulator_field_objs(self): 
    763763        return [oldforms.PositiveSmallIntegerField] 
    764764 
    765 class SlugField(Field): 
     765class SlugField(CharField): 
    766766    def __init__(self, *args, **kwargs): 
    767767        kwargs['maxlength'] = kwargs.get('maxlength', 50) 
    768768        kwargs.setdefault('validator_list', []).append(validators.isSlug) 
    769769        # Set db_index=True unless it's been set manually. 
    770770        if not kwargs.has_key('db_index'): 
    771771            kwargs['db_index'] = True 
    772         Field.__init__(self, *args, **kwargs) 
     772        CharField.__init__(self, *args, **kwargs) 
    773773 
    774     def get_manipulator_field_objs(self): 
    775         return [oldforms.TextField] 
    776  
    777774class SmallIntegerField(IntegerField): 
    778775    def get_manipulator_field_objs(self): 
    779776        return [oldforms.SmallIntegerField] 
  • tests/modeltests/model_forms/models.py

     
    2525from django.db import models 
    2626 
    2727class Category(models.Model): 
     28    slug = models.SlugField(maxlength=20) 
    2829    name = models.CharField(maxlength=20) 
    2930    url = models.CharField('The URL', maxlength=40) 
    3031 
     
    3839        return self.name 
    3940 
    4041class Article(models.Model): 
     42    slug = models.SlugField() 
    4143    headline = models.CharField(maxlength=50) 
    4244    pub_date = models.DateField() 
    4345    created = models.DateField(editable=False) 
     
    7173>>> CategoryForm = form_for_model(Category) 
    7274>>> f = CategoryForm() 
    7375>>> print f 
     76<tr><th><label for="id_slug">Slug:</label></th><td><input id="id_slug" type="text" name="slug" maxlength="20" /></td></tr> 
    7477<tr><th><label for="id_name">Name:</label></th><td><input id="id_name" type="text" name="name" maxlength="20" /></td></tr> 
    7578<tr><th><label for="id_url">The URL:</label></th><td><input id="id_url" type="text" name="url" maxlength="40" /></td></tr> 
    7679>>> print f.as_ul() 
     80<li><label for="id_slug">Slug:</label> <input id="id_slug" type="text" name="slug" maxlength="20" /></li> 
    7781<li><label for="id_name">Name:</label> <input id="id_name" type="text" name="name" maxlength="20" /></li> 
    7882<li><label for="id_url">The URL:</label> <input id="id_url" type="text" name="url" maxlength="40" /></li> 
    7983>>> print f['name'] 
     
    8185 
    8286>>> f = CategoryForm(auto_id=False) 
    8387>>> print f.as_ul() 
     88<li>Slug: <input type="text" name="slug" maxlength="20" /></li> 
    8489<li>Name: <input type="text" name="name" maxlength="20" /></li> 
    8590<li>The URL: <input type="text" name="url" maxlength="40" /></li> 
    8691 
    87 >>> f = CategoryForm({'name': 'Entertainment', 'url': 'entertainment'}) 
     92>>> f = CategoryForm({'slug': 'entertainment', 'name': 'Entertainment', 'url': 'entertainment'}) 
    8893>>> f.is_valid() 
    8994True 
    9095>>> f.clean_data 
    91 {'url': u'entertainment', 'name': u'Entertainment'} 
     96{'url': u'entertainment', 'slug': u'entertainment', 'name': u'Entertainment'} 
    9297>>> obj = f.save() 
    9398>>> obj 
    9499<Category: Entertainment> 
    95100>>> Category.objects.all() 
    96101[<Category: Entertainment>] 
    97102 
    98 >>> f = CategoryForm({'name': "It's a test", 'url': 'test'}) 
     103>>> f = CategoryForm({'slug': 'its-test', 'name': "It's a test", 'url': 'test'}) 
    99104>>> f.is_valid() 
    100105True 
    101106>>> f.clean_data 
    102 {'url': u'test', 'name': u"It's a test"} 
     107{'url': u'test', 'slug': u'its-test', 'name': u"It's a test"} 
    103108>>> obj = f.save() 
    104109>>> obj 
    105110<Category: It's a test> 
     
    109114If you call save() with commit=False, then it will return an object that 
    110115hasn't yet been saved to the database. In this case, it's up to you to call 
    111116save() on the resulting model instance. 
    112 >>> f = CategoryForm({'name': 'Third test', 'url': 'third'}) 
     117>>> f = CategoryForm({'slug': 'third-test', 'name': 'Third test', 'url': 'third'}) 
    113118>>> f.is_valid() 
    114119True 
    115120>>> f.clean_data 
    116 {'url': u'third', 'name': u'Third test'} 
     121{'url': u'third', 'slug': u'third-test', 'name': u'Third test'} 
    117122>>> obj = f.save(commit=False) 
    118123>>> obj 
    119124<Category: Third test> 
     
    124129[<Category: Entertainment>, <Category: It's a test>, <Category: Third test>] 
    125130 
    126131If you call save() with invalid data, you'll get a ValueError. 
    127 >>> f = CategoryForm({'name': '', 'url': 'foo'}) 
     132>>> f = CategoryForm({'slug': '', 'name': '', 'url': 'foo'}) 
    128133>>> f.errors 
    129 {'name': [u'This field is required.']} 
     134{'slug': [u'This field is required.'], 'name': [u'This field is required.']} 
    130135>>> f.clean_data 
    131136Traceback (most recent call last): 
    132137... 
     
    135140Traceback (most recent call last): 
    136141... 
    137142ValueError: The Category could not be created because the data didn't validate. 
    138 >>> f = CategoryForm({'name': '', 'url': 'foo'}) 
     143>>> f = CategoryForm({'slug': '', 'name': '', 'url': 'foo'}) 
    139144>>> f.save() 
    140145Traceback (most recent call last): 
    141146... 
     
    152157>>> ArticleForm = form_for_model(Article) 
    153158>>> f = ArticleForm(auto_id=False) 
    154159>>> print f 
     160<tr><th>Slug:</th><td><input type="text" name="slug" maxlength="50" /></td></tr> 
    155161<tr><th>Headline:</th><td><input type="text" name="headline" maxlength="50" /></td></tr> 
    156162<tr><th>Pub date:</th><td><input type="text" name="pub_date" /></td></tr> 
    157163<tr><th>Writer:</th><td><select name="writer"> 
     
    185191>>> print f 
    186192<tr><th>Name:</th><td><input type="text" name="name" value="Mike Royko" maxlength="50" /><br />Use both first and last names.</td></tr> 
    187193 
    188 >>> art = Article(headline='Test article', pub_date=datetime.date(1988, 1, 4), writer=w, article='Hello.') 
     194>>> art = Article(slug='test-article', headline='Test article', pub_date=datetime.date(1988, 1, 4), writer=w, article='Hello.') 
    189195>>> art.save() 
    190196>>> art.id 
    1911971 
    192198>>> TestArticleForm = form_for_instance(art) 
    193199>>> f = TestArticleForm(auto_id=False) 
    194200>>> print f.as_ul() 
     201<li>Slug: <input type="text" name="slug" value="test-article" maxlength="50" /></li> 
    195202<li>Headline: <input type="text" name="headline" value="Test article" maxlength="50" /></li> 
    196203<li>Pub date: <input type="text" name="pub_date" value="1988-01-04" /></li> 
    197204<li>Writer: <select name="writer"> 
     
    205212<option value="2">It&#39;s a test</option> 
    206213<option value="3">Third test</option> 
    207214</select>  Hold down "Control", or "Command" on a Mac, to select more than one.</li> 
    208 >>> f = TestArticleForm({'headline': u'New headline', 'pub_date': u'1988-01-04', 'writer': u'1', 'article': 'Hello.'}) 
     215>>> f = TestArticleForm({'slug': 'new-headline', 'headline': u'New headline', 'pub_date': u'1988-01-04', 'writer': u'1', 'article': 'Hello.'}) 
    209216>>> f.is_valid() 
    210217True 
    211218>>> new_art = f.save() 
     
    224231>>> TestArticleForm = form_for_instance(new_art) 
    225232>>> f = TestArticleForm(auto_id=False) 
    226233>>> print f.as_ul() 
     234<li>Slug: <input type="text" name="slug" value="new-headline" maxlength="50" /></li> 
    227235<li>Headline: <input type="text" name="headline" value="New headline" maxlength="50" /></li> 
    228236<li>Pub date: <input type="text" name="pub_date" value="1988-01-04" /></li> 
    229237<li>Writer: <select name="writer"> 
     
    238246<option value="3">Third test</option> 
    239247</select>  Hold down "Control", or "Command" on a Mac, to select more than one.</li> 
    240248 
    241 >>> f = TestArticleForm({'headline': u'New headline', 'pub_date': u'1988-01-04', 
     249>>> f = TestArticleForm({'slug': u'new-headline', 'headline': u'New headline', 'pub_date': u'1988-01-04', 
    242250...     'writer': u'1', 'article': u'Hello.', 'categories': [u'1', u'2']}) 
    243251>>> new_art = f.save() 
    244252>>> new_art.id 
     
    248256[<Category: Entertainment>, <Category: It's a test>] 
    249257 
    250258Now, submit form data with no categories. This deletes the existing categories. 
    251 >>> f = TestArticleForm({'headline': u'New headline', 'pub_date': u'1988-01-04', 
     259>>> f = TestArticleForm({'slug': u'new-headline', 'headline': u'New headline', 'pub_date': u'1988-01-04', 
    252260...     'writer': u'1', 'article': u'Hello.'}) 
    253261>>> new_art = f.save() 
    254262>>> new_art.id 
     
    259267 
    260268Create a new article, with categories, via the form. 
    261269>>> ArticleForm = form_for_model(Article) 
    262 >>> f = ArticleForm({'headline': u'The walrus was Paul', 'pub_date': u'1967-11-01', 
     270>>> f = ArticleForm({'slug': u'new-headline', 'headline': u'The walrus was Paul', 'pub_date': u'1967-11-01', 
    263271...     'writer': u'1', 'article': u'Test.', 'categories': [u'1', u'2']}) 
    264272>>> new_art = f.save() 
    265273>>> new_art.id 
     
    270278 
    271279Create a new article, with no categories, via the form. 
    272280>>> ArticleForm = form_for_model(Article) 
    273 >>> f = ArticleForm({'headline': u'The walrus was Paul', 'pub_date': u'1967-11-01', 
     281>>> f = ArticleForm({'slug': u'walrus-was-paul', 'headline': u'The walrus was Paul', 'pub_date': u'1967-11-01', 
    274282...     'writer': u'1', 'article': u'Test.'}) 
    275283>>> new_art = f.save() 
    276284>>> new_art.id 
     
    283291the Category model, we can use save_instance() to apply its changes to an 
    284292existing Category instance. 
    285293>>> class ShortCategory(Form): 
     294...     slug = CharField(max_length=5) 
    286295...     name = CharField(max_length=5) 
    287296...     url = CharField(max_length=3) 
    288297>>> cat = Category.objects.get(name='Third test') 
     
    290299<Category: Third test> 
    291300>>> cat.id 
    2923013 
    293 >>> sc = ShortCategory({'name': 'Third', 'url': '3rd'}) 
     302>>> sc = ShortCategory({'slug': 'third', 'name': 'Third', 'url': '3rd'}) 
    294303>>> save_instance(sc, cat) 
    295304<Category: Third> 
    296305>>> Category.objects.get(id=3) 
     
    302311>>> ArticleForm = form_for_model(Article) 
    303312>>> f = ArticleForm(auto_id=False) 
    304313>>> print f.as_ul() 
     314<li>Slug: <input type="text" name="slug" maxlength="50" /></li> 
    305315<li>Headline: <input type="text" name="headline" maxlength="50" /></li> 
    306316<li>Pub date: <input type="text" name="pub_date" /></li> 
    307317<li>Writer: <select name="writer"> 
     
    320330>>> Writer.objects.create(name='Carl Bernstein') 
    321331<Writer: Carl Bernstein> 
    322332>>> print f.as_ul() 
     333<li>Slug: <input type="text" name="slug" maxlength="50" /></li> 
    323334<li>Headline: <input type="text" name="headline" maxlength="50" /></li> 
    324335<li>Pub date: <input type="text" name="pub_date" /></li> 
    325336<li>Writer: <select name="writer">