MattG
MattG

Reputation: 1932

How to pass a variable from one view to another in Django

I would like to pass a variable from one view to another in Django and am not sure of the best method.

The "defaultCreateView" below is a form that makes a new database entry and has a required field that I want to be filled automatically (device_id). So my thought is I could pass it through in the URL. This form is accessed using the button shown in my template below. So the idea is that the first view passes the variable to the template where the button is, then this button adds the device_id to the URL via the href.

Is there a much easier/better way to accomplish this?

Thanks in advance for any help.

urls.py

urlpatterns = [
    path('<int:pk>/edit/', defaultUpdateView.as_view(), name='default_edit'),
    path('<int:pk>/', defaultDetailView.as_view(), name='default_detail'),
    path('<int:pk>/delete/', defaultDeleteView.as_view(), name='default_delete'),
    path('<int:device>', DefaultsListView.as_view(), name='Default_Listview'),
    path('<int:device>/new/', defaultCreateView.as_view(), name='default_new'),
    path('Defaultsapidata/', apiDefaultsListView.as_view(), name='Defaults_apidata_list'),
    path('<int:pk>/changedefaults/', changeDefaultsViewSingle.as_view()),
]

Views.py

class DefaultsListView(LoginRequiredMixin,ListView):
    model = models.DefaultDMLSProcessParams
    template_name = 'defaults_list.html'
    login_url = 'login'
    def get_queryset(self):
        return super(DefaultsListView, self).get_queryset().filter(device_id=self.kwargs['device'])

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        deviceID = self.kwargs['device']
        context['deviceID'] = deviceID
        return context

class defaultCreateView(LoginRequiredMixin,CreateView):
    model = models.DefaultDMLSProcessParams
    template_name = 'default_new.html'
    fields= ['defaultParamDescrip','processType','processNotes',]
    login_url = 'login'

    def form_valid(self, form):
        form.instance.customerTag = self.request.user.customerTag 
        form.instance.device_id = self.kwargs['device']
        return super().form_valid(form)

defaults_list.html

<a class="btn btn-primary btn-lg" 
href="{% url 'default_new' {{deviceID}}  %}" role="button"> Add New Default Parameter</a>

EDIT I get a "NoReverseMatch at /defaults/41" when I try to access defaults_list.html, but this is solved when I change the URL of defaultCreateView to:

        path('new/', defaultCreateView.as_view(), name='default_new'),

Upvotes: 2

Views: 5044

Answers (2)

Alex_FIR_IT
Alex_FIR_IT

Reputation: 71

I had the same problem. I've made up my mind to pass an email into args in 'RegisterUserView' and then in 'CodeConfirmationUserView' retrieve this value in 'get_initial' method which obtains an 'email' from self.kwargs and then passes it into my template as an initial data.

views.py

class RegisterUserView(ConfirmationCodeMixin, ErrorMessageMixin, SuccessMessageMixin, CreateView):
    model = get_user_model()
    form_class = RegisterUserForm
    template_name = 'users/register.html'
    extra_context = {'title': 'Registration'}
    success_message = "The confirmation code has been successfully sent!"

    def form_valid(self, form):
        try:
            user = form.save(commit=False)
        except UserNotInExternalResource as error:
            messages.error(request=self.request, message=error)
            return redirect(to=reverse_lazy(REGISTER_URL))
        # ...

        return redirect(to=reverse_lazy('users:code_confirmation', args=(user.email,)))


class CodeConfirmationUserView(ConfirmationCodeMixin, ErrorMessageMixin, SuccessMessageMixin, FormView):
    model = get_user_model()
    form_class = CodeConfirmationUserForm
    template_name = 'users/code_confirmation.html'
    extra_context = {'title': 'Registration'}
    success_url = reverse_lazy('home')
    success_message = "Registation and authentication have been successfully permormed!"

    def post(self, request, *args, **kwargs):
        # ... 

    def get_initial(self):
        initial = super().get_initial()
        initial['email'] = self.kwargs.get('email', '')  # Set the initial value for the email field
        return initial

code_confirmation.html

<div class="my-3">
    <label class="w-150 me-2 align-top" for="{{ form.email.id_for_label }}">
        {{ form.email.label }}
    </label>
    {{ form.email }}
</div>
<div class="my-3">
    <label class="w-150 me-2 align-top" for="{{ form.confirmation_code.id_for_label }}">
        {{ form.confirmation_code.label }}
    </label>
    {{ form.confirmation_code }}
</div>

urls.py

from django.urls import path
from users import views

app_name = "users"

urlpatterns = [
    path('register/', views.RegisterUserView.as_view(), name='register'),
    path('code_confirmation/<str:email>', views.CodeConfirmationUserView.as_view(), name='code_confirmation')
]

Now the default value for email will be displayed

enter image description here enter image description here

Upvotes: 0

Yacine Bouziane
Yacine Bouziane

Reputation: 208

def update_project_filter(request):
...
selected_project_id = project_form.cleaned_data["Project_Name"].id
request.session['selected_project_id'] = selected_project_id
...

def update_project(request):
...
selected_project_id = request.session.get('selected_project_id')
...

Assuming you've activated "django.contrib.sessions.middleware.SessionMiddleware"

Upvotes: 10

Related Questions