0

How to can I address this NoReverseMatch error?

Context

I want to document this question as much as possible in order to be able to detail the origin of the problem.

I have a model named LodgingOffer, to create a lodging offer and have the detail their information

class LodgingOffer(models.Model):

    # Foreign Key to my User model      
    created_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)

    ad_title = models.CharField(null=False, blank=False,
        max_length=255, verbose_name='Título de la oferta')

    slug = models.SlugField(max_length=100, blank=True)

    # ... Another fields ...

    def __str__(self):
        return "%s" % self.ad_title

    def get_absolute_url(self):
        return reverse('host:detail', kwargs = {'slug' : self.slug })

# I assign slug to offer based in ad_title field,checking if slug exist
def create_slug(instance, new_slug=None):
    slug = slugify(instance.ad_title)
    if new_slug is not None:
        slug = new_slug
    qs = LodgingOffer.objects.filter(slug=slug).order_by("-id")
    exists = qs.exists()
    if exists:
        new_slug = "%s-%s" % (slug, qs.first().id)
        return create_slug(instance, new_slug=new_slug)
    return slug

# Brefore to save, assign slug to offer created above.
def pre_save_article_receiver(sender, instance, *args, **kwargs):
    if not instance.slug:
        instance.slug = create_slug(instance)

pre_save.connect(pre_save_article_receiver, sender=LodgingOffer)

For this model, I have a DetailView named HostingOfferDetailView .

An important objective I want to pursue and for which I ask this question is that in the detail view of an LodgingOffer object, I should be able to contact the owner of that offer (object LodgingOffer - user who created it -) so that another interested user can apply to it.

I would like that in the detail view for the LodgingOffer object be able to contact the offer owner (object LodgingOffer - user who created it -) so others users interested could apply to it

For this purpose, I have contact_owner_offer() function, is where I send an email to the owner of this offer.

I'm doing all using the HostingOfferDetailView detail view like this:

class HostingOfferDetailView(DetailView):
    model = LodgingOffer
    template_name = 'lodgingoffer_detail.html'
    context_object_name = 'lodgingofferdetail'

    def get_context_data(self, **kwargs):
        context = super(HostingOfferDetailView, self).get_context_data(**kwargs)
        user = self.request.user

        # Get the related data offer
        #lodging_offer_owner = self.get_object()
        lodging_offer_owner_full_name = self.get_object().created_by.get_long_name()

        lodging_offer_owner_email = self.get_object().created_by.email

        lodging_offer_title = self.get_object().ad_title
        user_interested_email = user.email
        user_interested_full_name = user.get_long_name()

        # Send to context email of owner offer and user interested in offer
        context['user_interested_email'] = user_interested_email
        context['lodging_offer_owner_email'] = lodging_offer_owner_email

        # Send the data (lodging_offer_owner_email
        # user_interested_email and lodging_offer_title) presented 
        # above to the contact_owner_offer function
        contact_owner_offer(self.request, lodging_offer_owner_email, user_interested_email, lodging_offer_title)

        return context

My contact_owner_offer() function receives these offer parameters and sends an email to the owner of the offer or the publisher, as follows:

def contact_owner_offer(request, lodging_offer_owner_email, user_interested_email, lodging_offer_title):
    user = request.user
    if user.is_authenticated:
        # print('Send email')
        mail_subject = 'Interest in your offer'

        context = {
            'lodging_offer_owner_email': lodging_offer_owner_email,
            # User owner offer - TO send email message

            'offer': lodging_offer_title,
            # offer for which a user asks 

            'user_interested_email': user_interested_email,
            # Interested user offer

            'domain': settings.SITE_URL,
            'request': request
        }

        message = render_to_string('contact_user_own_offer.html', context)
        #to_email = lodging_offer_owner.email,

        send_mail(mail_subject, message, settings.DEFAULT_FROM_EMAIL,
                  [lodging_offer_owner_email], fail_silently=True)

I have done this as a test and so far everything is as I wanted, and the result is that when I enter the URL of a detailed offer object LodgingOffer, an email is sent to the owner of that offer.

What I would like that the offer detail template has a button with contains "Contact the owner of the offer" and when any user who presses it send an email to the owner of the offer.

To do this I defined a URL for contact_owner_offer() function and it has a link on the href attribute of a button in my template.

The URL, (according to my understanding and this is where the doubt and the reason for my question resides) I have defined it according to the number of parameters that the contact_owner_offer() function receives.

This means my URL must receive:

  • The offer owner's email address
  • The e-mail address of the user interested in the offer
  • The title of the offer, although for this I'm sending you the slug of that title, I don't know if that's correct.

So, according to the above, I've created this URL:

url(r'^contact-to-owner/(?P<email>[\w.@+-]+)/from/'
        r'(?P<interested_email>[\w.@+-]+)/(?P<slug>[\w-]+)/$',
        contact_owner_offer, name='contact_owner_offer'),

Then, in my template, I generate an html button where I call this URL sending them their respective parameters that expect:

<div class="contact">
    <a class="contact-button" href="{% url 'host:contact_owner_offer' email=lodging_offer_owner_email interested_email=user_interested_email slug=lodgingofferdetail.slug %}">
        <img src="{% static 'img/icons/contact.svg' %}" alt="">
        <span>Contact owner offer</span>
    </a>
</div>

What happens to me is that when I enter the offer detail template and click on the Contact owner offer reference button immediately above, I get the following error message:

 TypeError: contact_owner_offer() got an unexpected keyword argument 'email'
[10/Oct/2017 01:04:06] "GET /host/contact-to-owner/[email protected]/from/[email protected]/apartacho/ HTTP/1.1" 500 77979  

My traceback is here

Traceback:

File "/home/bgarcial/.virtualenvs/hostayni/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner
  42.             response = get_response(request)

File "/home/bgarcial/.virtualenvs/hostayni/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  187.                 response = self.process_exception_by_middleware(e, request)

File "/home/bgarcial/.virtualenvs/hostayni/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  185.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

Exception Type: TypeError at /host/contact-to-owner/[email protected]/from/[email protected]/apartacho/
Exception Value: contact_owner_offer() got an unexpected keyword argument 'email'

What I don't understand, is because it tells me that my URL doesn't wait for an argument called email which is where I pass the parameter email=lodging_offer_owner_owner_email through the button in the template.

I appreciate any guidance Best Regards


UPDATE

According to the @RajKris and @Daniel recommendations I've changed slightly my URL regex, specifying the name of the keyword argument which I am passing. The URL stay of this way:

url(r'^contact-to-owner/(?P<lodging_offer_owner_email>[\w.@+-]+)/from/'
        r'(?P<interested_email>[\w.@+-]+)/(?P<slug>[\w-]+)/$',
        contact_owner_offer,
        name='contact_owner_offer'
    ),

This mean, I am naming the url parameters of the same way in which I've named the parameters that contact_owner_offer() receive.

And when I enter the offer detail template and click on the Contact owner offer reference button I get the NoReverseMatch error

Template error:
In template /home/bgarcial/workspace/hostayni_platform/hosts/templates/lodgingoffer_detail.html, error at line 193
   Reverse for 'contact_owner_offer' with arguments '()' and keyword arguments '{'email': '[email protected]', 'interested_email': '[email protected]', 'slug': 'apartacho'}' not found. 1 pattern(s) tried: ['host/contact-to-owner/(?P<lodging_offer_owner_email>[\\w.@+-]+)/from/(?P<interested_email>[\\w.@+-]+)/(?P<slug>[\\w-]+)/$']   183 :                                </tr>
   184 :                                <tr>
   185 :                                    <td>{{ lodgingofferdetail.room_value }}</td>
   186 :                                    <td>{{ lodgingofferdetail.additional_description }}</td>
   187 :                                    <td>{{ lodgingofferdetail.lodging_offer_owner_email }}</td>
   188 :                                </tr>
   189 :                            </tbody>
   190 :                        </table>
   191 :                    </div>
   192 :                    <div class="contact">
   193 :                        <a class="contact-button" href=" {% url 'host:contact_owner_offer' email=lodging_offer_owner_email interested_email=user_interested_email slug=lodgingofferdetail.slug %} ">
   194 :                            <img src="{% static 'img/icons/contact.svg' %}" alt="">
   195 :                            <span>Contactar</span>
   196 :                        </a>
   197 :                    </div>

The general traceback is here:

File "/home/bgarcial/.virtualenvs/hostayni/lib/python3.6/site-packages/django/urls/resolvers.py" in _reverse_with_prefix
  392.             (lookup_view_s, args, kwargs, len(patterns), patterns)

Exception Type: NoReverseMatch at /host/lodging-offer/apartacho/
Exception Value: Reverse for 'contact_owner_offer' with arguments '()' and keyword arguments '{'email': '[email protected]', 'interested_email': '[email protected]', 'slug': 'apartacho'}' not found. 1 pattern(s) tried: ['host/contact-to-owner/(?P<lodging_offer_owner_email>[\\w.@+-]+)/from/(?P<interested_email>[\\w.@+-]+)/(?P<slug>[\\w-]+)/$']

How to can I address this NoReverseMatch error?

5
  • 1
    Are you trying to call another view from one view ? Or just want to call a function ? If you just want to call a function, don't have to list it in ulrs. Commented Oct 10, 2017 at 12:21
  • 1
    Firstly, doing any action like sending emails on GET is a very bad idea. Secondly, the URL you have posted here would not give this error; instead you would get a ReverseMatchError, because you are passing keyword args to the {% url %} tag. Finally, don't post a screenshot of an error; click that link that says "Switch to copy-and-paste view' and post the resulting text as text. Commented Oct 10, 2017 at 12:28
  • @DanielRoseman Thanks for the tips. The email sent on DetailView is just as a test, this call to the contact_owner_offer() function inside HostingOfferDetailView won't be included in the end. I've post my traceback, it's true I am passing keyword args in the {% url %} tag, but I don't know the reason which I get the same error Exception Value: contact_owner_offer() got an unexpected keyword argument 'email' Commented Oct 10, 2017 at 13:45
  • @SandeepBalagopal I am calling a function based view (contact_owner_offer()) inside my HostingOfferDetailView class based view. I did this, because the idea is reach to contact_owner_offer() by calling it by means of the {% url %} tag in my template, and receive these parameters which I am passing Commented Oct 10, 2017 at 13:48
  • @DanielRoseman I've changed slightly my URL regex, specifying the name of the keyword argument which I am passing, and I get the ReverseMatchError that you specify me. I would like if you can check this scenarie please Commented Oct 10, 2017 at 14:15

2 Answers 2

1

In the URL regex you have to specify, name of the kyword arg you're passing:

url(r'^contact-to-owner/(?P<email1>[\w.@+-]+)/from/' r'(?P<email1>[\w.@+-]+)/(?P<email3>[\w-]+)/$', contact_owner_offer, name='contact_owner_offer'),

This is referred here:

Django Doc

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the tip. I still don't finish of understand the named groups parameters in URL. I've changed slightly my URL regex, specifying the name of the keyword argument which I am passing, and I get the ReverseMatchError, an error different. I know that the problem is my URL, when I define it. ?
Can you check my update to my original question please?
1

Why not using simple url with get params?

e.g. "contact-to-owner/?owner-email=xxx&user-email=xxx&title=xxx"

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.