pythondjangodjango-countries

How to set initial value from a model's custom field in a ModelForm in Django


I want the PestReport country to be automatically set in the ModelForm but keep getting the following error using the code below:

TypeError at /countries/italy/pestreports/create/
pest_report_create() got an unexpected keyword argument 'country'

I will also eventually need to make sure that the user can only add pest reports of a country that is the same as their profile's country. I'm using django-countries.

How can I set the URL's keyword argument to the form automatically (the user should not be able to select the country) in the code below?

urls.py

from django.conf.urls import patterns, include, url
from .ippc.views import pest_report_create

urlpatterns = patterns("",
    # pest report add
    url(r'^countries/(?P<country>[\w-]+)/pestreports/create/$',
        view=pest_report_create,
        name='pest-report-create'),
)

models.py:

from django.db import models
from django import forms
from django_countries.fields import CountryField
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.models import User

class IppcUserProfile(models.Model):
     user = models.OneToOneField("auth.User")
     country = CountryField(_("Country"))

class PestReport(models.Model):
    country = CountryField(_("Country"))
    author = models.ForeignKey(User, related_name="pest_report_author")

class PestReportForm(forms.ModelForm):

class Meta:
    model = PestReport

views.py:

from .models import UserProfile, PestReport, PestReportForm
from django.template import RequestContext
from django.shortcuts import render_to_response, get_object_or_404, redirect

def pest_report_create(request):
if request.method == "POST":

    form = form(request.POST, instance=PestReport())

    user = request.user
    author_id = user.id

    profile_user = request.profile_user
    country = profile_user.country

    if form.is_valid():
        new_pest_report = form.save(commit=False)
        new_pest_report.author_id = author_id
        new_pest_report.country = country
        form.save()
        return HttpResponseRedirect('/thank-you/')
else:
    form = form(instance=PestReport())
return render_to_response('countries/pest_report_create.html', {'form': form},
    context_instance=RequestContext(request))

UPDATED views.py function (now works) thanks to Peter Tinkler's answer:

def pest_report_create(request, country):

    user = request.user
    author = user
    country=user.get_profile().country

    form = PestReportForm(request.POST or None)

    if request.method == "POST":
        if form.is_valid():
            new_pest_report = form.save(commit=False)
            new_pest_report.author = request.user
            new_pest_report.author_id = author.id
            form.save()
            return redirect("pest-report-detail", country=country, year=new_pest_report.publish_date.strftime("%Y"), month=new_pest_report.publish_date.strftime("%m"), slug=new_pest_report.slug)
    else:

        form = PestReportForm(initial={'country': country}, instance=PestReport())

    return render_to_response('countries/pest_report_create.html', {'form': form},
        context_instance=RequestContext(request))

countries/template/pest_report_create.html:

{% extends "base.html" %}

{% block main %}

<form class="customform" method="POST" action="">
    {% csrf_token %}
    {{ form.non_field_errors }}
    {{ form.as_p }}
    <input type="submit" value="Submit />
</form>

{% endblock %}

Solution

  • Your URL has a parameter:

    (?P<country>[\w-]+)
    

    that it is trying to pass to your view, but your view isn't accepting that parameter.

    def pest_report_create(request):
    

    should be

    def pest_report_create(request, country):
    

    You'll then want to pass the country across in the initial data for the form:

    form = PestReportForm(inital={'country': country}
    

    I'd also recommend not defining your forms in the models module