Wednesday, May 24, 2017

Re: saving data from both a model and a derived model

Internal Server Error: /prep_signing/
Traceback (most recent call last):
File "/home/jja/testenv3.5/lib/python3.5/site-packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
File "/home/jja/testenv3.5/lib/python3.5/site-packages/django/db/backends/sqlite3/base.py", line 337, in execute
return Database.Cursor.execute(self, query, params)
sqlite3.IntegrityError: UNIQUE constraint failed: siggy_stemplate.name

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "/home/jja/testenv3.5/lib/python3.5/site-packages/django/core/handlers/exception.py", line 39, in inner
response = get_response(request)
File "/home/jja/testenv3.5/lib/python3.5/site-packages/django/core/handlers/base.py", line 249, in _legacy_get_response
response = self._get_response(request)
File "/home/jja/testenv3.5/lib/python3.5/site-packages/django/core/handlers/base.py", line 187, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/home/jja/testenv3.5/lib/python3.5/site-packages/django/core/handlers/base.py", line 185, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/jja/testenv3.5/lib/python3.5/site-packages/django/views/generic/base.py", line 68, in view
return self.dispatch(request, *args, **kwargs)
File "/home/jja/testenv3.5/lib/python3.5/site-packages/django/views/generic/base.py", line 88, in dispatch
return handler(request, *args, **kwargs)
File "/home/jja/prog/ppath/newSiggy/siggy_project/views/RSPrepView.py", line 33, in get
template_data_list = self.rs_templates()
File "/home/jja/prog/ppath/newSiggy/siggy_project/views/RSPrepView.py", line 91, in rs_templates
rs_template.save()
File "/home/jja/testenv3.5/lib/python3.5/site-packages/django/db/models/base.py", line 796, in save
force_update=force_update, update_fields=update_fields)
File "/home/jja/testenv3.5/lib/python3.5/site-packages/django/db/models/base.py", line 823, in save_base
self._save_parents(cls, using, update_fields)
File "/home/jja/testenv3.5/lib/python3.5/site-packages/django/db/models/base.py", line 848, in _save_parents
self._save_table(cls=parent, using=using, update_fields=update_fields)
File "/home/jja/testenv3.5/lib/python3.5/site-packages/django/db/models/base.py", line 908, in _save_table
result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
File "/home/jja/testenv3.5/lib/python3.5/site-packages/django/db/models/base.py", line 947, in _do_insert
using=using, raw=raw)
File "/home/jja/testenv3.5/lib/python3.5/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/home/jja/testenv3.5/lib/python3.5/site-packages/django/db/models/query.py", line 1045, in _insert
return query.get_compiler(using=using).execute_sql(return_id)
File "/home/jja/testenv3.5/lib/python3.5/site-packages/django/db/models/sql/compiler.py", line 1054, in execute_sql
cursor.execute(sql, params)
File "/home/jja/testenv3.5/lib/python3.5/site-packages/django/db/backends/utils.py", line 79, in execute
return super(CursorDebugWrapper, self).execute(sql, params)
File "/home/jja/testenv3.5/lib/python3.5/site-packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
File "/home/jja/testenv3.5/lib/python3.5/site-packages/django/db/utils.py", line 94, in __exit__
six.reraise(dj_exc_type, dj_exc_value, traceback)
File "/home/jja/testenv3.5/lib/python3.5/site-packages/django/utils/six.py", line 685, in reraise
raise value.with_traceback(tb)
File "/home/jja/testenv3.5/lib/python3.5/site-packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
File "/home/jja/testenv3.5/lib/python3.5/site-packages/django/db/backends/sqlite3/base.py", line 337, in execute
return Database.Cursor.execute(self, query, params)
django.db.utils.IntegrityError: UNIQUE constraint failed: siggy_stemplate.name
[24/May/2017 17:35:51] "GET /prep_signing/ HTTP/1.1" 500 184214

Hi James,

I'm attaching the stacktrace as you requested.

The call to rs_template.save() is made from a django view.  rs_template is an instance of a class RSTemplate which is derived from STemplate. STemplate is derived from PriorityItemType. PriorityItemType is derived from ItemType. ItemType is derived from models.Model. PriorityItemType and ItemType are classes that are part of a library and which I have minimal control over, so figure them as constants that cannot be changed.

Jim


The relevant code is as follows:

From ItemType.py

[code]
class ItemType(models.Model):
    ...
    name = models.CharField('Name', max_length=100, unique=True, db_index=True)
[/code]

From PriorityItemType.py

[code]
class PriorityItemType(ItemType):
   ...
   priority = models.IntegerField('Priority', default=1)
[/code]

From STemplate.py

[code]
class STemplate(PriorityItemType):
    ...
    backend = models.ForeignKey('siggy.SBackend', null=True, blank=True)
[/code]

From RSTemplate.py

[code]
class RSTemplate(STemplate):
   ...
   role = models.CharField(max_length=50)
[code]

From RSPrepView.py

[code]
class RSPrewView(View):
   ...
  
   for t in templates.templates:
            try:
                rs_template = RSTemplate.objects.get(name=t.filename)
            except RSTemplate.DoesNotExist:
                rs_template = RSTemplate()
            rs_template.name = t.filename
            rs_template.role = "RS Template"
            rs_template.save()
[/code]



On Wed, May 24, 2017 at 3:36 AM, James Schneider <jrschneider83@gmail.com> wrote:


On Tue, May 23, 2017 at 3:44 PM, <jjanderson52000@gmail.com> wrote:
I have a model class, 'A_base', and a 2nd model class, 'A_derived'. When I save an object of A_derived, I want the data from both my base and derived class to be saved.

Example code looks like this:

    class A_base(models.model):
        name = models.CharField(max_length=50)

    class A_derived(A_base):
        role = models.CharField(max_length=50)


So when I call save(), I want to save an instance of the derived object, including the data in the base class into my sqlite3 database. I would like my code to look like this:

    ...
    derived_obj = A_derived.objects.get(name="john")
    derived_obj.role = "parent"
    derived_obj.save()
    ...

My question is whether the save method will save 'role' to the A_derived table and save 'name' to the A_base table? Or do I have to override the save method so that it saves 'role' and then calls the base class save method to save 'name'?


No, you have created two separate (but related) models. A_base has a model field of 'name', and A_derived has model fields 'name' and 'role'. Since you are inheriting from a non-abstract parent model, there is an implied OneToOne relationship between the two models, see the following: https://docs.djangoproject.com/en/1.11/topics/db/models/#multi-table-inheritance

I'm not a big fan of this implied behavior, but it hasn't been problematic for me because I make heavy use of abstract model classes.

If you do not want the implied relationship between the two models, create an abstract base class matching A_base and have both of your models inherit from it (A_base would be an empty model in this case, most likely).

From a Django perspective, these two are completely independent models/entities (aside from the OneToOne relationship). A_derivied will have its own name and role. A_base also has it's own name, but will not be able to contain a role.

To achieve the behavior you want, when A_derived is saved, you'll need to either create a new A_base object and set the 'name' field to the same value, or query for an existing A_base object and change/save the 'name' field. Keep in mind that the two values are not connected to each other. Changing the 'name' field on the same A_derived class later will NOT change the 'name' field on an A_base object automatically, you would need to provide such logic on one or both models, depending on the direction of the dependency you wish to create.
 
I tried doing this using the default save method and it created a stack trace, so I'm guessing that I am expecting too much from the default save method.


Post the entire stack trace and we may be able to better illuminate the issue.  

-James

--
You received this message because you are subscribed to a topic in the Google Groups "Django users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/django-users/QPo8MFXNdAc/unsubscribe.
To unsubscribe from this group and all its topics, send an email to django-users+unsubscribe@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/CA%2Be%2BciXDpbGmmpqbcDC_iipvRVowJhuw3VcdeJsVLMAVJ5g-WQ%40mail.gmail.com.

For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/CAB5UADG81zZsE4s54rNWifP_3v8-C0vke88pXOFm6QgJZLRFZQ%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

No comments:

Post a Comment