I have been using str to handle human readable names for model objects for awhile now, but recently I have been running into some strange crashes and bugs that seem to be related to this function.
I have two models SensorAssignment
and SnComplex
, both have OneToOne relationships to a column on a third model RadioSn
. RadioSn
is the master pool of all serial numbers. SnComplex
is the list of serials assigned to a customer and SensorAssignment
handles the metadata for a customer's serial assigned to a specific physical location.
It is important to note that this is a legacy db that I inherited. Some relationships are not ideal IMHO.
Below are simplified versions of the models with only relevant columns.
RadioSn
class RadioSn(models.Model):
sn = models.AutoField(primary_key=True)
role = models.ForeignKey('Roles', db_column='role', on_delete=models.DO_NOTHING)
class Meta:
managed = False
db_table = 'radio_sn'
ordering = ['sn']
def __str__(self):
return '%s -- %s' % (self.sn, self.role)
SnComplex
class SnComplex(models.Model):
sn = models.OneToOneField(RadioSn, on_delete=models.DO_NOTHING, db_column='sn', primary_key=True)
complex = models.ForeignKey(Complex, on_delete=models.DO_NOTHING, db_column='complex')
class Meta:
managed = False
db_table = 'sn_complex'
SensorAssignment
class SensorAssignment(models.Model):
unit = models.ForeignKey('Unit', on_delete=models.DO_NOTHING, db_column='unit')
sn = models.OneToOneField(RadioSn, on_delete=models.DO_NOTHING, db_column='sn')
class Meta:
managed = False
db_table = 'sensor_assignment'
ordering = ['sn']
def __str__(self):
return self.pk
Here is where we start to run into my problem. I use form.ModelForm
to handle the creation and maintenance of SensorAssignment
objects. Thus for the field sn
it creates a html <select>
with choices of RadioSn
objects which are represented by the str format delineated above (a string composed of the int primary key sn
and the foreign key role
[bad naming IMHO]).
This works perfectly (I do limit the querysets to relevant options on the form's initialization on a view, so it isn't all()
objects in the model.)
So I should be able to do the same thing for SnComplex
, right? After all each model has the same relationship to RadioSn
on their respective sn
columns, and the str
representation of RadioSn
objects is done on that model.
Nope, this is what I get.
If I simply represent RadioSn
objects as self.sn
instead of concatenating self.sn
and self.role
it works on both forms, but if I leave it concatenated is crashes the SnComplex
form. All RadioSn
objects have a role value.
Any ideas what is going on? We have a string representation of RadioSn
model objects crashing the SnComplex
ModelForm
on template rendering, but working fine on multiple versions SensorAssignment
ModelForm
elsewhere.
Requested SnComplex form:
class AddSensorForm(forms.ModelForm):
class Meta:
model = SnComplex
fields = '__all__'
Full traceback:
Request Method: GET
Request URL: http://127.0.0.1/complex/33/
Django Version: 2.0.4
Python Version: 3.6.1
Installed Applications:
['apps.dashboard',
'rest_framework',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'apps.dashboard.templatetags.custom_filters',
'widget_tweaks',
'phonenumber_field',
'pygal',
'django_filters']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware']
Template error:
In template C:\git\si-dash\apps\dashboard\templates\header.html, error at line 0
Roles matching query does not exist.
1 : {% load static %}
2 : {% load widget_tweaks %}
3 : {% load custom_filters %}
4 : {% csrf_token %}
5 :
6 : <!DOCTYPE html>
7 : <html lang="en">
8 :
9 : <head>
10 : <meta charset="utf-8">
Traceback:
File "C:\Python36\lib\site-packages\django\db\models\fields\related_descriptors.py" in __get__
158. rel_obj = self.field.get_cached_value(instance)
File "C:\Python36\lib\site-packages\django\db\models\fields\mixins.py" in get_cached_value
13. return instance._state.fields_cache[cache_name]
During handling of the above exception ('role'), another exception occurred:
File "C:\Python36\lib\site-packages\django\core\handlers\exception.py" in inner
35. response = get_response(request)
File "C:\Python36\lib\site-packages\django\core\handlers\base.py" in _get_response
128. response = self.process_exception_by_middleware(e, request)
File "C:\Python36\lib\site-packages\django\core\handlers\base.py" in _get_response
126. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Python36\lib\site-packages\django\contrib\auth\decorators.py" in _wrapped_view
21. return view_func(request, *args, **kwargs)
File "C:\git\si-dash\apps\dashboard\views\complex.py" in complex
179. return render(request, 'design/complex.html', passed_data)
File "C:\Python36\lib\site-packages\django\shortcuts.py" in render
36. content = loader.render_to_string(template_name, context, request, using=using)
File "C:\Python36\lib\site-packages\django\template\loader.py" in render_to_string
62. return template.render(context, request)
File "C:\Python36\lib\site-packages\django\template\backends\django.py" in render
61. return self.template.render(context)
File "C:\Python36\lib\site-packages\django\template\base.py" in render
175. return self._render(context)
File "C:\Python36\lib\site-packages\django\template\base.py" in _render
167. return self.nodelist.render(context)
File "C:\Python36\lib\site-packages\django\template\base.py" in render
943. bit = node.render_annotated(context)
File "C:\Python36\lib\site-packages\django\template\base.py" in render_annotated
910. return self.render(context)
File "C:\Python36\lib\site-packages\django\template\loader_tags.py" in render
155. return compiled_parent._render(context)
File "C:\Python36\lib\site-packages\django\template\base.py" in _render
167. return self.nodelist.render(context)
File "C:\Python36\lib\site-packages\django\template\base.py" in render
943. bit = node.render_annotated(context)
File "C:\Python36\lib\site-packages\django\template\base.py" in render_annotated
910. return self.render(context)
File "C:\Python36\lib\site-packages\django\template\loader_tags.py" in render
67. result = block.nodelist.render(context)
File "C:\Python36\lib\site-packages\django\template\base.py" in render
943. bit = node.render_annotated(context)
File "C:\Python36\lib\site-packages\django\template\base.py" in render_annotated
910. return self.render(context)
File "C:\Python36\lib\site-packages\django\template\defaulttags.py" in render
314. return nodelist.render(context)
File "C:\Python36\lib\site-packages\django\template\base.py" in render
943. bit = node.render_annotated(context)
File "C:\Python36\lib\site-packages\django\template\base.py" in render_annotated
910. return self.render(context)
File "C:\Python36\lib\site-packages\django\template\defaulttags.py" in render
211. nodelist.append(node.render_annotated(context))
File "C:\Python36\lib\site-packages\django\template\base.py" in render_annotated
910. return self.render(context)
File "C:\Python36\lib\site-packages\widget_tweaks\templatetags\widget_tweaks.py" in render
187. return str(bounded_field)
File "C:\Python36\lib\site-packages\django\utils\html.py" in <lambda>
380. klass.__str__ = lambda self: mark_safe(klass_str(self))
File "C:\Python36\lib\site-packages\django\forms\boundfield.py" in __str__
36. return self.as_widget()
File "C:\Python36\lib\site-packages\widget_tweaks\templatetags\widget_tweaks.py" in as_widget
31. html = old_as_widget(widget, attrs, only_initial)
File "C:\Python36\lib\site-packages\widget_tweaks\templatetags\widget_tweaks.py" in as_widget
31. html = old_as_widget(widget, attrs, only_initial)
File "C:\Python36\lib\site-packages\widget_tweaks\templatetags\widget_tweaks.py" in as_widget
31. html = old_as_widget(widget, attrs, only_initial)
File "C:\Python36\lib\site-packages\django\forms\boundfield.py" in as_widget
118. **kwargs
File "C:\Python36\lib\site-packages\django\forms\widgets.py" in render
234. context = self.get_context(name, value, attrs)
File "C:\Python36\lib\site-packages\django\forms\widgets.py" in get_context
677. context = super().get_context(name, value, attrs)
File "C:\Python36\lib\site-packages\django\forms\widgets.py" in get_context
637. context['widget']['optgroups'] = self.optgroups(name, context['widget']['value'], attrs)
File "C:\Python36\lib\site-packages\django\forms\widgets.py" in optgroups
585. for index, (option_value, option_label) in enumerate(self.choices):
File "C:\Python36\lib\site-packages\django\forms\models.py" in __iter__
1141. yield self.choice(obj)
File "C:\Python36\lib\site-packages\django\forms\models.py" in choice
1147. return (self.field.prepare_value(obj), self.field.label_from_instance(obj))
File "C:\Python36\lib\site-packages\django\forms\models.py" in label_from_instance
1213. return str(obj)
File "C:\git\si-dash\apps\dashboard\models.py" in __str__
728. return '%s -- %s' % (self.sn, self.role)
File "C:\Python36\lib\site-packages\django\db\models\fields\related_descriptors.py" in __get__
164. rel_obj = self.get_object(instance)
File "C:\Python36\lib\site-packages\django\db\models\fields\related_descriptors.py" in get_object
139. return qs.get(self.field.get_reverse_related_filter(instance))
File "C:\Python36\lib\site-packages\django\db\models\query.py" in get
403. self.model._meta.object_name
Exception Type: DoesNotExist at /complex/33/
Exception Value: Roles matching query does not exist.
I was reviewing the issue you are having and I thought it might be an internal joining error. I looked at the DB (non django managed) and it appears the radio_sn.role is not set as a foreign key.
Given that it was possible to have a "bad" role associated with a particular sensor. It looks there was a legacy record of a serial number with a role that didn't exist in the roles table which was the root cause of the join error and the "no role" error you were getting.
I corrected those records and will look into steps into making radio_sn.role a foreign key to the roles table.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.