Ken Ist
Ken Ist

Reputation: 79

How can I delete in one View OLD model OBJECT and create NEW with COPIED fields?Django

I have a model Book:

models.py

class Book(core.BaseModel):
    MAX_TAG_NUMBER = 99999

    class Statuses(models.IntegerChoices):
        AVAILABLE = 1, 'Available'
        NOT_AVAILABLE = 2, 'Not Available'

  
    author = models.ForeignKey(
        Author, models.PROTECT, verbose_name='Author',
        related_name='author_name',
    )
    
    tag_number = models.PositiveIntegerField('Tag number', validators=[
        MinValueValidator(1),
        MaxValueValidator(MAX_TAG_NUMBER),
    ])
    year = models.PositiveSmallIntegerField(
        'Year', default=default_current_year, validators=[validate_current_year],
    )
    status = models.PositiveSmallIntegerField('Status', choices=Statuses.choices, default=Statuses.AVAILABLE)

I want to create button which delete object by id and copy all fields from this OLD object and CREATE new model object with this fields BUT deleted field 'tag_number' which I want to create again. I created this:

class BookUpdateView(core.DeleteView):
    form_class = BookTagForm
    template_name = 'book/book_update.html'
    success_url = reverse_lazy('book:book-list')

def dispatch(self, *args, **kwargs):
    obj = self.get_object()
    obj.pk = None
    copy = []
    copy.append(obj)
    # obj.delete()
    return redirect('book:book-create' % copy.id)

But I don't understand: 1)how to Delete all this fields in View and create new object with this copy of fields EXCLUDE tag_number? 2)Which view it must to be?CreateView, UpdateView? How can I delete and create in the same view

class BookTagForm(core.ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)


    class Meta:
        model = Book
        fields = ('tag_number', 'author', )

    def save(self, commit=True):
        instance = super().save(commit=False)
        instance = Book.objects.create(
            author=self.cleaned_data['author'],
            status=self.cleaned_data['status'],
            tag_number=self.cleaned_data['tag_number'],
            year=self.cleaned_data['year'],
        )
        if commit:
            instance.save()
        return instance

Upvotes: 0

Views: 553

Answers (1)

AKX
AKX

Reputation: 168913

Something like this might do the trick, if I'm understanding your question correctly.

However, I'd question your data model – why exactly do you need to delete instances? That will break foreign keys and such...

class BookUpdateView(core.UpdateView):
    form_class = BookTagForm
    template_name = 'book/book_update.html'
    success_url = reverse_lazy('book:book-list')


class BookTagForm(core.ModelForm):
    class Meta:
        model = Book
        fields = ('tag_number', 'author')

    def save(self, commit=True):
        assert commit  # this function doesn't work correctly when not committing
        assert self.instance.pk  # work on existing models only
        self.instance.delete()  # delete old instance from database
        self.instance.pk = None  # remove pk from instance, thus making save() create a new instance
        self.instance = super().save()  # assigns the new fields from this form and saves the object
        return self.instance

Upvotes: 2

Related Questions