How to pass pk to form (ForeignKey) and views - from template when following link?
How to pass pk to the form (ForeignKey) and views - from the template when clicking on a link? Good day!
I have a model. Which is displayed in the template. And the transition to another template is configured by a link. But my form is not displayed there. I also wanted to ask how I can pass (pk) to the form in order to enter data only for the object by which the transition was made by the link? I click on the link and get to a specific object. I wanted to fill in its properties through the form. How can I fill in specifically for the object by (pk) that I clicked on the link to the view and form? For some reason, my form is not displayed.
class ArkiObject_1 (models.Model):
city = models.CharField(choices=TYPE_CITY, verbose_name="Городской округ")
nameobject = models.TextField(verbose_name="Наименование объекта")
typeobject = models.CharField(choices=TYPE_OBJECT, verbose_name="Тип объекта")
param_1 = models.FloatField(verbose_name="Мощность котельной, МВт")
param_2 = models.FloatField(verbose_name="Диаметры трубопроводов, мм")
def __str__(self):
return self.nameobject
class ArkiGpr (models.Model):
name = models.ForeignKey(ArkiObject_1, on_delete=models.CASCADE)
work = models.TextField(verbose_name="Наименование работы")
peoples = models.IntegerField(verbose_name="Количество людей")
---
class FormOne (forms.ModelForm):
class Meta:
model = ArkiObject_1
fields = "__all__"
class Form_GPR (forms.ModelForm):
class Meta:
model = ArkiGpr
fields = "__all__"
class FilterForm(forms.Form):
name = forms.CharField()
---
import django_filters
from .models import *
class BookFilter(django_filters.FilterSet):
class Meta:
model = ArkiObject_1
fields = ["city"]
def formone(request):
context = {}
formone = FormOne(request.POST or None)
if formone.is_valid():
formone.save()
return redirect("formone")
context['formone'] = formone
return render(request, "formone.html", context)
def table(request):
context = {}
book_filter = BookFilter(request.GET, queryset=ArkiObject_1.objects.all())
table_2 = book_filter.qs
context['form'] = book_filter.form
table = pd.DataFrame.from_records(table_2.values("city", "nameobject", "typeobject", "budget", "podryadchik"))
context['table'] = table
context['books'] = table_2
return render(request, "table.html", context)
def book(request, pk):
context = {}
form_2 = Form_GPR(request.POST or None)
if form_2.is_valid():
form_2.save()
return redirect("bookdetail")
context['form_2'] = form_2
""" Gets an individual book object from the database, based on its ID/PK. Renders a detail template """
book = get_object_or_404(ArkiObject_1, pk=pk)
context = {'book': book}
return render(request, 'bookdetail.html', context)
----
urlpatterns = [
path('admin/', admin.site.urls),
path('formone', views.formone, name="formone"),
path('table', views.table, name="table"),
path('book/<int:pk>/', views.book, name='book-detail')
]
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>title</title>
</head>
<body>
<div>
<h4>Мероприятия</h4>
</div>
<br/>
<div>
<form method="GET" action="{% url 'table' %}">
{{ form.as_p }}
<input type="submit" value="Submit" class="button" />
</form>
</div>
<br/>
<div>
<table style="font-family: Arial, Helvetica, sans-serif; font-size: small;">
<thead>
<tr>
{% for col in table.columns %}
<th>
{{ col }}
</th>
{% endfor %}
</tr>
</thead>
{% for index, row in table.iterrows %}
<tr>
{% for cell in row %}
<td style="text-align: center;">
{{ cell }}
</td>
{% endfor %}
</tr>
{% endfor %}
</table>
</div>
<br/>
<hr/>
<div>
<ul>
{% for book in books %}
<li>
<a href="{% url 'book-detail' book.pk %}">{{ book.nameobject }}</a>
</li>
{% endfor %}
</ul>
</div>
<br/>
<hr/>
<div>
<table>
<thead>
<tr>
<th>ОМСУ</th>
<th>Наименование объекта</th>
<th>Тип объекта</th>
<th>Объём финансирования</th>
<th>Подрядчик</th>
</tr>
</thead>
<tbody>
{% for book in books %}
<tr>
<td>{{ book.city }}</td>
<td >
<a href="{% url 'book-detail' book.pk %}">{{ book.nameobject }}</a>
</td>
<td>{{ book.typeobject }}</td>
<td>{{ book.budget }}</td>
<td>{{ book.podryadchik }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>title</title>
</head>
<body>
<div>
<form method="POST" class="post-form">
{% csrf_token %} {{formone.as_p}}
<button type="submit" class="button">Отправить</button>
</form>
</div>
</body>
</html>
-----
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>title</title>
</head>
<body>
<div>
<form method="POST" class="post-form">
{% csrf_token %} {{form_2.as_p}}
<button type="submit" class="button">Отправить</button>
</form>
</div>
<div>
{{ book }}
</div>
</body>
</html>
Good day!
I identified some problems with your code:
You're overwriting the context in the "book" view
You're not linking the FK to the specific object
The form doesn't know which object it should be associated with
Here's the fixed code, hope it helps.
views.py:
def book(request, pk):
book_obj = get_object_or_404(ArkiObject_1, pk=pk)
if request.method == 'POST':
form_2 = Form_GPR(request.POST)
if form_2.is_valid():
gpr_instance = form_2.save(commit=False)
gpr_instance.name = book_obj # Link to specific object
gpr_instance.save()
return redirect('book-detail', pk=pk)
else:
form_2 = Form_GPR()
context = {
'book': book_obj,
'form_2': form_2
}
return render(request, 'bookdetail.html', context)
forms.py:
class Form_GPR(forms.ModelForm):
class Meta:
model = ArkiGpr
fields = ['work', 'peoples'] # Exclude 'name' field
# OR use exclude = ['name'] if you prefer
bookdetail.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>{{ book.nameobject }}</title>
</head>
<body>
<h2>{{ book.nameobject }}</h2>
<p><strong>City:</strong> {{ book.city }}</p>
<p><strong>Type:</strong> {{ book.typeobject }}</p>
<hr>
<h3>Add GPR Work</h3>
<div>
<form method="POST">
{% csrf_token %}
{{ form_2.as_p }}
<button type="submit">Submit</button>
</form>
</div>
</body>
</html>