Opened 4 years ago

Closed 7 weeks ago

#17214 closed Bug (fixed)

incorrect rendering of inline fk when parent has custom pk field

Reported by: Aryeh Leib Taurog <vim@…> Owned by: nobody
Component: Forms Version: 1.3
Severity: Normal Keywords:
Cc: vim@… Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

pkfk/models.py

from django.db import models

class TZDateField(models.DateField):
    description = "Date field stored in PostgreSQL as TIMESTAMP WITH TIME ZONE"
    __metaclass__ = models.SubfieldBase
    def db_type(self, connection): return "TIMESTAMP WITH TIME ZONE"

class FooDate(models.Model):
    foo_date = TZDateField(primary_key=True)

class Bar(models.Model):
    baz  = models.CharField(max_length=10)
    foo_date = models.ForeignKey("FooDate")
    class Meta:
        unique_together = ("baz", "foo_date")

pkfk/admin.py

from django.contrib import admin
from pkfk.models import FooDate, Bar

class BarInline(admin.TabularInline):
    model = Bar

class FooDateAdmin(admin.ModelAdmin):
    inlines = [BarInline]

admin.site.register(FooDate, FooDateAdmin)

When trying to re-save inline objects in the admin, I get a mysterious "Please correct the errors below." message, but no further error messages are displayed. If I supply my own inline formset and catch the clean() call, I can see the following formset.errors:

[{'foo_date': [u'The inline foreign key did not match the parent instance primary key.']},
 {'foo_date': [u'The inline foreign key did not match the parent instance primary key.']},
 {},
 {},
 {}]

This is because html for the hidden foreign key field on the inline is rendered as follows:

<input type="hidden" name="bar_set-0-foo_date" value="2011-11-12 00:00:00" id="id_bar_set-0-foo_date">

In order for this to work it needs to be rendered without the time:

<input type="hidden" name="bar_set-0-foo_date" value="2011-11-12" id="id_bar_set-0-foo_date">

If the inline form would only call the pk field's to_python or get_prep_value before rendering the fk, it would be correct, but it seems to be pulling it straight from the db and rendering that datum on its own. Perhaps this ticket is related? Am I missing something?

I tried this and got the same results under 1.2.4, 1.2.7, and 1.3.1.

Change History (5)

comment:1 follow-up: Changed 4 years ago by aaugustin

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Resolution set to duplicate
  • Status changed from new to closed

I'm pretty sure this is a duplicate of #17122. This ticket has patches, could you test if they resolve your problem?

comment:2 in reply to: ↑ 1 Changed 4 years ago by Aryeh Leib Taurog <vim@…>

  • Resolution duplicate deleted
  • Status changed from closed to reopened

Replying to aaugustin:

I'm pretty sure this is a duplicate of #17122. This ticket has patches, could you test if they resolve your problem?

Yes, I also thought so. I should have mentioned that I tried that patch before submitting this bug. It does not solve the problem. Feel free to give it a whirl. All you need to test are the models.py and admin.py I posted and a postgresql db.

comment:3 Changed 4 years ago by aaugustin

  • Triage Stage changed from Unreviewed to Accepted

Since your report contains enough detail to reproduce the problem, and the bug looks plausible, I'm accepting the ticket (I didn't attempt to reproduce it myself).

comment:4 Changed 2 years ago by aaugustin

  • Status changed from reopened to new

comment:5 Changed 7 weeks ago by claudep

  • Resolution set to fixed
  • Status changed from new to closed

I think that the addition of from_db_value() in Django 1.8 solves this issue.
https://docs.djangoproject.com/en/1.8/ref/models/fields/#django.db.models.Field.from_db_value

Here's what would be a functional TZDateField definition:

class TZDateField(models.DateField):
    description = "Date field stored in PostgreSQL as TIMESTAMP WITH TIME ZONE"

    def db_type(self, connection):
        return "TIMESTAMP WITH TIME ZONE"

    def from_db_value(self, value, expression, connection, context):
        if value is not None:
            return self.to_python(value)
        return value
Note: See TracTickets for help on using tickets.
Back to Top