0

I'd like to use the same form for both adding new records to the database and editing existing ones. The id of the record to be edited is passed via the URL (is this how I should do it?):

urlpatterns = [
    path('add-or-edit/<int:id>/', add-or-edit_view, name='edit'),
    path('add-or-edit/', add-or-edit_view, name='create'),
[...]

views.py:

def add-or-edit_view(request, id):
    if id is not there: # pseudocode, of course :)
        form = MyForm(request.POST or None)

    elif request.method == "POST":
        obj = get_object_or_404(Event, id=id)
        form = MyForm(request.POST or None, instance=obj)

        if form.is_valid():

            form.save()

    context = {
                'form':form
                }

    return render(request, "templates/add-or-edit.html", context)

I other words: if I go to add-or-edit/ then I want my empty form, if I go to add-or-edit/1 I want the form populated with data from the object with id 1. I am already doing this with two different views, one edit_view(request, id) and the other add-or-edit_view(request), which of course is not DRY.

PS

If I use:

def event_edit_view(request, id='None'):

    obj = get_object_or_404(Model, id=id)
    form = MyForm(request.POST or None, instance=obj)

then Django will complain if I access the URL with no parameters:

ValueError at /add-or-create/

Field 'id' expected a number but got 'None'.

PS 2

If I use:

def add-or-edit_view(request, id='None'):

    if id =='None':
        [unbound form]
    else:
        [bound form]

then I get:

AttributeError at /add-or-edit/

'NoneType' object has no attribute 'has_header'
HBMCS
  • 686
  • 5
  • 25

1 Answers1

0

You can use the same view but have to create two entries in urls.py, only then you are able to visit the page with or without parameter (id in your case, example answer

And in the view you have to do something like this:

def add_or_edit_view(request, id=None):
    if id is None:
        # "create view"
        if request.method == 'POST':
            # stuff
        else:
            # other stuff
    else:
        # edit view
        if request.method == 'POST':
            # stuff
        else:
            # other stuff

also don't forget to checkout the documentation about how to handle forms in the views.

bb4L
  • 899
  • 5
  • 16
  • Thank you. As you can see from my question I already have two directives in the urls, and the 'if' gives me the 'NoneType' object has no attribute 'has_header' error. I'll try 'None' without inverted commas now. – HBMCS May 15 '20 at 19:32
  • but you got it running with two different views and urls? – bb4L May 15 '20 at 19:41
  • Rigth now yes, two views and two urls, that's what I'm trying to fix, hence my question :) . I probably have to use `None` instead of `'None'`, will try it later, thanks. – HBMCS May 15 '20 at 19:46
  • i adjusted my answer slightly, with this pattern you should be able to merge the views and then refactor until you don't have duplicated code – bb4L May 15 '20 at 19:52
  • It looks promising, I can check only tomorrow and will let you know. – HBMCS May 15 '20 at 20:00