Django редактирует атрибут внешнего ключа через форму родительского объекта - PullRequest
0 голосов
/ 17 октября 2019

Использование:

Python 3.7.3

django 2.2.5

mysql 5.7.27

У меня определены следующие модели:

class Item(models.Model):
...
asset       = models.ForeignKey('Assets', default=None, null=True, on_delete=models.SET_DEFAULT)
...

class Comments(models.Model):
    item = models.ForeignKey('Item', default=None, null=True, on_delete=models.CASCADE)
    comment = models.TextField(max_length=512, default="", blank=True)

class Assets(models.Model):
...
assettag = models.CharField(db_column='AssetTag', unique=True, max_length=10)
...

Я хочу обновить представление, которое позволит мне обновить поля объекта Item, а также предоставит способ редактирования comment или assettag. Я использую представления на основе классов, и у меня определена следующая форма:

class ItemUpdateForm(forms.ModelForm):
...
    Asset = forms.CharField(label="AssetTag",
                            required=False,
                            widget=forms.TextInput(attrs={"placeholder":"Item Inventory Tag",
                                                          "rows":1,
                                                          "cols":7,
                                                       }
                                                )
                         )
...
    class Meta:
        model = Item
        fields = [
            ...,
            'Asset',
            ...,
        ]

    def clean_Asset(self, *args, **kwargs):
        AssetTag = self.cleaned_data.get("Asset")
        if len(AssetTag) != 7:
            raise forms.ValidationError("AssetTag length incorrect")
        if not AssetTag.lower().startswith("dp"):
            raise forms.ValidationError("This is not a valid AssetTag")
        else:
            try:
                _asset = Assets.objects.get(assettag = AssetTag)
            except Assets.DoesNotExist:
                raise forms.ValidationError("Item does not exist")
            self.Asset = _asset
            return self.Asset

ItemFormSet = forms.inlineformset_factory(Item, Comments, ItemUpdateForm, fields=('Comment',), extra=1)

Представление не является причудливым:

class UpdateView(ObjectMixin, generic.UpdateView):

    template_name = some template
    form_class = ItemFormSet

ObjectMixin предоставляет некоторые методы, которые я использовал в нескольких представлениях:get_object, get_success_url, form_valid и dispatch с login_required декоратором.

Шаблон также очень прост:

    {% extends "pages/base.html" %}
    {% block content %}
        <h1>Update {{item.Asset.assettag}}</h1>

    <form action ="." method="POST"> {% csrf_token %}
        <table border="1">
            {{ form.as_table }}
        </table>
        <input class="btn btn-success" type="submit" value="Update"/>
        <a href="{{ view.get_success_url }}" class="btn btn-secondary">Cancel</a>
    </form>
    {% endblock %}

Проблемы:

  1. В сгенерированной форме будет отображаться (начальное значение) первичный ключ объекта Assets, в то время как я хотел бы, чтобы он отображал поле assettag.

У меня естьпытался сделать:

    class Meta:
        model = Item
        fields = [
            ...,
            'Asset.assettag',
                   # or
            'Asset__assettag',
            ...,
        ]

, но, похоже, не работает. Есть ли способ сделать это?

Использование inlineformset_factory будет делать то, что я хочу: показывать поля объекта Comments, связанного с экземпляром Item. Единственная проблема заключается в том, что он будет отображать ItemUpdateForm для каждого Comments объекта, который ссылается на Item (каждая строка в таблице Comments , связанная с этим экземпляром Item)

Например, если у меня есть только один комментарий и в качестве аргумента указано extra=0, форма будет в порядке. Если объект Item будет иметь два комментария, то отображаемая страница будет содержать два ItemUpdateForm с полем Комментарий, вставленным в каждый. Увеличение значения extra добавит еще ItemUpdateForm.

Я предполагаю, что мне нужно вставить каждое поле только в один экземпляр ItemUpdateForm.

.
...