4

I know there is a better way to do this, but I can't quite figure it out.

I am making a web application that has a series of the same pages, based on what department and station you select.

This is info that I am using later in a separate script to determine where to send a file.

But right now I am using different views for each page.

For example I have one view in my views.py that looks like this:

views.py

def FOO_station_0(request):
    Site_Data.station = 0
    Site_Data.dept = "FOO"
    ctx = {}
    ctx['station'] = Site_Data.station

    if request.method == 'POST':
        form = my_form(request.POST)

        if form.is_valid():
            try:
                Ext_Data.parsed_data = form.cleaned_data['full_scan']
                saveScan()
            except IndexError:
                ctx['error_message'] = error_message
                return HttpResponseRedirect('/error/input')

            return HttpResponseRedirect(f'/confirm')

    else:
        form = my_form()
    ctx['form'] = form
    return render(request, f'scan/FOO/FOO_station.html', ctx)

And another that looks like this:

def BAR_station_2(request):
    Site_Data.station = 2
    Site_Data.dept = "BAR"
    ctx = {}
    ctx['station'] = Site_Data.station

    if request.method == 'POST':
        form = my_form(request.POST)

        if form.is_valid():
            try:
                Ext_Data.parsed_data = form.cleaned_data['full_scan']
                saveScan()
            except IndexError:
                ctx['error_message'] = error_message
                return HttpResponseRedirect('/error/input')

            return HttpResponseRedirect(f'/confirm')

    else:
        form = my_form()
    ctx['form'] = form
    return render(request, f'scan/BAR/BAR_station.html', ctx)

As you can see, they are both returning the same HTML file, this is because they are very similar, but I want the URL, and the information passed to be different.

I need to do this for many different stations, all having a different dept or station number, but other than that it will be the same.

I could just add one view for each station, but that feels sloppy.

My Urls.py looks like this:

from django.urls import path
from . import views

urlpatterns = [
...
...
    path('FOO/station_0', views.FOO_station_0, name='FOO_station_0'),
    path('FOO/station_1', views.FOO_station_1, name='FOO_station_0'),
    path('FOO/station_2', views.FOO_station_2, name='FOO_station_0'),
    path('FOO/station_3', views.FOO_station_3, name='FOO_station_0'),
...
...
    path('BAR/station_1', views.BAR_station_1, name='BAR_station_1'),
    path('BAR/station_2', views.BAR_station_2, name='BAR_station_2'),
    path('BAR/station_3', views.BAR_station_3, name='BAR_station_3'),
    path('BAR/station_4', views.BAR_station_4, name='BAR_station_4'),
...
...
]

Where each station is returning a different URL, because that URL is linked to the data that I want passed.

It doesn't seem like this is the best way to do this, but I don't know where to start to find a better way.

What is the best way to do this in Django?

Any help is very much appreciated.


Besides the answers given below, this link was also helpful for anyone who finds this question in the future.

https://docs.djangoproject.com/en/3.2/intro/tutorial03/

2 Answers2

2

first you need to use regex in you urls. by doing this you will have one or a few urls instead of too many. This is the link how you can do this capture parameters from url

In the link above, you will see how to capture parameters from url, then you can use those parameters inside your view. By doing this you will have one or a few views, and you will not need to add one view for each url.

Khanzadeh_AH
  • 139
  • 6
  • 1
    I was not aware that more parameters could be passed in like that. Though, now that I see it, it definitely makes sense. I appreciate you taking the time to help me out. I am going to play around with it and make sure this fits my needs before marking the question as solved. – Josh_At_Sorenson Aug 27 '21 at 14:39
2

Since station and dept are the only things that change you can add them as the arguments of function:

def station_view(request, dept, station_num):
    Site_Data.dept = dept
    Site_Data.station = station_num
    ctx = {}
    ctx['station'] = Site_Data.station

    if request.method == 'POST':
        form = my_form(request.POST)

        if form.is_valid():
            try:
                Ext_Data.parsed_data = form.cleaned_data['full_scan']
                saveScan()
            except IndexError:
                ctx['error_message'] = error_message
                return HttpResponseRedirect('/error/input')

            return HttpResponseRedirect(f'/confirm')

    else:
        form = my_form()
    ctx['form'] = form
    # assuming dept will always be either 'FOO' or 'BAR'
    return render(request, f'scan/{dept}/{dept}_station.html', ctx)

Then in urls.py define those parameters in url as below:

urlpatterns = [
...
    path('<dept>/station_<station_num>/', views.station_view, name='station-view'),
]

Finally in templates, you can relate each object's station and dept with something like below:

{% for obj in objects %}
    <a href="url 'station-view' dept=obj.dept station_num=obj.station">obj.name<>
{% endfor %}

PS: I assume your context object name is objects and it actually contains fields dept, station and name. Fit it for your needs.

Rustam Garayev
  • 2,632
  • 1
  • 9
  • 13