-1

I am learning Django by building an application, called TravelBuddies. It will allow travelers to plan their trip and keep associated travel items (such as bookings, tickets, copy of passport, insurance information, etc), as well as create alerts for daily activities. The application will also able to update local information such as weather or daily news to the traveler. Travelers can also share the travel information with someone or have someone to collaborate with them to plan for the trip.

I am facing a problem. I have a form like this: enter image description here

When I click on the Submit button, I am supposed to be redirected to http://127.0.0.1:8000/triplist/johor-bahru/. Instead, I get this error:

NoReverseMatch at /addactivity/
Reverse for 'activity' with no arguments not found. 1 pattern(s) tried: ['triplist/(?P<slug>[-a-zA-Z0-9_]+)/$']
Request Method: POST
Request URL:    http://127.0.0.1:8000/addactivity/
Django Version: 3.0
Exception Type: NoReverseMatch
Exception Value:    
Reverse for 'activity' with no arguments not found. 1 pattern(s) tried: ['triplist/(?P<slug>[-a-zA-Z0-9_]+)/$']

Here are my codes in models.py inside Trips folder:

from django.contrib.auth.models import User
from django.db import models
from django.template.defaultfilters import slugify

# Create your models here.
class Trip(models.Model):
    trip_name = models.CharField(max_length=100)
    date = models.DateField()
    planner_name = models.CharField(max_length=100)
    add_coplanner = models.ManyToManyField(User)
    trip_description = models.CharField(max_length=1000, default='null')
    slug = models.SlugField(max_length=150, default='null')

    def __str__(self):
        return self.trip_name

    def save(self, *args, **kwargs):
        self.slug = slugify(self.trip_name)
        super().save(*args, **kwargs)

class Activity(models.Model):
    trip = models.ForeignKey(Trip, on_delete=models.CASCADE)
    activity_name = models.CharField(max_length=100)
    date = models.DateField()
    time = models.TimeField()
    location = models.CharField(max_length=100)
    activity_description = models.CharField(max_length=1000, default='null')
    item_type = models.CharField(max_length=100)
    item_number = models.CharField(max_length=100)
    add_cotraveller = models.ManyToManyField(User)
    slug = models.SlugField(max_length=150, default='null')


    def __str__(self):
        return self.activity_name

    def save(self):
        super(Activity, self).save()
        self.slug = '%i-%s' % (
            self.id, slugify(self.trip.trip_name)
        )
        super(Activity, self).save()

Here are my codes in views.py inside Trips folder:

from django.views import generic
from .models import Trip, Activity


class TripListView(generic.ListView):
    template_name = 'trips/triplist.html'
    context_object_name = 'all_trips'

    def get_queryset(self):
        return Trip.objects.all()


class ActivityView(generic.DetailView):
    model = Trip
    template_name = 'trips/activity.html'

Here are my codes in urls.py inside Trips folder:

from . import views
from django.urls import path

app_name = 'trips'

urlpatterns = [
    path('triplist/', views.TripListView.as_view(), name='triplist'),
    path('triplist/<slug:slug>/', views.ActivityView.as_view(), name='activity'),
]

Here are my codes in apps.py inside trips folder:

from django.apps import AppConfig


class TripsConfig(AppConfig):
    name = 'trips'

Here are my codes in apps.py inside addactivity folder:

from django.apps import AppConfig


class AddactivityConfig(AppConfig):
    name = 'addactivity'

Here are my codes in forms.py inside addactivity folder:

from django.forms import ModelForm
from trips.models import Activity

class ActivityForm(ModelForm):
    class Meta:
        model = Activity
        fields = ['trip', 'activity_name', 'date', 'time', 'location', 'activity_description', 'item_type', 'item_number', 'add_cotraveller']

Here are my codes in forms.py inside addactivity folder:

from django.forms import ModelForm
from trips.models import Activity

class ActivityForm(ModelForm):
    class Meta:
        model = Activity
        fields = ['trip', 'activity_name', 'date', 'time', 'location', 'activity_description', 'item_type', 'item_number', 'add_cotraveller']

Here are my codes in urls.py inside addactivity folder:

from . import views
from django.urls import path

app_name = 'addactivity'

urlpatterns = [
    path('addactivity/', views.AddActivityFormView.as_view(), name='addactivity'),

]

Here are my codes in views.py inside addactivity folder:

from django.shortcuts import render
from django.views.generic import TemplateView
from .forms import ActivityForm
from trips.models import Activity
from django.http import HttpResponseRedirect
from django.urls import reverse

# Create your views here.


class AddActivityFormView(TemplateView):
    template_name = 'addactivity/addactivityform.html'

    def get(self, request):
        form = ActivityForm()
        activities = Activity.objects.all()
        args = {'form': form, 'activities': activities}
        return render(request, self.template_name, args)

    def post(self, request):
        form = ActivityForm(request.POST)
        if form.is_valid():
            form.save()
            trip = form.cleaned_data['trip']
            activity_name = form.cleaned_data['activity_name']
            date = form.cleaned_data['date']
            time = form.cleaned_data['time']
            location = form.cleaned_data['location']
            activity_description = form.cleaned_data['activity_description']
            item_type = form.cleaned_data['item_type']
            item_number = form.cleaned_data['item_number']
            add_cotraveller = form.cleaned_data['add_cotraveller']

            args = {'form': form, 'trip': trip, 'activity_name': activity_name, 'date': date, 'time': time, 'location': location, 'activity_description': activity_description, 'item_type': item_type, 'item_number': item_number, 'add_cotraveller': add_cotraveller}
            return HttpResponseRedirect(reverse('trips:activity'))

Here are my codes in addactivityform.html inside templates > addactivity folder:

{% extends 'base.html' %}
{% load static %}

{% block title %} Add Activity {% endblock %}

{% block content %}

<div class="container">
    <h2>Add New Activity</h2>
    <form method="post">
        {% csrf_token %}
        {{ form.as_p }}
        <button type="submit">Submit</button>
    </form>
</div>

{% endblock %}

Is there any problem in return HttpResponseRedirect(reverse('trips:activity'))?

In urls.py inside Trips folder, there is a slug.

path('triplist/<slug:slug>/', views.ActivityView.as_view(), name='activity'),

I can't figure out a way to redirect to a web page with slug with my codes in views.py inside addactivity folder. Being a beginner, I am unable to solve the issue. So, I need help.

Update: I have added my codes in addactivityform.html inside templates > addactivity folder in the question.

I also found similar questions and answers at Stackoverflow. But still, I can't solve the issue.

Here is the link to my project files.

Shawn
  • 173
  • 14
  • I'm not a django expert at all, but it seems the submit button is taking you to `http://127.0.0.1:8000/addactivity/`, not your expected url. I didn't see a view for that url format. – user1558604 Dec 07 '19 at 05:45
  • Edit the question to include the `addactivity/addactivityform.html` template. – John Gordon Dec 07 '19 at 05:46
  • @JohnGordon I have added my codes in `addactivityform.html` inside **templates > addactivity** folder in the question. – Shawn Dec 07 '19 at 05:51
  • Does this answer your question? [What is a NoReverseMatch error, and how do I fix it?](https://stackoverflow.com/questions/38390177/what-is-a-noreversematch-error-and-how-do-i-fix-it) – Kent Shikama Dec 07 '19 at 05:56
  • @KentShikama Yes, I have read them. But I can't solve the issue. If I use return `HttpResponseRedirect(reverse('trips:triplist'))` in views.py under addactivity folder, then I no longer see the error message. However, if I use the specific code, I am redirected to a wrong page, which is http://127.0.0.1:8000/triplist/. I need to be redirected to http://127.0.0.1:8000/triplist/johor-bahru/. – Shawn Dec 07 '19 at 06:00

1 Answers1

0

A better way is define a get absolute method in your activity model and call it in your views.

def get_absolute_url(self):
        return reverse("trips:activity", kwargs={"slug": self.slug})

and redirect in your views following way:

if form.is_valid():
        instance = form.save(commit=False)
        instance.save()
        return HttpResponseRedirect(instance.get_absolute_url())

Or if you use generic create view you can do as follows and give a success url

class TripCreateView(CreateView):
    model = Trip
    form_class = TripCreateForm
    template_name = 'your_remplate.html'

    def form_valid(self, form):
    ---------
    ---------
    return HttpResponseRedirect(self.get_success_url())
bmons
  • 3,352
  • 2
  • 10
  • 18
  • I have used your codes. But I am getting this error: `Page not found (404) Request Method: GET Request URL: http://127.0.0.1:8000/triplist/14-singapore/ Raised by: trips.views.ActivityView No trip found matching the query` – Shawn Dec 07 '19 at 06:23
  • Check whether it actually exists or not, as a better practice delete the previous data and add new then test it again – bmons Dec 07 '19 at 06:30
  • I have done that. But I am still getting the same error. Should I share my project files with you via Google Drive? – Shawn Dec 07 '19 at 06:36
  • Your naming confused me, the absolute method you have to place under Trip models, since you are using trip model in your views. – bmons Dec 07 '19 at 06:40
  • Here is the link to my project files: https://drive.google.com/open?id=1gSepA8JvhUAQz2YBagRksSjsHbKns7OR – Shawn Dec 07 '19 at 06:43
  • The link is not opening in my end, any how change as i suggested and let me know. – bmons Dec 07 '19 at 06:47
  • No, I get an error, which said `no get_absolute_url(self): found on Activity model.` – Shawn Dec 07 '19 at 06:50
  • Would you please try this link: https://drive.google.com/file/d/1gSepA8JvhUAQz2YBagRksSjsHbKns7OR/view – Shawn Dec 07 '19 at 06:53
  • Just click on the download button. – Shawn Dec 07 '19 at 06:54
  • no, it wont work here, I am on linux platform. You better write views using generic create view rather than template view. And use same models on views and forms. – bmons Dec 07 '19 at 06:58
  • I am a beginner. It will be highly appreciated if you share the working codes with me. – Shawn Dec 07 '19 at 07:02
  • i have updated the answer with a generic create view example – bmons Dec 07 '19 at 07:29
  • Does this solution takes me to a new web page, called 'your_remplate.html'? I need to be redirected to activity.html. – Shawn Dec 07 '19 at 08:26
  • it is your addactivityform.html not redirect template – bmons Dec 07 '19 at 08:31
  • if the answer was useful, don't forget to tick – bmons Dec 07 '19 at 10:31