pythondjangodjango-formsdetailviewcreate-view

Django CreateView object.id in get_succes_url pk(id) is NONE and then after redirecting to another URL it prints out created entry ID


I have a problem that I just can't figure out. After creating a work order I want to redirect to the detail page of that work order. Here is my models.py

class Radni_nalozi(models.Model):
    Klijent = models.ForeignKey(Klijenti, on_delete=models.CASCADE)
    Pacijent = models.CharField(max_length=100)
    Rok_isporuke = models.DateField()
    Cijena = models.FloatField(default=0)
    Napomene = models.CharField(max_length=400,blank=True)
    Zaduzenja = models.CharField(max_length=400,blank=True)
    Status = models.CharField(max_length=50, choices=STATUS_CHOICES, default = "OTVOREN")
    Aktivan = models.BooleanField(default=True)

    def __str__(self):
       return f"{self.id} - {self.Klijent}, {self.Pacijent}"

And here is my model form:

class RadniModelForm(BSModalModelForm):
    class Meta:
        model = Radni_nalozi
        fields = ["Klijent","Pacijent","Rok_isporuke","Napomene","Zaduzenja"]
        labels = {"Klijent":"Klijent: ", "Pacijent":"Pacijent: ", "Rok_isporuke":"Rok isporuke: ", "Napomene":"Napomene: ","Zaduzenja":"Zaduženja: "}
        widgets = {'Rok_isporuke': DatePickerInput(options={
                        "locale":"en-gb",
                    })}

I want to create a new work order and I'm using django BSModalCreateView. Here is my views.py:

class RadniCreateView(LoginRequiredMixin,BSModalCreateView):
    template_name = 'app/radni_nalozi/dodaj_rn.html'
    form_class = RadniModelForm


    def get_form(self):
        form = super(RadniCreateView,self).get_form() #instantiate using parent
        form.fields['Klijent'].queryset = Klijenti.objects.filter(Aktivan=1)
        return form

    def get_context_data(self, **kwargs):
        context = super(BSModalCreateView, self).get_context_data(**kwargs)
        context['title'] = 'NOVI RADNI NALOG'
        context['gumb'] = 'KREIRAJ'
        return context

    def get_success_url(self):
        print(self.object.pk)
        return reverse_lazy('detalji_rn', kwargs={'pk': self.object.pk})

Here is urls.py:

path('radni_nalozi', views.Radni_nalozi_view.as_view(), name='radni_nalozi'),
    path('radni_nalozi_arhiva', views.Radni_nalozi_arhiva_view.as_view(), name='radni_nalozi_arhiva'),
    path('dodaj_rn', views.RadniCreateView.as_view(), name='dodaj_rn'),
    path('radni_nalozi/details_rn/<pk>', views.RadniDetailView.as_view(), name="detalji_rn"),
    path('radni_nalozi/update/<pk>', views.RadniUpdateView.as_view(), name="update_rn"),
    path('radni_nalozi/delete/<pk>', views.RadniDeleteView.as_view(), name="delete_rn"),

The command print(self.object.pk) returns NONE although the object is created. If I put some other hardcoded value in reverse_lazy function (for example number 13) then my view executes, it redirects to the hardcoded value and prints out command print(self.object.pk) two times, first with value NONE and then with the value of just created entry?

How can I access the pk of the created entry before the view is redirected so I could redirect to a detail page of that created entry (work order)?

EDIT dodaj_rn.html:

<link rel="stylesheet" href="{% static 'css/forma_add.css' %}">
<div class="container novi_rn">

  <form method="post" action="" class="js-quote-request-form form_dodavanje"" id="quoteForm">
    {% csrf_token %}


   <div class="modal-header">
      <h4 class="modal-title">{{ title }}</h4>
      <!-- <button type="button" class="close" data-dismiss="modal" aria-label="Close">
        <span aria-hidden="true">&times;</span>
      </button> -->
    </div>

    <div class="modal-body">

      {% for field in form %}
        <div class="form-group{% if field.errors %} invalid{% endif %}">
          <label for="{{ field.id_for_label }}">{{ field.label }}</label>
          {{ field }}
          {% for error in field.errors %}
            <p class="help-block">{{ error }}</p>
          {% endfor %}
        </div>
      {% endfor %}
    </div>

    <div class="modal-footer">
      <!-- <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> -->
      <button type="submit" class="btn btn-primary btn-lg">{{ gumb}}</button>
    </div>
  </form>
</div>

EDIT JS script for triggering modal form for creating new entry:

<script type="text/javascript">
$(document).ready(function() {

    $("#create-rn").modalForm({
        formURL: "{% url link %}"
    });

});
</script>

EDIT: This is my forms.py for RadniModelForm. After I changed BSModalModelForm to forms.ModelForm and BSModalCreateView to only CreateView, now the entry is created and I get an object.id but the view won't redirect to a detail page. I get errors in the console that you can see in the bottom.

class RadniModelForm(ModelForm):
    class Meta:
        model = Radni_nalozi
        fields = ["Klijent","Pacijent","Rok_isporuke","Napomene","Zaduzenja"]
        labels = {"Klijent":"Klijent: ", "Pacijent":"Pacijent: ", "Rok_isporuke":"Rok isporuke: ", 
                  "Napomene":"Napomene: ","Zaduzenja":"Zaduženja: "}
        widgets = {'Rok_isporuke': DatePickerInput(options={
                        "locale":"en-gb",
                    })}

EDIT: When I changed RadniCreateView class from BSModalCreateView to CreateView and RadniModelForm class from BSModalModelForm to ModelForm (not forms.ModelForm) the redirecting works. But the new entry is created two times, and the view redirects me to the last one.


Solution

  • EDIT:

    Ok, I understand the problem now. Your library is working with modals. So, urls and templates of "createview" and "updateview" are auxiliary for the proper functioning of modals. With this library, It has no sense the "success_url" because the idea of a modal is to be integrated in a parent template.

    If you want to redirect your user to another url different from the original one, change the class of "RadniCreateView":

    From this:

    class RadniCreateView(LoginRequiredMixin,BSModalCreateView):
    

    To this:

    class RadniCreateView(LoginRequiredMixin,CreateView):
    

    OLD ANSWER:

    It seems that when get_success_url() is called the object cannot be obtained. I don't see any errors in the code, but I don't understand the usefulness of this line:

    context = super(BSModalCreateView, self).get_context_data(**kwargs)
    

    By changing the super() of the context you may be looking for the object in the wrong class. Maybe it works if you change it for this one:

    context = super(RadniCreateView, self).get_context_data(**kwargs)