Problem with pk that doesn’t exist yet

Asked

Viewed 120 times

1

I have the following urls:

# urls.py
url(r'^proposal/(?P<pk>\d+)/$', ProposalDetail.as_view(), name='proposal_detail'),
url(r'^contract/(?P<pk>\d+)/$', ContractDetail.as_view(), name='contract_detail'),
url(r'^proposal/edit/contract/$', 'create_contract', name='create_contract_url'),

It means that there is I have /proposal/1/, but in my example I will not have /contract/3/ still, that is to say, /contract/3/ is a contract that does not yet exist, and when there will be pk which may be different from proposal.

# views.py
class ProposalDetail(DetailView):
    template_name = 'core/proposal/proposal_detail.html'
    model = Proposal

To the contract exist I will perform the following function...

def create_contract(request, pk):
    if request.user.is_authenticated:
        proposal = Proposal.objects.get(pk=pk)
        if proposal.status != 'co':
            return HttpResponse('O status do orçamento deve ser concluido.')
        else:
            contractor = proposal.work.customer
            obj = Contract(
                proposal=proposal,
                contractor=contractor
            )
            obj.save()
            proposal.status = 'a'
            proposal.save()
    return redirect('/contract/%d' % obj.id)

... from this button.

# proposal_detail.html
<form class="navbar-form navbar-right" action="." method="get">
    <a class="btn btn-primary" href="{% url 'create_contract_url' proposal.id %}"><i class="icon-edit icon-white"></i> Criar Contrato</a>
</form>

The problem is I’m having trouble controlling pk in the right way.

Question: How do I improve this code in order to inform the pk of proposal in function create_contract and redirect the page to /contract/3, whereas 3 will be a new pk of contract, but he doesn’t exist yet?

2 answers

1

Assuming Contract has a Foreignkey Proposal, you can assign the value at the time of saving, for example:

#models
class Contract(models.Model):
    proposal = models.ForeignKey('Proposal', blank=True)

#views:
def create_contract(request, pk):
    proposal = Proposal.objects.get(pk=pk)
    form = ContractForm(request.POST or None)
    if request.METHOD == 'POST':
        if form.is_valid():
            obj = form.save(commit=False)
            obj.proposal = proposal
            obj.save()
            return redirect('/contract/%d' % obj.id)

    return render(request, "seu_template.html", {'form':form, 'proposal':proposal})

Remembering that it is not very suggestive to use the url pk for two things, in the template you passed the id of Proposal in the url:

{% url 'create_contract_url' proposal.id %}"

And in your view redirect, you’re returning the created contract id:

return redirect('/contract/%d' % obj.id)

It is interesting that you refer to only one thing in your url, if you want the two pk’s, pass the two pk’s in the url.

If every contract refers to a prior, it becomes more intuitive that your contract url is that way:

url(r'^(?P<proposal_id>\d+)/contract/new/$', ContractCreate.as_view(), name='contract_create'),
url(r'^(?P<proposal_id>\d+)/contract/(?P<pk>\d+)/$', ContractUpdate.as_view(), name='contract_edit'),
url(r'^(?P<proposal_id>\d+)/contract/(?P<pk>\d+)/$', ContractDetail.as_view(), name='contract_detail'),

Respecting the idea of Createview, Updateview and Detailview, the system will be much more readable.

https://docs.djangoproject.com/en/1.8/ref/class-based-views/flattened-index/#createview

  • Yes, but I’m not using form, it’s just a button that I click and performs the function. But did you understand what I need about the id that doesn’t exist yet from the contract? I know I messed up the ids a bit, but I need to use the pk of Proposal just to reference me when creating the new contract. And then the redirect is to enter the new contract, when his pk exists.

  • I get it, but you can still use the urls the way I suggested. In both Updateview and Detailview, the Django default uses the "pk" to render the information of an already existing object. You can use the "proposal_id" nomenclature, in the future this will even help in code maintenance. In your view it would be def create_contract(request, proposal_id): .

  • Now I get it. Thank you.

-1


Solved.

@login_required
def create_contract(request, proposal_id):
    if request.user.is_authenticated:
        proposal = Proposal.objects.get(pk=proposal_id)
        if proposal.status != 'co':
            return HttpResponse('O status do orçamento deve ser concluido.')
        else:
            contractor = proposal.work.customer
            contract = Contract(
                proposal=proposal,
                contractor=contractor
            )
            contract.save()
            proposal.status = 'a'
            proposal.save()
    return redirect('/contract/%d' % contract.id)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.