I am attempting to access ForeignKeys in Class Based Views CreateView. I would like to be able to dynamically set initial values in CBV from ForeignKeys and also dynamically set template links from ForeignKeys.
These two questions (1. initial values, 2. template links) may be solved in similar methods, or perhaps by different methods... I'm still learning. Perhaps the first question can be solved within views.py
and the second question can be solved with template syntax in ingredient_form.html
?
I've seen questions on SO setting initial values from users (self.request.user
), but not from just a normal foreign key in models.py
.
I'm going through django-by-errors, and attempting to add extra features to expand my django knowledge.
My question specifically centers on views.py:IngredientAddView(CreateView)
, on
ingredient_form.html
, and on urls.py:'recipe-detail'
& 'ingredient-add
'.
When I view a 'recipe-detail'
, I can click a link to 'ingredient-add'
. I would like 'ingredient-add'
to "know" which recipe clicked to it, and be able to set this recipe as the initial value (my attempt within views.py:IngredientAddView:get_initials(self)
does not work), and also be able to link back to this recipe (my attempt within ingredient_form.html:{% comment %}
does not work).
Would appreciate any assistance.
models.py
class Food(models.Model):
name=models.CharField(max_length=20,unique=True)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('food-detail',kwargs={'pk':self.pk})
class Recipe(models.Model):
title=models.CharField(max_length=80,unique=True)
slug=models.SlugField(max_length=80,unique=True)
description=models.TextField(blank=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('recipe-detail',kwargs={'slug':self.slug})
class Ingredient(models.Model):
recipe=models.ForeignKey(Recipe)
food=models.ForeignKey(Food)
def __str__(self):
return '%s (%s)' % (self.food, self.recipe)
views.py
class FoodListView(ListView):
model=Food
class FoodDetailView(DetailView):
model=Food
class FoodCreateView(CreateView):
model=Food
class RecipeListView(ListView):
model=Recipe
class RecipeDetailView(DetailView):
model=Recipe
class RecipeCreateView(CreateView):
model=Recipe
class RecipeUpdateView(UpdateView):
model=Recipe
class IngredientAddView(CreateView):
model=Ingredient
# def get_context_data(self,**kwargs):
# context=super(IngredientAddView,self).get_context_data(**kwargs)
# context['foreign']=self.request.session.get('slug')
def get_initials(self):
return {
'recipe':self.request.session.get('recipe')
}
urls.py
from .views import FoodListView, FoodDetailView, FoodCreateView, RecipeListView, RecipeDetailView, RecipeCreateView, RecipeUpdateView, IngredientAddView
urlpatterns=patterns('',
url(r'^$',RecipeListView.as_view(),name='recipe-list'),
url(r'^(?P<slug>[-\w]+)$',RecipeDetailView.as_view(),name='recipe-detail'),
url(r'^(?P<slug>[-\w]+)/edit$',RecipeUpdateView.as_view(),name='recipe-edit'),
url(r'^(?P<slug>[-\w]+)/add_ingredient/$',IngredientAddView.as_view(),name='ingredient-add'),
url(r'^new/$',RecipeCreateView.as_view(),name='recipe-create'),
url(r'^food/$',FoodListView.as_view(),name='food-list'),
url(r'^food/(?P<pk>[\d]+)$',FoodDetailView.as_view(),name='food-detail'),
url(r'^food/create/$',FoodCreateView.as_view(),name='food-create'),
)
recipe_detail.html
{% extends "base_food.html" %}
{% block title %}{{ recipe }} {% endblock %}
{% block content %}
<h1>{{ recipe }}</h1>
<p>{{ recipe.id }}</p>
<p>{{ recipe.title }}</p>
<br>
<h2>Description</h2>
<p>{{ recipe.description|default:'No description' }}</p>
<h2>Ingredients</h2>
<ul>
{% for ingredient in recipe.ingredient_set.all %}
<li>{{ ingredient }}</li>
{% endfor %}
</ul>
<p><a href="{% url 'ingredient-add' recipe.slug %}">Add ingredient</a></p>
<p><a href="{% url 'recipe-edit' recipe.slug %}">Edit recipe</a></p>
<p><a href="{% url 'recipe-list' %}">Back to recipe list</a></p>
{% endblock %}
ingredient_form.html
{% extends "base_food.html" %}
{% block title %}Add Ingredient{% endblock %}
{% block content %}
<h1>Add Ingredient</h1>
<form method="POST">{% csrf_token %}
{{ form }}
<button type="submit" class="btn btn-primary">Save</button>
</form>
{%comment%} <p><a href="{% url 'recipe-detail' recipe.slug %}">Back to detail</a></p> {%endcomment%}
<p><a href="{% url 'recipe-list' %}">Back to recipe list</a></p>
{% endblock %}
You need to instantiate your recipe:
class IngredientAddView(CreateView):
model=Ingredient
def get_initial(self):
recipe = get_object_or_404(Recipe, slug=self.kwargs.get('slug'))
return {
'recipe':recipe,
}