I think I complicate this more because what I am using for the Foreign Key has a Choice setting and I have the Foreign Key set to show the human readable choice. Which seems to be what it is searching on. Strikes me as strange though because when I look at the return data it appears to be passing the primary key.
Anyways maybe some code will help so: (as a caveat this is the 9 millionth view iteration and at this point I was at least kind of experimenting with different thing)
views.py
model = Ship
fields = ['hull', 'name', 'debt']
template_name = 'crew/ship.html'
success_url = reverse_lazy('crew_app:ship_list')
def form_valid(self, form):
hul = form.instance.hull
hp = get_object_or_404(ShipHull, hull=hul)
form.instance.hull_points_max = hp.hull_points
form.instance.hull_points_cur = hp.hull_points
return super().form_valid(form)
models.py
class ShipHull(models.Model):
SHIP_TYPE = (
('WF', 'Worn Freighter'),
('RTT', 'Retired Troop Transport'),
('SAV', 'Strange Alien Vessel'),
('UPS', 'Upgraded Shuttle'),
('RSS', 'Retired Scout Ship'),
('RSV', 'Repurposed Science Vessel'),
('BMV', 'Battered Mining Ship'),
('UMC', 'Unreliable Merchant Cruiser'),
('FDV', 'Former Diplomatic Vessel'),
('ALC', 'Ancient Low-Tech Craft'),
('BSW', 'Built from Salvaged Wrecks'),
('RMS', 'Retired Military Patrol Ship'),
)
hull = models.CharField(max_length=200, choices=SHIP_TYPE)
traits = ArrayField(models.CharField(max_length=200), blank=True)
hull_points = models.IntegerField()
debt = models.CharField(max_length=200)
roll = IntegerRangeField(null=True)
def __str__(self):
return self.get_hull_display()
class Ship(models.Model):
owner = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True)
name = models.CharField(max_length=300,)
debt = models.CharField(max_length=4,)
hull = models.ForeignKey(ShipHull, on_delete=models.CASCADE, null=True)
hull_points_max = models.IntegerField(null=True)
hull_points_cur = models.IntegerField(null=True)
upgrades = ArrayField(models.CharField(max_length=200), blank=True)
def __str__(self):
return self.name
Here is what I see being returned in the POST:
hull: 1
name: Serenity
debt: 23
If I switch over to trying to use id I get a type error that it can't be found. Here is the traceback:
Traceback (most recent call last):
File "F:\Python\profnobody\venv\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
response = get_response(request)
File "F:\Python\profnobody\venv\lib\site-packages\django\core\handlers\base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "F:\Python\profnobody\venv\lib\site-packages\django\views\generic\base.py", line 70, in view
return self.dispatch(request, *args, **kwargs)
File "F:\Python\profnobody\venv\lib\site-packages\django\views\generic\base.py", line 98, in dispatch
return handler(request, *args, **kwargs)
File "F:\Python\profnobody\venv\lib\site-packages\django\views\generic\edit.py", line 172, in post
return super().post(request, *args, **kwargs)
File "F:\Python\profnobody\venv\lib\site-packages\django\views\generic\edit.py", line 142, in post
return self.form_valid(form)
File "F:\Python\profnobody\crew_app\views.py", line 54, in form_valid
hp = get_object_or_404(ShipHull, id=hul)
File "F:\Python\profnobody\venv\lib\site-packages\django\shortcuts.py", line 76, in get_object_or_404
return queryset.get(*args, **kwargs)
File "F:\Python\profnobody\venv\lib\site-packages\django\db\models\query.py", line 424, in get
clone = self._chain() if self.query.combinator else self.filter(*args, **kwargs)
File "F:\Python\profnobody\venv\lib\site-packages\django\db\models\query.py", line 941, in filter
return self._filter_or_exclude(False, args, kwargs)
File "F:\Python\profnobody\venv\lib\site-packages\django\db\models\query.py", line 961, in _filter_or_exclude
clone._filter_or_exclude_inplace(negate, args, kwargs)
File "F:\Python\profnobody\venv\lib\site-packages\django\db\models\query.py", line 968, in _filter_or_exclude_inplace
self._query.add_q(Q(*args, **kwargs))
File "F:\Python\profnobody\venv\lib\site-packages\django\db\models\sql\query.py", line 1416, in add_q
clause, _ = self._add_q(q_object, self.used_aliases)
File "F:\Python\profnobody\venv\lib\site-packages\django\db\models\sql\query.py", line 1435, in _add_q
child_clause, needed_inner = self.build_filter(
File "F:\Python\profnobody\venv\lib\site-packages\django\db\models\sql\query.py", line 1370, in build_filter
condition = self.build_lookup(lookups, col, value)
File "F:\Python\profnobody\venv\lib\site-packages\django\db\models\sql\query.py", line 1216, in build_lookup
lookup = lookup_class(lhs, rhs)
File "F:\Python\profnobody\venv\lib\site-packages\django\db\models\lookups.py", line 25, in __init__
self.rhs = self.get_prep_lookup()
File "F:\Python\profnobody\venv\lib\site-packages\django\db\models\lookups.py", line 77, in get_prep_lookup
return self.lhs.output_field.get_prep_value(self.rhs)
File "F:\Python\profnobody\venv\lib\site-packages\django\db\models\fields\__init__.py", line 1825, in get_prep_value
raise e.__class__(
TypeError: Field 'id' expected a number but got <ShipHull: Worn Freighter>.
So what I am trying to figure out, is how to be able to search this value properly.
Because I shared the traceback when I switch over to id here is the view with id: views.py (again but changed to id)
class CreateShipView(CreateView):
model = Ship
fields = ['hull', 'name', 'debt']
template_name = 'crew/ship.html'
success_url = reverse_lazy('crew_app:ship_list')
def form_valid(self, form):
hul = form.instance.hull
hp = get_object_or_404(ShipHull, id=hul)
form.instance.hull_points_max = hp.hull_points
form.instance.hull_points_cur = hp.hull_points
return super().form_valid(form)
CodePudding user response:
You're passing an object instance to an int field. Did you try:
hp = get_object_or_404(ShipHull, id=hul.id)
Or even better:
hp = get_object_or_404(ShipHull, pk=hul.pk)