Как передать pk подробного вида в fk формы - PullRequest
0 голосов
/ 12 мая 2019

Добрый день, я довольно новичок в Django, и я не уверен, что с этим делать. У меня есть проект Django 2.2 со следующими моделями:

class Equipment(models.Model):
    name = models.CharField(
            max_length=15,
            unique=True,
            verbose_name='asset name')
    asset_cat = models.ForeignKey('category',on_delete=models.PROTECT,verbose_name='asset category')
    asset_loc = models.ForeignKey('location',on_delete=models.PROTECT,verbose_name='asset location')
    state = models.ForeignKey('status',on_delete=models.PROTECT,verbose_name='status')

    brand = models.CharField(
            max_length=15,
            unique=False,
            blank=True)

    model = models.CharField(
            max_length=12,
            unique=False,
            blank=True,
            verbose_name='model number')

    def __str__(self):
        return "{}".format(self.name)

    def get_absolute_url(self):
        return reverse('equipment-detail', args=[str(self.id)])

    class Meta:
        ordering = ['asset_cat', 'name']
        verbose_name_plural = 'pieces of equipment'


class Action(models.Model):
    name = models.ForeignKey('equipment',on_delete=models.PROTECT,verbose_name='asset name',blank=False)

    dt = models.DateTimeField(
            auto_now_add=True,
            verbose_name='date and time of incident')

    incident = models.TextField(
            blank=True,
            null=True)

    CHANGE = 'CHANGE'
    SERVICE = 'SERVICE'
    ACTION_CHOICES = (
            (CHANGE, 'CHANGE'),
            (SERVICE, 'SERVICE')
    )

    act = models.TextField(
            blank=True,
            choices=ACTION_CHOICES,
            null=True,
            verbose_name='action taken')

    act_detail = models.TextField(
            verbose_name='action detail',
            blank=False)

    result = models.TextField(
            blank=True,
            null=True)

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse('service-detail', args=[str(self.id)])

    class Meta:
        ordering = ['-dt']
        verbose_name_plural = 'service calls'

У меня есть подробности оборудования, как это:

class EquipmentDetailView(generic.DetailView):
    model = Equipment
    template_name = 'equipment_detail.html'

    def get_context_data(self, **kwargs):
        context = super(EquipmentDetailView, self).get_context_data(**kwargs)

        return context

В подробном представлении есть две кнопки: редактировать и обслуживать.Если я нажимаю «Изменить», у меня появляется форма модели, которая позволяет мне успешно редактировать этот экземпляр модели «Оборудование».
Однако, когда я нажимаю кнопку «Сервис», появляется моя форма для создания экземпляра модели «Действие», но когда яотправить это говорит мне, что нулевое значение в name_id нарушает ненулевое ограничение.
Похоже, мой вопрос заключается в том, как я могу передать equipment.id из представления «Сведения об оборудовании» в action.name формы действия action и сохранить формуконцепция кнопки обслуживания?

Форма действия:

class ServiceForm(forms.ModelForm):

class Meta:
    model = Action
    fields = ['incident', 'act_detail', 'result']

Вид действия (фактически службы):

class EquipmentServiceView(generic.CreateView):
template_name = 'equipment_service.html'
form_class = ServiceForm
queryset = Action.objects.all()

1 Ответ

0 голосов
/ 13 мая 2019

Предполагая, что вы не хотите использовать простейшее решение, включив name в поля формы и настроив URL как:
/equipment/<id> - подробный вид оборудования
/service - сервис (или действие) создать представление

Существует несколько способов передачи оборудования id:

1) От URL
Мы собираемся изменить URL, чтобы принять equipment_id. Это означает, что вместо /service у вас будет URL /equipment/<equipment_id>/service.
Вероятно, лучшее решение - вы будете использовать URL в соответствии с архитектурой REST и будете иметь очень четкую структуру. Клиент может получить доступ к странице из любого места (например, просто скопировать ссылку вставки из почты), и она будет работать.

urls.py:

urlpatterns = [
    path('equipment/<int:pk>', EquipmentDetailView.as_view(), name='equipment-detail'),
    path('equipment/<int:equipment_pk>/service', EquipmentServiceView.as_view(), name='service-create')
]

Ваша сервисная кнопка должна выглядеть так: <a href="{% url 'service-create' object.pk %}">service</a>

и, наконец, ваш взгляд:

class EquipmentServiceView(CreateView):
    template_name = 'equipment_service.html'
    form_class = ServiceForm
    queryset = Action.objects.all()

    def form_valid(self, form):
        equipment_pk = self.kwargs['equipment_pk']
        equipment = get_object_or_404(Equipment, pk=equipment_pk)
        self.object = form.save(commit=False)
        self.object.name = equipment
        self.object.save()
        return super().form_valid(form)

2) Данные сеанса
Если вы хотите сохранить сервисный URL без добавления equipment_id, вы можете сохранить идентификатор оборудования либо в данных сеанса (на вашем сервере), либо в файлах cookie (на клиенте). Это не совсем хорошо - клиент должен перейти на EquipmentDetailView до создания Service, но это сохранит ваши URL без изменений.

views.py:

class EquipmentDetailView(DetailView):
    model = Equipment
    template_name = 'equipment_detail.html'

    def get(self, request, *args, **kwargs):
        response = super().get(request, *args, **kwargs)
        request.session['last_equipment_pk'] = self.object.pk
        return response


class EquipmentServiceView(CreateView):
    template_name = 'equipment_service.html'
    form_class = ServiceForm
    queryset = Action.objects.all()

    def form_valid(self, form):
        equipment_pk = self.request.session.get('last_equipment_pk')
        equipment = get_object_or_404(Equipment, pk=equipment_pk)
        self.object = form.save(commit=False)
        self.object.name = equipment
        self.object.save()
        return super().form_valid(form)

P.S .: name - неправильное имя поля для ForeignField - должно быть что-то вроде equipment или около того. Эти метки обычно ассоциируются с CharField и должны быть строками.

...