@Fedor_PV

Как написать CreateView для модели с ForeignKey?

Здравствуйте, помоги плиз новичку - есть такая модель: страны и города внутри стран, каждый город это Foreign Key для определенной страны. Очень просто создал CreateView для страны, вопросов нет, но не могу создать CreateView для города - мешает Foreign Key. В документации примеров нет - есть только туманный пример про внешний ключ автора

form.instance.created_by = self.request.user

Этот пример не помогает в данном случае. Как быть?

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>
  • Вопрос задан
  • 1472 просмотра
Решения вопроса 1
@Fedor_PV Автор вопроса
В общем вот код, который работает (другие подходы не помогли):

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)
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
@immaculate
Программист-путешественник
Во-первых, соблюдайте, пожалуйста PEP-8 и Django Coding Style. Это уважение к тем, кому приходится читать ваш код. Также, обратите внимание, что обычно модели называются в единственном числе: City, а не Cities. Country, а не Countries.

Во-вторых, при данном использовании CreateView форма создается автоматически. Вам же нужна своя форма, которая будет назначать страну. Создайте форму для City, в конструкторе которой будет сохраняться Country из запроса. А в CreateView вместо атрибута fields используйте form_class для использования вашей формы.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы