I'm building a page that allows users to edit Task and related Activity records (one task can have many activities), all on the same page. Here are extracts from my code...
models.py
from django.contrib.auth.models import User
class Task(models.Model):
category = models.CharField(max_length=300)
description = models.CharField(max_length=300)
class Activity(models.Model):
task = models.ForeignKey(Task, on_delete=models.CASCADE)
title = models.CharField(max_length=150)
notes = models.TextField(blank=True)
owner = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
The activity "owner" is linked to a User from the Django standard user model.
views.py
def manage_task(request, pk):
task = Task.objects.get(pk = pk)
TaskInlineFormSet = inlineformset_factory(Task, Activity,
form = ActivityForm)
if request.method == "POST":
form = TaskForm(request.POST, instance = task)
formset = TaskInlineFormSet(request.POST, instance = task)
if form.has_changed() and form.is_valid():
form.save()
if formset.has_changed() and formset.is_valid():
formset.save()
return redirect('manage_task',pk=task.id)
else:
form = TaskForm(instance = task)
formset = TaskInlineFormSet(instance = task)
context = {'task': task, 'task_form': form, 'formset': formset}
return render(request, 'tasks/manage_task.html', context)
And manage_task.html excerpt:
<h2>{{ task.category }}</h2>
<form method="post">
{% csrf_token %}
{{ task_form.description }}
{% for form in formset %}
{{ form.id }}
{{ form.title }}</br>
{{ form.notes }}</br>
{% if user.id == form.owner.value %}
You own this Activity!</br>
{% else %}
{{ form.owner.first_name }} owns this Activity</br>
{% endif %}
{% endfor %}
<input type="submit" value="SAVE">
</form>
Perhaps obviously, {{ form.owner.first_name }} doesn't return anything. form.owner understandably renders as a select drop down with all the Users listed - it's some sort of iterable object so it doesn't have a first_name attribute.
I think I need to have the first_name field in each form in the formset so it ties up properly with the correct Activity form.
I feel like I might have to adapt the view in some way to go through all the forms in the formset and use the owner.id (if it exists) to access the related User and add the first_name attribute as an extra field in the form somehow? That doesn't feel very Djangoish, there must be a better way.
How can I use the form field form.owner to get the first_name attribute from the User object that's related to the Activity so I can use it in the template?
CodePudding user response:
You should not take such value from form directly. It may be risky (i.e. changing real-life). But if you are aware of it and ok with that, try pointing to specific instance of form:
{{ form.instance.owner.first_name }}
