1

In my app I need to create products in a shop. So I have a model Shop and a model Product. I can see details about my shop in a DetailView ShopDetail. Now I need a CreateView in order to create products, but the url should be /shops/shop-id/products/create/, so I create products inside the shop. I guess it's something like

class ProductCreate(SingleObjectMixin, CreateView):
    model = Product

    def get_object(self, queryset=None):
        return Shop.objects.get(id = self.kwargs['shop_id'])

Am I on the right track? :-D

Nets
  • 141
  • 8
  • Presumably you have a FK relationship from `Product` > `Shop`, so you will need to set that relationship in your `CreateView` in the background (by getting the id from the url and manually assigning the relationship), then make that field hidden in your new form so that when the user creates a new instance, the relationship will be saved. Alternatively, you could set the relationshop when the users POSTs their form and it's validated. – Timmy O'Mahony May 23 '13 at 18:23
  • Hej Timmy. I know I can handle this in form_valid by settings form.instance.shop before saving form data, but I also have to set context data I guess, so I can get the shop name in the template – Nets May 23 '13 at 18:38

2 Answers2

0

No, you're not on the right track: the object returned by get_object should be a instance of the model; in fact, if you override get_object the model attribute becomes irrelevant.

There are a few approaches to this problem, but I would myself probably got for a single DetailView (with the Shop details), and add a form for Product to the template via the get_context_data method. The form's action attribute would, instead of being empty, point to the url to a separate CreateView which would handle the Product creation.

Alternatively you could simply display the Shop details through the get_context_data, which is simpler but mixes concerns (as the DetailView for shop is defined as a CreateView for Product).

Berislav Lopac
  • 16,656
  • 6
  • 71
  • 80
0

I think you need:

from django.shortcuts import get_object_or_404

class ProductCreate(CreateView):
    """Creates a Product for a Shop."""
    model = Product

    def form_valid(self, form):
        """Associate the Shop with the new Product before saving."""
        form.instance.shop = self.shop
        return super(CustomCreateView, self).form_valid(form)

    def dispatch(self, *args, **kwargs):
        """Ensure the Shop exists before creating a new Product."""
        self.shop = get_object_or_404(Shop, pk=kwargs['shop_id'])
        return super(ProductCreate, self).dispatch(*args, **kwargs)

    def get_context_data(self, **kwargs):
        """Add current shop to the context, so we can show it on the page."""
        context = super(ProductCreate, self).get_context_data(**kwargs)
        context['shop'] = self.shop
        return context

I hope it helps! :) You may wish to have a look at what the super-methods do.

(Disclaimer: Shameless self promotion.)

meshy
  • 8,470
  • 9
  • 51
  • 73