I am trying to use Django Generic Class-Based Views to build a CRUD interface to a two-model database. I have a working CRUD interface to the parent model, and am stuck trying to get the child Create working. For consistency with other Django examples, take the parent to be Author and the child to be Book. What is the simplest way to allow users to add Books to an Author?
In HTML terms, I think that I want to make a link on the Author detail page that includes the ID of the Author, have that ID be pre-set on the Book form, and then have the Book form processing use that ID as the PK of the Book. But I don't understand how to use Django to make this happen. I have read through https://docs.djangoproject.com/en/1.6/topics/class-based-views/generic-editing/, How do I use CreateView with a ModelForm, How do I set initial data on a Django class based generic createview with request data, and Set initial value to modelform in class based generic views, each of which seems to answer a slightly different question.
Here is the relevant code:
models.py
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
author = models.ForeignKey(Author)
title = models.CharField(max_length=500)
views.py
class BookCreate(CreateView):
form_class = BookForm
def get_success_url(self):
return reverse('myapp:author_read',args=(self.object.author.pk))
forms.py
class BookForm(forms.Modelform):
class Meta:
model = Book
urls.py
url(r'^(?P<pk>d+)/$', AuthorRead.as_view(), name='author_read'),
url(r'^book/create/(?P<author_id>d+)/$', BookCreate.as_view(), name='book_create'),
templates/myapp/author_detail.html
...
<p><a href="{% url 'myapp:book_create' author_id=Author.pk %}">Add a book</a></p>
...
templates/myapp/book_form.html
<form action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Done">
</form>
Questions
1) How do I get the Author ID from the Book page URL to the Author form, and then processed correctly? With the sample code above, the Django debugger shows that it's present in this way:
View function Arguments Keyword arguments URL name
myapp.views.BookCreate () {'author_id': u'1234'} book_create
but I don't understand how to grab that variable out of the ... context? ... and put it into the form.
1a) Can I make it a url parameter instead of part of the URL itself, i.e., book/create?author=1234
instead of book/create/1234/
? Or even make the whole thing a POST so that it's not part of the URL? Which is the best practice, and how is it done?
2) Once the variable is in the form, how can it be present as a hidden input, so that the user doesn't have to see it?
See Question&Answers more detail:
os