2

In short: I want to autofill form's foreign variable:

TL;DR
Here is project link. I have a model:

from django.db import models
from django.urls import reverse
# Create your models here.

class School(models.Model):
    name = models.CharField(max_length=256)
    principal = models.CharField(max_length=256)
    location = models.CharField(max_length=256)

    def __str__(self): return self.name

    def get_absolute_url(self):
        return reverse('basic:detail', kwargs={'pk': self.pk})

class Student(models.Model):
    name = models.CharField(max_length=256)
    age = models.PositiveIntegerField()
    school = models.ForeignKey(School, on_delete=models.CASCADE, related_name='students')

    def __str__(self): return self.name

    def get_absolute_url(self):
        return reverse('basic:detail', kwargs={'pk': self.school.pk})

and url.py:

urlpatterns = [
    path('', views.Index.as_view(), name='index'),
    path('list/', views.SchoolListView.as_view(), name='list'),
    path('<int:pk>/', views.SchoolDetailView.as_view(), name='detail'),
    path('create/', views.SchoolCreateView.as_view(), name='create'),
    path('update/<int:pk>/', views.SchoolUpdateView.as_view(), name='update'),
    path('delete/<int:pk>/', views.SchoolDeleteView.as_view(), name='delete'),

    path('student/create/', views.StudentCreateView.as_view(), name='creates'),
    path('student/create/<int:pk>', views.StudentCreateView.as_view(), name='createspk'),
    path('student/update/<int:pk>/', views.StudentUpdateView.as_view(), name='updates'),
    path('student/delete/<int:pk>/', views.StudentDeleteView.as_view(), name='deletes'),


]

and i am using CBV:

class StudentCreateView(CreateView):
    try:
        print("*******")
        print(pk)
    except:
        pass
    model = Student
    fields = ["name", "age", 'school']

I added a link to create student in school detail as shown below: screenshot

When I click create new with pk, I am passing pk of School and I go to: scrreenshot2

As you can see School field is dropdown with nothing selected, I would like to make that the school default value to be the school from where it is called, in this case xavier school for gifted childrens.

My create student code is:

{% extends "basic/base.html" %}

{% block content %}
<h1>
    {% if not form.instance.pk %}
    Create Student:
    {% else %}
    Update Student:
    {% endif %}
</h1>
<form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <input type="submit" value="Submit" class="btn btn-primary">
</form>
{% endblock content %}

How can I do that? Thanks in advance.

unnobtainium
  • 528
  • 1
  • 5
  • 15
  • This can be done in the `__init__` function of your form. Could you post your form code? – Tim Aug 28 '18 at 13:32
  • I am not using one. Because it is class based view. It is generating implicitly. – unnobtainium Aug 29 '18 at 04:09
  • Sorry, I missed that. I think it should be enough for you to add the `get_initial()` method to your view. Let me write together an answer with that. – Tim Aug 29 '18 at 08:20

1 Answers1

1

Try modifying your view like so:

class StudentCreateView(CreateView):
    try:
        print("*******")
        print(pk)
    except:
        pass
    model = Student
    fields = ["name", "age", 'school']

    def get_initial(self):
        initial = super(StudentCreateView, self).get_initial()
        initial['school'] = School.objects.get(pk=self.kwargs['pk'])
        return initial

I would additionally recommend to rename the parameter in the url (and then also in the get_initial method) to something like school_pk to make it clear you do not pass a pk for the Student to be created.

Tim
  • 1,272
  • 11
  • 28
  • Thanks man. It work like a charm. get_initial is new to me. One more thing why I am unable to get pk in try block. How can I get that outside function? – unnobtainium Aug 29 '18 at 10:10
  • You can't: Your try block is executed when the code is read by the python compiler an not when the class is instantiated at runtime. If you want to do something with pk when the view is called, you should use the `def dispatch(self, request, *args, **kwargs):`method. https://docs.djangoproject.com/en/2.1/ref/class-based-views/base/#django.views.generic.base.View.dispatch don't forget to call the `super()` method, otherwise this will break your view. – Tim Aug 29 '18 at 15:03
  • And also: the `pk` is not accessible directly, but rather via `self.kwargs['pk']` – Tim Aug 29 '18 at 15:04
  • Got it. Thanks again for your help. – unnobtainium Aug 30 '18 at 04:23
  • I'm getting KeyError, 'pk' – AnonymousUser Sep 23 '21 at 06:45