Ticket #13165: patch_13165_20110923.diff

File patch_13165_20110923.diff, 28.0 KB (added by Stefan Wehrmeyer, 8 years ago)

Latest Patch ported to trunk

  • AUTHORS

    diff --git a/AUTHORS b/AUTHORS
    index 6faa171..48433b6 100644
    a b answer newbie questions, and generally made Django that much better: 
    357357    michael.mcewan@gmail.com
    358358    Paul McLanahan <paul@mclanahan.net>
    359359    Tobias McNulty <http://www.caktusgroup.com/blog>
     360    Simon Meers <http://simonmeers.com/>
    360361    Zain Memon
    361362    Christian Metts
    362363    michal@plovarna.cz
  • django/contrib/admin/helpers.py

    diff --git a/django/contrib/admin/helpers.py b/django/contrib/admin/helpers.py
    index 04a3492..0af2375 100644
    a b  
    11from django import forms
    22from django.contrib.admin.util import (flatten_fieldsets, lookup_field,
    3     display_for_field, label_for_field, help_text_for_field)
     3    display_for_field, label_for_field, help_text_for_field,
     4    get_related_object, get_changelink_url)
    45from django.contrib.admin.templatetags.admin_static import static
    56from django.contrib.contenttypes.models import ContentType
    67from django.core.exceptions import ObjectDoesNotExist
    class AdminReadonlyField(object): 
    189190                    result_repr = display_for_field(value, f)
    190191        return conditional_escape(result_repr)
    191192
     193    def change_url(self):
     194        """ Return admin change URL for field if applicable. """
     195        field, original, model_admin = \
     196            self.field['field'], self.form.instance, self.model_admin
     197        try:
     198            f, attr, value = lookup_field(field, original, model_admin)
     199        except (AttributeError, ValueError, ObjectDoesNotExist):
     200            return None
     201        return get_changelink_url(value, self.model_admin.admin_site)
     202
     203
    192204class InlineAdminFormSet(object):
    193205    """
    194206    A wrapper around an inline formset for use in the admin system.
    class InlineAdminForm(AdminForm): 
    254266        if original is not None:
    255267            self.original_content_type_id = ContentType.objects.get_for_model(original).pk
    256268        self.show_url = original and hasattr(original, 'get_absolute_url')
     269        if original is not None and model_admin is not None:
     270            self.admin_url = get_changelink_url(original, model_admin.admin_site)
     271        else:
     272            self.admin_url = None
    257273        super(InlineAdminForm, self).__init__(form, fieldsets, prepopulated_fields,
    258274            readonly_fields, model_admin)
    259275
  • django/contrib/admin/templates/admin/edit_inline/stacked.html

    diff --git a/django/contrib/admin/templates/admin/edit_inline/stacked.html b/django/contrib/admin/templates/admin/edit_inline/stacked.html
    index 476e261..cf6723b 100644
    a b  
    66
    77{% for inline_admin_form in inline_admin_formset %}<div class="inline-related{% if forloop.last %} empty-form last-related{% endif %}" id="{{ inline_admin_formset.formset.prefix }}-{% if not forloop.last %}{{ forloop.counter0 }}{% else %}empty{% endif %}">
    88  <h3><b>{{ inline_admin_formset.opts.verbose_name|title }}:</b>&nbsp;<span class="inline_label">{% if inline_admin_form.original %}{{ inline_admin_form.original }}{% else %}#{{ forloop.counter }}{% endif %}</span>
     9    {% if inline_admin_form.admin_url %}<a href="{{ inline_admin_form.admin_url }}" class="inline-changelink changelink">{% trans "edit separately" %}</a>&nbsp;&nbsp;{% endif %}
    910    {% if inline_admin_form.show_url %}<a href="../../../r/{{ inline_admin_form.original_content_type_id }}/{{ inline_admin_form.original.id }}/">{% trans "View on site" %}</a>{% endif %}
    1011    {% if inline_admin_formset.formset.can_delete and inline_admin_form.original %}<span class="delete">{{ inline_admin_form.deletion_field.field }} {{ inline_admin_form.deletion_field.label_tag }}</span>{% endif %}
    1112  </h3>
  • django/contrib/admin/templates/admin/edit_inline/tabular.html

    diff --git a/django/contrib/admin/templates/admin/edit_inline/tabular.html b/django/contrib/admin/templates/admin/edit_inline/tabular.html
    index 71b097e..6741749 100644
    a b  
    2727        <td class="original">
    2828          {% if inline_admin_form.original or inline_admin_form.show_url %}<p>
    2929          {% if inline_admin_form.original %} {{ inline_admin_form.original }}{% endif %}
     30          {% if inline_admin_form.admin_url %}<a href="{{ inline_admin_form.admin_url }}" class="inline-changelink changelink">{% trans "edit separately" %}</a>&nbsp;&nbsp;{% endif %}
     31
    3032          {% if inline_admin_form.show_url %}<a href="../../../r/{{ inline_admin_form.original_content_type_id }}/{{ inline_admin_form.original.id }}/">{% trans "View on site" %}</a>{% endif %}
    3133            </p>{% endif %}
    3234          {% if inline_admin_form.has_auto_field %}{{ inline_admin_form.pk_field.field }}{% endif %}
     
    4648            {% for field in line %}
    4749              <td class="{{ field.field.name }}">
    4850              {% if field.is_readonly %}
    49                   <p>{{ field.contents }}</p>
     51                <p>{{ field.contents }}{% if field.change_url %} <a href="{{ field.change_url }}" class="readonly-changelink changelink">{% trans "edit" %}</a>{% endif %}</p>
    5052              {% else %}
    5153                  {{ field.field.errors.as_ul }}
    5254                  {{ field.field }}
  • django/contrib/admin/templates/admin/includes/fieldset.html

    diff --git a/django/contrib/admin/templates/admin/includes/fieldset.html b/django/contrib/admin/templates/admin/includes/fieldset.html
    index 6363aee..8720999 100644
    a b  
    1414                    {% else %}
    1515                        {{ field.label_tag }}
    1616                        {% if field.is_readonly %}
    17                             <p>{{ field.contents }}</p>
     17                            <p>{{ field.contents }}{% if field.change_url %} <a href="{{ field.change_url }}" class="readonly-changelink changelink">Edit</a>{% endif %}</p>
    1818                        {% else %}
    1919                            {{ field.field }}
    2020                        {% endif %}
  • django/contrib/admin/util.py

    diff --git a/django/contrib/admin/util.py b/django/contrib/admin/util.py
    index 7204a12..2434c4f 100644
    a b from django.utils.html import escape 
    88from django.utils.safestring import mark_safe
    99from django.utils.text import capfirst
    1010from django.utils.encoding import force_unicode, smart_unicode, smart_str
    11 from django.utils.translation import ungettext
    12 from django.core.urlresolvers import reverse
     11from django.utils.translation import ungettext, ugettext
     12from django.core.urlresolvers import reverse, NoReverseMatch
    1313
    1414
    1515def quote(s):
    def get_limit_choices_to_from_path(model, path): 
    393393        return limit_choices_to # already a Q
    394394    else:
    395395        return models.Q(**limit_choices_to) # convert dict to Q
     396
     397def get_related_object(rel, value):
     398    try:
     399        return rel.to.objects.get(pk=value)
     400    except:
     401        return None
     402
     403def get_changelink_url(obj, admin_site):
     404    """ If obj is registered in admin_site, return URL for change view. """
     405    if admin_site is None:
     406        # probably a ManyToManyRawIdWidget
     407        return None
     408    if obj.__class__ in admin_site._registry:
     409        try:
     410            view_name = '%s:%s_%s_change' % (
     411                admin_site.name,
     412                obj._meta.app_label,
     413                obj._meta.object_name.lower())
     414            return reverse(view_name, None, (quote(obj._get_pk_val()),))
     415        except NoReverseMatch:
     416            # should not happen, but fail silently just in case
     417            pass
     418    return None
     419
     420def get_changelink_html(obj, admin_site, show_name=False):
     421    """ Return HTML link to change view for obj if registered in admin_site.
     422
     423    Optionally includes representation of object (%s) in link.
     424    """
     425    url = get_changelink_url(obj, admin_site)
     426    if url is None:
     427        return ''
     428    if show_name:
     429        text = ugettext(u'Edit %s') % force_unicode(obj)
     430    else:
     431        text = ugettext('Edit')
     432    return (u' <a href="%(url)s" class="related-field-changelink changelink">'
     433            '%(text)s</a>' % {'url': url, 'text': escape(text)})
  • django/contrib/admin/widgets.py

    diff --git a/django/contrib/admin/widgets.py b/django/contrib/admin/widgets.py
    index 0d1f2a9..8415566 100644
    a b Form Widget classes specific to the Django admin site. 
    44
    55import copy
    66from django import forms
     7from django.contrib.admin.util import get_related_object, get_changelink_html
    78from django.contrib.admin.templatetags.admin_static import static
    89from django.core.urlresolvers import reverse
    910from django.forms.widgets import RadioFieldRenderer
    class ForeignKeyRawIdWidget(forms.TextInput): 
    154155            extra.append(u'<img src="%s" width="16" height="16" alt="%s" /></a>'
    155156                            % (static('admin/img/selector-search.gif'), _('Lookup')))
    156157        output = [super(ForeignKeyRawIdWidget, self).render(name, value, attrs)] + extra
     158
     159        output.append(get_changelink_html(
     160                get_related_object(self.rel, value),
     161                self.admin_site, show_name=False))
    157162        if value:
    158163            output.append(self.label_for_value(value))
    159164        return mark_safe(u''.join(output))
    class RelatedFieldWidgetWrapper(forms.Widget): 
    259264                          % (related_url, name))
    260265            output.append(u'<img src="%s" width="10" height="10" alt="%s"/></a>'
    261266                          % (static('admin/img/icon_addlink.gif'), _('Add Another')))
     267            output.append(get_changelink_html(
     268                    get_related_object(self.rel, value),
     269                    self.admin_site, show_name=True))
    262270        return mark_safe(u''.join(output))
    263271
    264272    def build_attrs(self, extra_attrs=None, **kwargs):
  • tests/regressiontests/admin_inlines/admin.py

    diff --git a/tests/regressiontests/admin_inlines/admin.py b/tests/regressiontests/admin_inlines/admin.py
    index 4edd361..43d7232 100644
    a b class SottoCapoInline(admin.TabularInline): 
    109109    model = SottoCapo
    110110
    111111
     112class IndividualInline(admin.StackedInline):
     113    model = Individual
     114    extra = 1
     115
     116
     117class PhoneInline(admin.StackedInline):
     118    model = Phone
     119    extra = 1
     120
     121
     122class EmailInline(admin.TabularInline):
     123    model = Email
     124    extra = 1
     125
     126
    112127site.register(TitleCollection, inlines=[TitleInline])
    113128# Test bug #12561 and #12778
    114129# only ModelAdmin media
    site.register(Fashionista, inlines=[InlineWeakness]) 
    124139site.register(Holder4, Holder4Admin)
    125140site.register(Author, AuthorAdmin)
    126141site.register(CapoFamiglia, inlines=[ConsigliereInline, SottoCapoInline])
     142
     143site.register(Household, inlines=[IndividualInline, PhoneInline])
     144site.register(Individual, inlines=[EmailInline])
     145site.register(Email)
     146# (Phone not registered)
  • tests/regressiontests/admin_inlines/models.py

    diff --git a/tests/regressiontests/admin_inlines/models.py b/tests/regressiontests/admin_inlines/models.py
    index 748280d..896b3d0 100644
    a b class Consigliere(models.Model): 
    136136class SottoCapo(models.Model):
    137137    name = models.CharField(max_length=100)
    138138    capo_famiglia = models.ForeignKey(CapoFamiglia, related_name='+')
     139
     140
     141# Test InlineAdminForm.admin_url:
     142
     143class Household(models.Model):
     144    pass
     145
     146
     147class Individual(models.Model):
     148    household = models.ForeignKey(Household)
     149
     150
     151class Phone(models.Model):
     152    household = models.ForeignKey(Household)
     153    number = models.CharField(max_length=64)
     154
     155
     156class Email(models.Model):
     157    individual = models.ForeignKey(Individual)
     158    email = models.EmailField()
  • tests/regressiontests/admin_inlines/tests.py

    diff --git a/tests/regressiontests/admin_inlines/tests.py b/tests/regressiontests/admin_inlines/tests.py
    index 955d620..6cf077b 100644
    a b  
     1from django.core import urlresolvers
    12from django.contrib.admin.helpers import InlineAdminForm
    23from django.contrib.contenttypes.models import ContentType
    34from django.test import TestCase
    45
    56# local test models
     7
    68from models import (Holder, Inner, Holder2, Inner2, Holder3,
    79    Inner3, Person, OutfitItem, Fashionista, Teacher, Parent, Child,
    8     CapoFamiglia, Consigliere, SottoCapo)
    9 from admin import InnerInline
     10    CapoFamiglia, Consigliere, SottoCapo, Household, Individual, Phone, Email)
     11
     12from admin import site, InnerInline
    1013
    1114
    1215class TestInline(TestCase):
    class TestInlineAdminForm(TestCase): 
    196199        iaf = InlineAdminForm(None, None, {}, {}, joe)
    197200        parent_ct = ContentType.objects.get_for_model(Parent)
    198201        self.assertEqual(iaf.original.content_type, parent_ct)
     202
     203
     204class TestAdminURL(TestCase):
     205    urls = "regressiontests.admin_inlines.urls"
     206    fixtures = ['admin-views-users.xml']
     207   
     208    def get_admin_url(self, obj_or_class, add=False):
     209        params = [site.name, obj_or_class._meta.app_label,
     210                obj_or_class._meta.module_name]
     211        if add:
     212            params.append("add")
     213            args = ()
     214        else:
     215            params.append("change")
     216            args = (obj_or_class.pk,)
     217        return urlresolvers.reverse('%s:%s_%s_%s' % tuple(params), args=args)
     218       
     219    def setUp(self):
     220        self.household = Household.objects.create()
     221        self.individual = Individual.objects.create(household=self.household)
     222        self.phone = Phone.objects.create(household=self.household,
     223                                          number='1234567890')
     224        self.email = Email.objects.create(individual=self.individual,
     225                                          email='me@example.com')
     226       
     227        result = self.client.login(username='super', password='secret')
     228        self.assertEqual(result, True)
     229       
     230    def tearDown(self):
     231        self.client.logout()
     232
     233    def test_admin_url(self):
     234        """
     235        admin_url should be set for admin-registered inline models only.
     236
     237        Also check to ensure URLs look correct and only set on bound forms.
     238        """
     239
     240        response = self.client.get(self.get_admin_url(self.household))
     241        for inline_admin_fset in response.context[-1]['inline_admin_formsets']:
     242            for inline_admin_form in inline_admin_fset:
     243                if inline_admin_form.form._meta.model != Individual:
     244                    self.assertFalse(
     245                        getattr(inline_admin_form, 'admin_url', None),
     246                        'admin_url set with unregistered model')
     247                elif not inline_admin_form.original:
     248                    self.assertFalse(
     249                        getattr(inline_admin_form, 'admin_url', None),
     250                        'admin_url set on unbound form!')
     251                else:
     252                    self.assertTrue(inline_admin_form.admin_url,
     253                                    'admin_url not set')
     254                    self.assertEqual(
     255                        inline_admin_form.original, self.individual,
     256                        'original is not expected object')
     257                    self.assertEqual(
     258                        inline_admin_form.admin_url,
     259                        self.get_admin_url(inline_admin_form.original),
     260                        'admin_url appears incorrect')
     261
     262    def test_link_rendering(self):
     263        """ Confirm links are displayed where appropriate. """
     264        LINK_CSS_CLASS = 'inline-changelink'
     265        LINK_TEXT = 'edit separately'
     266
     267        # test StackedInline rendering
     268       
     269        response = self.client.get(self.get_admin_url(Household, 'add'))
     270        self.assertNotContains(response, LINK_CSS_CLASS)
     271        self.assertNotContains(response, LINK_TEXT)
     272       
     273        response = self.client.get(self.get_admin_url(self.household))
     274        self.assertContains(response, LINK_CSS_CLASS)
     275        self.assertContains(response, LINK_TEXT)
     276
     277        # test TabularInline rendering
     278
     279        response = self.client.get(self.get_admin_url(Individual, 'add'))
     280        self.assertNotContains(response, LINK_CSS_CLASS)
     281        self.assertNotContains(response, LINK_TEXT)
     282       
     283        response = self.client.get(self.get_admin_url(self.individual))
     284        self.assertContains(response, LINK_CSS_CLASS)
     285        self.assertContains(response, LINK_TEXT)   
  • tests/regressiontests/admin_views/admin.py

    diff --git a/tests/regressiontests/admin_views/admin.py b/tests/regressiontests/admin_views/admin.py
    index e4aae4f..3d47ab6 100644
    a b class PizzaAdmin(admin.ModelAdmin): 
    385385    readonly_fields = ('toppings',)
    386386
    387387
     388class DonutOrderAdmin(admin.ModelAdmin):
     389    raw_id_fields = ('donut',)
     390
     391
     392class PizzaOrderAdmin(admin.ModelAdmin):
     393    readonly_fields = ('pizza',)
     394
     395
    388396class WorkHourAdmin(admin.ModelAdmin):
    389397    list_display = ('datum', 'employee')
    390398    list_filter = ('employee',)
    site.register(Post, PostAdmin) 
    486494site.register(Gadget, GadgetAdmin)
    487495site.register(Villain)
    488496site.register(SuperVillain)
     497site.register(Ambush)
    489498site.register(Plot)
    490499site.register(PlotDetails)
    491500site.register(CyclicOne)
    site.register(Book, inlines=[ChapterInline]) 
    512521site.register(Promo)
    513522site.register(ChapterXtra1, ChapterXtra1Admin)
    514523site.register(Pizza, PizzaAdmin)
     524site.register(PizzaOrder, PizzaOrderAdmin)
    515525site.register(Topping)
     526site.register(Donut)
     527site.register(DonutOrder, DonutOrderAdmin)
    516528site.register(Album, AlbumAdmin)
    517529site.register(Question)
    518530site.register(Answer)
  • tests/regressiontests/admin_views/models.py

    diff --git a/tests/regressiontests/admin_views/models.py b/tests/regressiontests/admin_views/models.py
    index bb8d026..f04dfea 100644
    a b class SuperSecretHideout(models.Model): 
    433433        return self.location
    434434
    435435
     436class Ambush(models.Model):
     437    hideout = models.ForeignKey(SecretHideout)
     438    when = models.DateTimeField()
     439
     440    def __unicode__(self):
     441        return u'Ambush %s at %s' % (self.hideout, self.when)
     442
     443
    436444class CyclicOne(models.Model):
    437445    name = models.CharField(max_length=25)
    438446    two = models.ForeignKey('CyclicTwo')
    class Pizza(models.Model): 
    458466    toppings = models.ManyToManyField('Topping')
    459467
    460468
     469class Donut(models.Model):
     470    name = models.CharField(max_length=20)
     471    toppings = models.ManyToManyField('Topping')
     472
     473    def __unicode__(self):
     474        return self.name
     475
     476
     477class DonutOrder(models.Model):
     478    donut = models.ForeignKey(Donut)
     479    quantity = models.IntegerField()
     480
     481    def __unicode__(self):
     482        return '%s x %d' % (self.donut, self.quantity)
     483
     484
     485class PizzaOrder(models.Model):
     486    pizza = models.ForeignKey(Pizza)
     487    quantity = models.IntegerField()
     488
     489    def __unicode__(self):
     490        return '%s x %d' % (self.pizza, self.quantity)
     491
     492
    461493class Album(models.Model):
    462494    owner = models.ForeignKey(User)
    463495    title = models.CharField(max_length=30)
  • tests/regressiontests/admin_views/tests.py

    diff --git a/tests/regressiontests/admin_views/tests.py b/tests/regressiontests/admin_views/tests.py
    index b6e7b9e..2761610 100644
    a b from django.utils.http import urlencode 
    3131from django.utils import unittest
    3232
    3333# local test models
     34
    3435from models import (Article, BarAccount, CustomArticle, EmptyModel,
    3536    FooAccount, Gallery, ModelWithStringPrimaryKey,
    3637    Person, Persona, Picture, Podcast, Section, Subscriber, Vodcast,
    from models import (Article, BarAccount, CustomArticle, EmptyModel, 
    3839    Category, Post, Plot, FunkyTag, Chapter, Book, Promo, WorkHour, Employee,
    3940    Question, Answer, Inquisition, Actor, FoodDelivery,
    4041    RowLevelChangePermissionModel, Paper, CoverLetter, Story, OtherStory,
    41     ComplexSortedPerson, Parent, Child)
     42    ComplexSortedPerson, Parent, Child, PlotDetails, Villain, SecretHideout,
     43    Ambush, Pizza, PizzaOrder, Topping, Donut, DonutOrder)
     44
    4245
    4346ERROR_MESSAGE = "Please enter the correct username and password \
    4447for a staff account. Note that both fields are case-sensitive."
    class AdminCustomSaveRelatedTests(TestCase): 
    32553258
    32563259        self.assertEqual('Josh Stone', Parent.objects.latest('id').name)
    32573260        self.assertEqual([u'Catherine Stone', u'Paul Stone'], children_names)
     3261
     3262
     3263class RelatedLinksTest(TestCase):
     3264    urls = "regressiontests.admin_views.urls"
     3265    fixtures = ['admin-views-users.xml']
     3266   
     3267    def setUp(self):
     3268        self.client.login(username='super', password='secret')
     3269        self.RELATED_LINK_CSS_CLASS = 'related-field-changelink'
     3270        self.READONLY_LINK_CSS_CLASS = 'readonly-changelink'
     3271        self.black_knight = Villain.objects.create(name='Black Knight')
     3272        self.plot = Plot.objects.create(name='None shall <pass>',
     3273                                        team_leader=self.black_knight,
     3274                                        contact=self.black_knight)
     3275        self.plot_details = PlotDetails.objects.create(
     3276            plot=self.plot, details="I'll bite your legs off!")
     3277        self.hideout = SecretHideout.objects.create(villain=self.black_knight,
     3278                                                    location='forest')
     3279        self.ambush = Ambush.objects.create(hideout=self.hideout,
     3280                                            when=datetime.datetime.now())
     3281
     3282        self.pizza = Pizza.objects.create(name='Wafer-thin pizza')
     3283        self.topping = Topping.objects.create(name='Mint')
     3284        self.pizza.toppings.add(self.topping)
     3285        self.donut = Donut.objects.create(name='Wafer-thin donut')
     3286        self.donut.toppings.add(self.topping)
     3287        self.donut_order = DonutOrder.objects.create(donut=self.donut,
     3288                                                     quantity=1000000)
     3289        self.pizza_order = PizzaOrder.objects.create(pizza=self.pizza,
     3290                                                     quantity=50)
     3291       
     3292    def tearDown(self):
     3293        self.client.logout()
     3294
     3295    def test_foreignkey(self):
     3296        """ Confirm changelink appears for populated ForeignKey fields """
     3297        response = self.client.get('/test_admin/admin/admin_views/plot/add/')
     3298        self.assertNotContains(response, self.RELATED_LINK_CSS_CLASS)
     3299        response = self.client.get('/test_admin/admin/admin_views/plot/%d/' %
     3300                                   self.plot.pk)
     3301        self.assertContains(response, self.RELATED_LINK_CSS_CLASS)
     3302        self.assertContains(response, '>Edit %s</a>' % self.black_knight)
     3303
     3304    def test_onetoone(self):
     3305        """ Confirm changelink appears for populated OneToOne fields """
     3306        response = self.client.get(
     3307            '/test_admin/admin/admin_views/plotdetails/add/')
     3308        self.assertNotContains(response, self.RELATED_LINK_CSS_CLASS)
     3309        response = self.client.get(
     3310            '/test_admin/admin/admin_views/plotdetails/%d/' %
     3311            self.plot_details.pk)
     3312        self.assertContains(response, self.RELATED_LINK_CSS_CLASS)
     3313        self.assertContains(response, '>Edit %s</a>' % escape(self.plot))
     3314
     3315    def test_unregistered(self):
     3316        """ Confirm changelink does *not* appear for unregistered fields """
     3317        response = self.client.get(
     3318            '/test_admin/admin/admin_views/ambush/add/')
     3319        self.assertNotContains(response, self.RELATED_LINK_CSS_CLASS)
     3320        response = self.client.get(
     3321            '/test_admin/admin/admin_views/ambush/%d/' %
     3322            self.ambush.pk)
     3323        self.assertNotContains(response, self.RELATED_LINK_CSS_CLASS)
     3324       
     3325    def test_readonly(self):
     3326        """ Confirm changelink appears for populated readonly fields """
     3327        response = self.client.get(
     3328            '/test_admin/admin/admin_views/pizzaorder/add/')
     3329        self.assertNotContains(response, self.READONLY_LINK_CSS_CLASS)
     3330        response = self.client.get(
     3331            '/test_admin/admin/admin_views/pizzaorder/%d/' %
     3332            self.pizza_order.pk)
     3333        self.assertContains(response, self.READONLY_LINK_CSS_CLASS)
     3334        self.assertContains(response, '>Edit</a>')
     3335
     3336    def test_manytomany(self):
     3337        """ Confirm changelinks do *not* appear for ManyToMany fields """
     3338        MULTIPLE_SELECT_STRING = '<select multiple="multiple"'
     3339       
     3340        response = self.client.get(
     3341            '/test_admin/admin/admin_views/pizza/add/')
     3342        self.assertNotContains(response, self.RELATED_LINK_CSS_CLASS)
     3343        self.assertNotContains(response, MULTIPLE_SELECT_STRING)
     3344        response = self.client.get(
     3345            '/test_admin/admin/admin_views/pizza/%d/' % self.pizza.pk)
     3346        self.assertNotContains(response, self.RELATED_LINK_CSS_CLASS)
     3347        self.assertNotContains(response, MULTIPLE_SELECT_STRING)
     3348
     3349        # try non-readonly ManyToMany
     3350        response = self.client.get(
     3351            '/test_admin/admin/admin_views/donut/add/')
     3352        self.assertContains(response, MULTIPLE_SELECT_STRING)
     3353        self.assertNotContains(response, self.RELATED_LINK_CSS_CLASS)
     3354        response = self.client.get(
     3355            '/test_admin/admin/admin_views/donut/%d/' % self.donut.pk)
     3356        self.assertNotContains(response, self.RELATED_LINK_CSS_CLASS)
     3357        self.assertContains(response, MULTIPLE_SELECT_STRING)       
     3358
     3359    def test_raw_id(self):
     3360        """ Confirm links appears for populated raw_id_fields """
     3361        response = self.client.get(
     3362            '/test_admin/admin/admin_views/donutorder/add/')
     3363        self.assertNotContains(response, self.RELATED_LINK_CSS_CLASS)
     3364        response = self.client.get(
     3365            '/test_admin/admin/admin_views/donutorder/%d/' %
     3366            self.donut_order.pk)
     3367        self.assertContains(response, self.RELATED_LINK_CSS_CLASS)
     3368        self.assertContains(response, '>Edit</a>')
  • tests/regressiontests/admin_widgets/tests.py

    diff --git a/tests/regressiontests/admin_widgets/tests.py b/tests/regressiontests/admin_widgets/tests.py
    index a7bfe55..7d6702d 100644
    a b class ForeignKeyRawIdWidgetTest(DjangoTestCase): 
    255255        w = widgets.ForeignKeyRawIdWidget(rel, widget_admin_site)
    256256        self.assertEqual(
    257257            conditional_escape(w.render('test', band.pk, attrs={})),
    258             '<input type="text" name="test" value="%(bandpk)s" class="vForeignKeyRawIdAdminField" /><a href="/widget_admin/admin_widgets/band/?t=id" class="related-lookup" id="lookup_id_test" onclick="return showRelatedObjectLookupPopup(this);"> <img src="%(ADMIN_MEDIA_PREFIX)simg/selector-search.gif" width="16" height="16" alt="Lookup" /></a>&nbsp;<strong>Linkin Park</strong>' % dict(admin_media_prefix(), bandpk=band.pk)
     258            '<input type="text" name="test" value="%(bandpk)s" class="vForeignKeyRawIdAdminField" /><a href="/widget_admin/admin_widgets/band/?t=id" class="related-lookup" id="lookup_id_test" onclick="return showRelatedObjectLookupPopup(this);"> <img src="%(ADMIN_MEDIA_PREFIX)simg/selector-search.gif" width="16" height="16" alt="Lookup" /></a> <a href="/widget_admin/admin_widgets/band/%(bandpk)s/" class="related-field-changelink changelink">Edit</a>&nbsp;<strong>Linkin Park</strong>' % dict(admin_media_prefix(), bandpk=band.pk)
    259259        )
    260260
    261261    def test_relations_to_non_primary_key(self):
    class ManyToManyRawIdWidgetTest(DjangoTestCase): 
    333333
    334334        self.assertEqual(
    335335            conditional_escape(w.render('test', [m1.pk])),
    336             '<input type="text" name="test" value="%(m1pk)s" class="vManyToManyRawIdAdminField" /><a href="/widget_admin/admin_widgets/member/" class="related-lookup" id="lookup_id_test" onclick="return showRelatedObjectLookupPopup(this);"> <img src="%(ADMIN_MEDIA_PREFIX)simg/selector-search.gif" width="16" height="16" alt="Lookup" /></a>' % dict(admin_media_prefix(), m1pk=m1.pk)
     336            '<input type="text" name="test" value="%(m1pk)s" class="vManyToManyRawIdAdminField" /><a href="/widget_admin/admin_widgets/member/" class="related-lookup" id="lookup_id_test" onclick="return showRelatedObjectLookupPopup(this);"> <img src="%(ADMIN_MEDIA_PREFIX)simg/selector-search.gif" width="16" height="16" alt="Lookup" /></a> <a href="/widget_admin/admin_widgets/member/%(m1pk)s/" class="related-field-changelink changelink">Edit</a>' % dict(admin_media_prefix(), m1pk=m1.pk)
    337337        )
    338338
    339339        self.assertEqual(w._has_changed(None, None), False)
Back to Top