F
F
Fedor_PV2018-06-29 06:58:36
Django
Fedor_PV, 2018-06-29 06:58:36

How to write CreateView for model with ForeignKey?

Hello, please help a newbie - there is such a model: countries and cities within countries, each city is a Foreign Key for a specific country. It's very easy to create a CreateView for a country, no questions, but I can't create a CreateView for a city - Foreign Key interferes. There are no examples in the documentation - there is only a vague example about the author's foreign key.
form.instance.created_by = self.request.user
This example does not help in this case. How to be?
models.py

class Countries(models.Model):
....
    country_name=models.CharField(max_length=30, choices=COUNTRY_CHOICE)
....

class Cities(models.Model):
    country=models.ForeignKey(Countries, on_delete=models.CASCADE)
    city_name=models.CharField(max_length=100)
....

urls.ry
path('countries/<int: country_id>/new_city/', login_required(CityCreate.as_view()), name='new_city')

view.py
class CityCreate(CreateView):
    model=Cities
    fields=['city_name', 'tags']
    success_url=reverse_lazy('countries:cities')
    template_name='countries/new_city.html'

def get(self, request, *args, **kwargs):
    self.country=Countries.objects.get(id=self.kwargs['country_id'])
    return super(CityCreate, self).get(request, *args, **kwargs) 

def get_context_data(self, **kwargs):
    context=super(CityCreate, self).get_context_data(**kwargs)
    context['country']=self.country
    return context

def form_valid(self, form):
    form.instance.country=self.country
    return super().form_valid(form)

countries/new_city.html:
country: {{ country }}

<form action="{% url 'countries:new_city' country.id %}" method='post'  class="form">
 {% csrf_token %}

 </form>

Answer the question

In order to leave comments, you need to log in

2 answer(s)
F
Fedor_PV, 2018-07-04
@Fedor_PV

In general, here is the code that works (other approaches did not help):

class CityCreate(CreateView):
    model = Cities
    fields = ['city_name', 'tags']
    template_name = 'countries/new_city.html'

    def get_success_url(self):
        return reverse('countries:cities', args=[self.country.id])

    def get_context_data(self, **kwargs):
        self.country = get_object_or_404(Countries, id=self.kwargs['country_id'])
        kwargs['country'] = self.country
        return super().get_context_data(**kwargs)

    def form_valid(self, form):
        self.country = get_object_or_404(Countries, id=self.kwargs['country_id'])
        form.instance.country = self.country
        messages.success(self.request, 'The city has been added to the list of visited places, thank you') 
        return super().form_valid(form)

E
Eugene, 2018-06-29
@immaculate

First, please follow PEP-8 and Django Coding Style. This is respect for those who have to read your code. Also, note that models are usually referred to in the singular: City, not Cities. Country, not Countries.
Secondly, with this use of CreateView, the form is automatically created. You also need your own form that will assign the country. Create a form for City, in the constructor of which the Country from the request will be stored. And in CreateView, instead of the fields attribute, use form_class to use your form.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question