Django 3 - CreateView с начальным полем ForeignKey - PullRequest
1 голос
/ 28 марта 2020

Я пытаюсь создать приложение "рейтинг ресторана" на Django 3. Я настроил следующие модели:

# Table storing the different restaurants
class Restaurant(models.Model):
    restaurant_name = models.CharField(max_length=200, unique=True)
    restaurant_address = models.CharField(max_length=200)
    restaurant_street_number = models.CharField(max_length=10)
    restaurant_city = models.CharField(max_length=200)
    restaurant_cuisine_type = models.CharField(max_length=200)
    def __str__(self):
        return self.restaurant_name + ' - ' + self.restaurant_city


class UserReview(models.Model):
    # Defining the possible grades
    Grade_1 = 1
    Grade_2 = 2
    Grade_3 = 3
    Grade_4 = 4
    Grade_5 = 5
    # All those grades will sit under Review_Grade to appear in choices
    Review_Grade = (
        (1, '1'),
        (2, '2'),
        (3, '3'),
        (4, '4'),
        (5, '5')
    )
    restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE)
    user_review_grade = models.IntegerField(default=None, choices=Review_Grade) # default=None pour eviter d'avoir un bouton vide sur ma template
    user_review_comment = models.CharField(max_length=1500)
    def get_absolute_url(self):
        return reverse('restaurants:reviews', args=[self.id])

Это форма, которую я использую:

# Form for user reviews per restaurant
class UserReviewForm(forms.ModelForm):
    class Meta:
        model = UserReview
        #  restaurant = forms.ModelChoiceField(queryset=Restaurant.objects.filter(pk=id))
        fields = [
            'restaurant',
            'user_review_grade',
            'user_review_comment'
        ]
        widgets = {
            'restaurant': forms.HiddenInput,
            'user_review_grade': forms.RadioSelect,
            'user_review_comment': forms.Textarea
        }
        labels = {
            'user_review_grade': 'Chose a satisfaction level:',
            'user_review_comment': 'And write your comments:'
        }

Вот мои URL:

app_name = 'restaurants'
urlpatterns = [
    # ex: /restaurants/
    path('', views.index, name='index'),

    # ex: /restaurants/15
    path('<int:restaurant_id>/', views.details, name='details'),

    # ex: /restaurants/test
    path('<int:restaurant_id>/test', views.Test.as_view(), name='test')

]

Шаблон:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>TEST</title>
</head>
<body>
<h1>Write a review for this restaurant:</h1>
<form method="post">
    {% csrf_token %}
    <input type="Hidden" name="restaurant" value="{{restaurant.restaurant_id}}">
    {{ form.as_p }}
    <br>
    <input type="submit" value="Submit">
</form>
</body>
</html>

И, наконец, мое мнение:

# Test class to be renamed posts reviews as it should
class Test (CreateView):
    template_name = 'restaurants/TEST.html'
    form_class = UserReviewForm

    # Get the initial information needed for the form to function: restaurant field
    def get_initial(self, restaurant_id, *args, **kwargs):
        initial = super(Test, self).get_initial(**kwargs)
        initial['restaurant'] = 9
        return initial()

    # Post the data into the DB
    def post(self, request, *args, **kwargs):
        form = UserReviewForm(request.POST)
        if form.is_valid():
            review = form.save()
            print(review)  # Print so I cna see in cmd prompt that something posts as it should
            review.save()
        return render(request, 'restaurants/reviews.html', {'form': form})

У меня возникла проблема, когда Я определяю initial как целое число (скажем, 9 - так как я проверял, действительно ли моя форма публиковала), он без проблем публикует обзор в БД для ресторана с id = 9. Однако я не могу его получить restaurant_id автоматически заполняется в зависимости от того, какую страницу ресторана мы посещаем.

Я попробовал следующее, а также несколько других «хитростей», найденных здесь и там, но, похоже, ничего не помогло ...

# Test class to be renamed later IF it works...
class Test (CreateView):
    template_name = 'restaurants/TEST.html'
    form_class = UserReviewForm

    # Get the initial information needed for the form to function: restaurant field
    def get_initial(self, restaurant_id, *args, **kwargs):
        restaurant = get_object_or_404(Restaurant, pk=restaurant_id)
        initial = super(Test, self).get_initial(**kwargs)
        initial['restaurant'] = self.request.restaurant.pk  
        return initial()

    # Post the data into the DB
    def post(self, request, *args, **kwargs):
        form = UserReviewForm(request.POST)
        if form.is_valid():
            review = form.save()
            print(review)  # Print so I cna see in cmd prompt that something posts as it should
            review.save()
        return render(request, 'restaurants/reviews.html', {'form': form})

Буду признателен за любую помощь, чтобы указать мне правильное направление:)

1 Ответ

0 голосов
/ 28 марта 2020

Вы можете получить restaurant_id в параметрах URL с помощью self.kwargs['restaurant_id']. Итак, вы можете:

class Test(CreateView):

    def get_initial(self, *args, **kwargs):
        initial = super(Test, self).get_initial(**kwargs)
        <b>initial['restaurant'] = self.kwargs['restaurant_id']</b>  
        return initial

    # &hellip;

При этом довольно странно хранить это в любом случае. Вы можете просто установить это, когда форма действительна. Итак, мы определяем форму без ресторана:

class UserReviewForm(forms.ModelForm):
    class Meta:
        model = UserReview
        fields = [
            'user_review_grade',
            'user_review_comment'
        ]
        widgets = {
            'user_review_grade': forms.RadioSelect,
            'user_review_comment': forms.Textarea
        }
        labels = {
            'user_review_grade': 'Chose a satisfaction level:',
            'user_review_comment': 'And write your comments:'
        }

, а в CreateView мы затем устанавливаем restaurant этого экземпляра:

class Test(CreateView):
    template_name = 'restaurants/TEST.html'
    model = UserReview
    form_class = UserReviewForm
    success_url = &hellip;

    def form_valid(self, form):
        <b>form.instance.restaurant_id = self.kwargs['restaurant_id']</b>
        super().form_valid(form)

Здесь необходимо указать success_url, на который он будет перенаправлен в случае успешной отправки. В случае успешного выполнения POST необходимо выполнить перенаправление для реализации шаблона Post / Redirect / Get [wiki] .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...