How can I use a url parameter(that is a user id <str:pk>) to prepopulate a field in DJANGO form
I'm doing a management application with 2 pages: users(clientes) and a user datail page that contains a user payment history(cheques).
I'm trying to do a create a form in payment history page(cheques.html) to add a new payment, but I'd the Cheque.cliente would be equals to the current user URL. Ex.: if your URL is cheque/5/, the Cheque.cliente should be 5, and when I add a new payment, the payment should be tracked(ForeignKey) to the user 5(each user has many payments).
Resuming: This application has the functions to CRUD all the user(clientes) and all the payments(cheques), but only the add payment(cheque) function isn't working.
VIEWS.py
#CLIENTES
def index(request):
clientes = Cliente.objects.all()
form = ClienteForm()
if request.method == 'POST':
form = ClienteForm(request.POST)
if form.is_valid():
form.save()
return redirect('/')
context = {'clientes':clientes, 'form':form}
return render(request, 'clientes/home.html', context)
#CHEQUES
#THE ERROR IS IN THIS VIEW!
def chequesCliente(request, pk):
cheques = Cheque.objects.filter(id=pk)
nome = Cliente.objects.get(id=pk)
formc = ChequeForm()
if request.method == 'POST':
formc = ChequeForm(request.POST)
print(formc.data['cliente'])
if formc.is_valid():
print(formc.cleaned_data)
formc.save()
return redirect('/')
context = {'cheques':cheques, 'formc':formc, 'nome':nome,}
return render(request, 'clientes/cheques.html', context)
def updateCheque(request, pk):
cheque = Cheque.objects.get(id=pk)
formc = ChequeForm(instance=cheque)
if request.method == 'POST':
formc = ChequeForm(request.POST, instance=cheque)
if formc.is_valid():
formc.save()
return redirect('/')
context = {'formc':formc}
return render(request, 'clientes/update_cheque.html', context)
def deleteCheque(request, pk):
item = Cheque.objects.get(id=pk)
if request.method == "POST":
item.delete()
return redirect('/')
context = {'item':item}
return render(request, 'clientes/delete_cheque.html', context)
URLS.py
path('admin/', admin.site.urls),
path('', views.index, name='lista'),
path('update/<str:pk>/', views.updateCliente, name="update"),
path('delete/<str:pk>/', views.deleteCliente, name="delete"),
path('cheques/<str:pk>/', views.chequesCliente, name="lista_cheques"),
#cliente/CRUD/num_cheque
path('update_cheque/<str:pk>/', views.updateCheque, name="update_cheque"),
path('delete_cheque/<str:pk>/', views.deleteCheque, name="delete_cheque"),
]
MODELS.py
nome = models.CharField(max_length=150)
cpf = models.CharField(max_length=14)
num = models.CharField(max_length=50)
endereco = models.CharField(max_length=150)
cidade = models.CharField(max_length=150)
limite = models.DecimalField(max_digits=9, decimal_places=2)
situacao = models.BooleanField(default=True)
def __str__(self):
return self.nome
class Cheque(models.Model):
cliente = models.ForeignKey(Cliente, on_delete=models.CASCADE, related_name='cheques')
banco = models.CharField(max_length=25)
numero = models.IntegerField(default=0)
valor = models.DecimalField(max_digits=20, decimal_places=2)
emissao = models.DateField()
vencimento = models.DateField()
sem_fundos = models.BooleanField(default=False)
def __str__(self):
return self.banco
FORMS.py
class Meta:
model = Cliente
fields = '__all__'
class ChequeForm(forms.ModelForm):
class Meta:
model = Cheque
fields = '__all__'
exclude = ['cliente',]
TEMPLATES_cheques.HTML
<div id="flex_subheader">
<button type="button" class="my_btn" id="retornar" onclick="location.href='{% url 'clientes:lista' %}'"><span>Retornar</span></button>
<h2>{{ nome }}</h2></div>
<div id="adicionar_cheque" class="criar">
<form method="post" action=".">
{% csrf_token %}
{{ formc.non_field_errors }}
<table>
{{ formc.as_table }}
<input type="submit" id="sub_cheque" value="Confirmar!">
</table>
</form>
</div>
<table class="table table-hover">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Banco</th>
<th scope="col">Número</th>
<th scope="col">Valor</th>
<th scope="col">Emissão</th>
<th scope="col">Vencimento</th>
<th scope="col">Sem Fundos</th>
</tr>
</thead>
<tbody>
{% for cheque in cheques %}
<tr>
<th scope="row">{{ cheque.pk }}</th>
<td>{{ cheque.banco }}</td>
<td>{{ cheque.numero }}</td>
<td>{{ cheque.valor }}</td>
<td>{{ cheque.emissao }}</td>
<td>{{ cheque.vencimento }}</td>
<td>{{ cheque.sem_fundos }}</td>
<td><a href="{% url 'clientes:update_cheque' cheque.id %}" class="my_btn" id="editar">Editar</a></td>
<td><a href="{% url 'clientes:delete_cheque' cheque.pk %}" class="my_btn" id="excluir">Excluir</a></td>
</tr>
{% endfor %}
</tbody>
</table>
</section>
TEMPLATES_clientes.html
<tr>
<th scope="row">{{ cliente.pk }}</th>
<td> <a href="{% url 'clientes:lista_cheques' cliente.id %}"> {{ cliente.nome }} </a></td>
<td>{{ cliente.cpf }}</td>
<td>{{ cliente.num }}</td>
<td>{{ cliente.endereco }}</td>
<td>{{ cliente.cidade }}</td>
<td>{{ cliente.limite }}</td>
<td>{{ cliente.situacao }}</td>
<td><a href="{% url 'clientes:update' cliente.id %}" class="my_btn" id="editar">Editar</a></td>
<td><a href="{% url 'clientes:delete' cliente.id %}" class="my_btn" id="excluir">Excluir</a></td>
</tr>
{% endfor %}
Solution 1:
When saving the form, you can add the parameter commit=False. This will create a objects of the submitted data, but not save it in the database (no primary key exists). On the object you can alter data and when you are done, save the object:
if form.is_valid():
obj = form.save(commit=False) # returns an instance of a model object without pk
obj.field1 = some_value
obj.save() # Save the object to the db