How to pass pk through URL to CreateView

1,245 views
Skip to first unread message

Sam Hefer

unread,
Feb 15, 2020, 3:19:04 AM2/15/20
to Django users
Hi,

I'm trying to figure out how to fill a form field in the background using form_valid. However, everything I've tried doesn't work.

As you can see in the model, there is a job field with a foreign key to Job.

class JobDocket(models.Model):
EQUIPMENT_TYPE = (
('1', 'Air Conditioning'),
('2', 'Heating/Heat-Pump'),
('3', 'Refrigeration'),
('4', 'Ventilation/Extraction'),
('5', 'Electrical/Controls'),
)

job = models.ForeignKey(Job, on_delete=models.CASCADE)
technician = models.ForeignKey(User, on_delete=models.CASCADE)
site_equipment = models.CharField(choices=EQUIPMENT_TYPE, max_length=50, default='1')
date = models.DateField(default=date.today())
start_time = models.TimeField()
end_time = models.TimeField()
rate = models.FloatField(default=80.00)
mileage = models.IntegerField()
description = models.CharField(max_length=1000, help_text='Description of work carried out', blank=False)
created = models.DateTimeField(default=now, blank=True)

def total_time_spent(self):
start_hour = self.start_time.hour
end_hour = self.end_time.hour
start_min = self.start_time.minute
end_min = self.end_time.minute
total_hours = str(end_hour - start_hour)
total_min = str(end_min - start_min)
total_time = total_hours + " hours" " and " + total_min + " minutes"
return total_time

def total_labour_price(self):
start_hour = self.start_time.hour
end_hour = self.end_time.hour
start_min = self.start_time.minute
end_min = self.end_time.minute
total_hours = end_hour - start_hour
total_min = end_min - start_min
total_time = total_hours + total_min/60
labour_price = total_time * self.rate
return labour_price

def __str__(self):
return str(self.technician)

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


In the View, I'm trying to get the pk for the job to automatically fill the field so that the logged in user doesn't have to.

class JobDocketCreate(CreateView):
    model = JobDocket
    form_class = JobDocketForm
    template_name = 'jobs/job_docket_create.html'

    def get_success_url(self):
        return reverse('jobs:my_job_dockets')

    def form_valid(self, form):
        form.instance.technician = self.request.user
        # form.instance.job_id = Job.objects.get(pk=self.kwargs['job_id'])
         # print(form.instance.job_id)
        return super(JobDocketCreate, self).form_valid(form)

    def get_initial(self):
        Job.objects.get(pk=self.kwargs.get('job_id'))
        initial = super(JobDocketCreate, self).get_initial()
        initial['job'] = Job.objects.get(pk=self.kwargs['job_id'])
        print(initial)
        return initial

I've tried passing the pk of the job through the URL like so;

path('<int:job_id>/jobdocketcreate/', JobDocketCreate.as_view(), name='create_job_docket'),

I have the template link referencing the job like this;

<a class="tg-btn" href="{% url 'jobs:create_job_docket' job.pk %}">Add Job Docket</a>


But I can't get it to work, the error I keep getting is;

NoReverseMatch at /jobs/1/jobdocketcreate/

Reverse for 'create_job_docket' with arguments '('',)' not found. 1 pattern(s) tried: ['jobs\\/(?P<job_id>[0-9]+)\\/jobdocketcreate\\/$']

Has anyone got experience making this work? How did you do it?

Here is the Job model if you need it;

class Job(models.Model):
    JOB_TYPE = (
        ('1', 'Service'),
        ('2', 'Repair'),
        ('3', 'Quotation'),
        ('4', 'Consultation'),
        ('5', 'Report'),
        ('6', 'Design'),
    )

    ACCOUNT_TYPE = (
        ('1', 'Existing Customer'),
        ('2', 'Charge to Account'),
        ('3', 'New Customer'),
        ('4', 'Pre-Paid/C.O.D'),
        ('5', 'Issued and Acc App'),
    )

    company_name = models.ForeignKey(Company, related_name='jobs', verbose_name="Company Name", on_delete=models.CASCADE)
    contact_person = models.CharField(max_length=50)
    contact_number = models.IntegerField()
    contact_person_email = models.EmailField(max_length=100, blank=True, null=True)
    site_address = models.CharField(max_length=100)
    job_type = models.CharField(choices=JOB_TYPE, max_length=50, default='1')
    account_type = models.CharField(choices=ACCOUNT_TYPE, max_length=50, default='1')
    job_details = models.CharField(max_length=1000)
    created = models.DateTimeField(default=now, blank=True)

    def __str__(self):
        return str(self.company_name)

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

And the form:

class JobDocketForm(forms.ModelForm):
    description = forms.CharField(max_length=1000, widget=forms.Textarea)
    date = forms.DateField(widget=DatePicker)
    start_time = forms.TimeField(widget=TimePicker)
    end_time = forms.TimeField(widget=TimePicker)

    class Meta:
        model = JobDocket
        exclude = 'rate', 'created', 'technician', 'job',
        fields = (
            'site_equipment', 'date', 'start_time', 'end_time', 'mileage', 'description'
        )


I've looked on StackOverflow for solutions like in the links below, but they don't work.


I would really appreciate some help.

Thanks,
Sam


Phil Kauffman

unread,
Feb 18, 2020, 2:20:32 PM2/18/20
to Django users
Hello,

Did you get any headway on this issue? I'm a novice Django user but was thinking of doing something similar with my code for a project I'm working on. I'm struggling with reverse lookup on foreign key.

Have you had any issues doing reverse lookup on FK?

For example in a view if you wanted to filter the Jobs class by Company_Name, by using a pk, is that working for you?



Thanks

Farai M

unread,
Feb 18, 2020, 7:47:09 PM2/18/20
to django...@googlegroups.com
It should work two issue
1.Url is not matching your need to visit that is where you are getting that reverse error.
2.To pull that value through kwargs you need to use the get request so override the get method otherwise it should work fine.

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/5660cc9d-7c97-41c8-b70d-fa11cd5037ed%40googlegroups.com.

Sam Hefer

unread,
Feb 18, 2020, 11:00:30 PM2/18/20
to django...@googlegroups.com
Hi Phil,

I did find a solution to my query.

Have a look at my post on stackoverflow: 

https://stackoverflow.com/a/60273100/7063031

Thanks,
Sam

On 19/02/2020, at 3:21 AM, Phil Kauffman <kauffm...@gmail.com> wrote:


--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages