Opened 8 years ago

Closed 8 years ago

#26245 closed Bug (duplicate)

[1.9] Change of primary_key Field on Child Table with One-to-one Relationship Create Duplicated Record

Reported by: lystor Owned by: nobody
Component: Database layer (models, ORM) Version: 1.9
Severity: Normal Keywords: One-to-one, duplicate
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Hi

After changing the value of primary_key field on child table (using drop-down list) with One-to-one relationship in Django Admin Site we got duplicated record in table because the record with new primary_key value is added but existing record with old primary_key is not deleted.

  • django 1.9.2
  • python 3.5.1
  • mysqlclient 1.3.7
  • mysql 5.7.11

models.py

from django.db import models

class Metric(models.Model):
	name		= models.CharField(unique=True, max_length=255)
	params		= models.CharField(max_length=255)
	value		= models.CharField(max_length=255, blank=True)

	class Meta:
		managed		= False
		db_table	= 'metrics'

	def __str__(self):
		return str(self.id)


class PollerEvent(models.Model):
	metric			= models.OneToOneField(Metric, on_delete=models.CASCADE, primary_key=True)
	duration		= models.IntegerField()
	error			= models.TextField()

	class Meta:
		managed		= False
		db_table	= 'poller_events'

	def __str__(self):
		return '%s (%s)' % (self.metric_id, self.error)

admin.py

from django.contrib import admin

from .models import Metric, PollerEvent

admin.site.register(Metric)
admin.site.register(PollerEvent)

test.py

import django, os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings")
django.setup()
from dashboard.models import Metric, PollerEvent

print('=== BEFORE ===============================')
print(Metric.objects.all())
print(PollerEvent.objects.all())

print('=== CHANGE ===============================')
event = PollerEvent.objects.get(metric_id = 3)
event.metric_id = 4
event.save()

print('=== AFTER ===============================')
print(PollerEvent.objects.all())

print('=== SQL ===============================')
for query in django.db.connection.queries:
	print(query)

result

=== BEFORE ===============================
[<Metric: 1>, <Metric: 3>, <Metric: 4>]

[<PollerEvent: 3 (timeout)>]

=== CHANGE ===============================

=== AFTER ===============================
[<PollerEvent: 3 (timeout)>, <PollerEvent: 4 (timeout)>]

=== SQL ===============================
{'sql': 'SET SQL_AUTO_IS_NULL = 0', 'time': '0.036'}

{'sql': 'SELECT `metrics`.`id`, `metrics`.`name`, `metrics`.`params`, `metrics`.`value` FROM `metrics` LIMIT 21', 'time': '0.036'}

{'sql': 'SELECT `poller_events`.`metric_id`, `poller_events`.`duration`, `poller_events`.`error` FROM `poller_events` LIMIT 21', 'time': '0.036'}

{'sql': 'SELECT `poller_events`.`metric_id`, `poller_events`.`duration`, `poller_events`.`error` FROM `poller_events` WHERE `poller_events`.`metric_id` = 3', 'time': '0.036'}

{'sql': "UPDATE `poller_events` SET `duration` = 555, `error` = 'timeout' WHERE `poller_events`.`metric_id` = 4", 'time': '0.036'}

{'sql': "INSERT INTO `poller_events` (`metric_id`, `duration`, `error`) VALUES (4, 555, 'timeout')", 'time': '0.036'}

{'sql': 'SELECT `poller_events`.`metric_id`, `poller_events`.`duration`, `poller_events`.`error` FROM `poller_events` LIMIT 21', 'time': '0.036'}

Please fix this bug.
Thank you!

--
With best regards,
Mykola

Change History (1)

comment:1 by Tim Graham, 8 years ago

Resolution: duplicate
Severity: Release blockerNormal
Status: newclosed

Unless the behavior changed in 1.9, this looks like a duplicate of #2259 to me.

Note: See TracTickets for help on using tickets.
Back to Top