0

I'm using django2 and I get an error when I access this url: http://127.0.0.1:8000/hotes/12/access/7/update I get an error 404 "None access object was found"

To make a long story short: I want to update an object linked to another. To do so, I have to send through the link, both primary keys (12 and 7 in the url). Also, I use the generic view "UpdateView" given by Django.

This is the path concerned in my project.urls:

urlpatterns = [
    path('hotes/<int:pk>/access/<int:access_pk>/update/',views.AccessUpdateView.as_view(), name='access_update'),
    path('hotes/add',views.host_add, name='host_add'),
    path('hotes/<int:pk>/', include([
        path('edit',views.HostUpdateView.as_view(), name='host_update'),
        path('delete',views.host_delete, name='host_delete'),
    ])),
    path('hotes/<int:pk>/add/', include([
        path('access',views.access_add, name='access_add'),
        path('oncall',views.onCall_add, name='onCall_add'),
        path('network',views.network_add, name='network_add'),
    ])),
    path('hotes/<int:pk>/',views.host_view, name='host_view'),
    path('hotes/',views.hosts_view, name='hosts_view'),
    path('', views.home, name='home'),
    path('admin/', admin.site.urls),
]

I want the second primary key to be used in my view "AccessUpdateView".

This is a part of my models.py:

class Host(models.Model):
    name = models.CharField(max_length=30, unique=True)
    usage = models.CharField(max_length=30, blank=True)
    function = models.CharField(max_length=30, blank=True)
    production = models.NullBooleanField(blank=True, null=True)
    place = models.CharField(max_length=30, blank=True)
    type = models.CharField(max_length=30, blank=True)
    processor = models.DecimalField(max_digits=3, decimal_places=2, null=True, blank=True)
    storage = models.CharField(max_length=10, blank=True)
    memory = models.CharField(max_length=10, blank=True)
    dns_inner = models.CharField(max_length=50, blank=True)
    dns_extern = models.CharField(max_length=50, blank=True)
    os = models.ForeignKey(Os, null=True, related_name='hosts', on_delete=models.SET_NULL, blank=True)

class Access(models.Model):
    service = models.CharField(max_length=20)
    client_access = models.NullBooleanField(blank=True, null=True)
    ip = models.GenericIPAddressField()
    login = models.CharField(max_length=30, blank=True)
    password = models.CharField(max_length=50, blank=True)
    host = models.ForeignKey(Host, related_name='access', on_delete=models.CASCADE)

As you can see on host can have multiple access but an access in linked to only one host.

This is the view concerned:

class AccessUpdateView(UpdateView):
    model = Access
    fields = ('service','client_access','ip','login','password', )
    template_name = 'access_update.html'
    pk_url_kwarg = 'access_pk'
    context_object_name = 'access'

    def form_valid(self, form):
        access = form.save(commit=False)
        host_id = self.kwargs['pk']
        access.host_id = host_id
        access.save()
        return redirect('host_view', pk=host_id)

EDIT: new error when I try to access the url:

NoReverseMatch at /hotes/12/access/7/update/

Reverse for 'host_view' with arguments '('',)' not found. 1 pattern(s) tried: ['hotes\/(?P[0-9]+)\/$']


EDIT: The error was coming from "access_update.html" I removed the href in the Hote link which contained {% url host.pk %}

{% extends 'base.html' %}

{% load widget_tweaks %}

{% block title %}Modifier Acces{% endblock %}

{% block breadcrumb %}
  <li class="breadcrumb-item"><a href="{% url 'hosts_view' %}">Hotes</a></li>
  <li class="breadcrumb-item"><a href="">Hote</a></li>
  <li class="breadcrumb-item active">Modification Acces</li>
{% endblock %}

{% block contenu %}
  <form method="post" novalidate>
    {% csrf_token %}
    {% include 'includes/form.html' %}
    <button type="submit" class="btn btn-success">Modifier</button>
  </form>
{% endblock %}

The question is what is the right way to write the pk of the host in the url? (host_id doesn't work)

Gug
  • 55
  • 2
  • 8

1 Answers1

0

If you want to use access_pk, then you should set pk_url_kwarg = 'access_pk' in the view.

In your form_valid method, you are using host without defining it. If pk from the URL is the host id, then you can access it with self.kwargs['pk'].

def form_valid(self, form):
    access = form.save(commit=False)
    host_id = self.kwargs['pk']
    access.host_id = host_id
    access.save()
    return redirect('host_view', pk=host_id)

Inside the template for the AccessUpdateView, you have access to access since that is the object that is being updated. If you want to use the host or its id, you should access it via access.

{% url 'host_view' access.host_id %}
Alasdair
  • 298,606
  • 55
  • 578
  • 516
  • I tried that, but it doesn't work either. It's more like Django doesn't like the "access" part in the url – Gug Jan 09 '18 at 21:23
  • "it doesn't work either" is not enough information to help. What happens when you try that? – Alasdair Jan 09 '18 at 21:25
  • I restarted my server and now the message changed: NoReverseMatch at /hotes/12/access/7/update/ Reverse for 'host_view' with arguments '('',)' not found. 1 pattern(s) tried: ['hotes\\/(?P[0-9]+)\\/$'] – Gug Jan 09 '18 at 21:56
  • Don't put error messages in the comments, they are difficult to read. Edit your question and include the full traceback. You haven't shown the `host_view` URL pattern in question. – Alasdair Jan 09 '18 at 21:58
  • I modified it as you said – Gug Jan 09 '18 at 22:23
  • The updated `form_valid` method shouldn't give that error. Where is the `NoReverseMatch` coming from? The template? Or somewhere else? – Alasdair Jan 09 '18 at 22:42
  • It was in the template. I removed what was troublesome but I don't know what I should write instead. I edited my question. – Gug Jan 09 '18 at 23:20
  • You can't use `host.pk` in the template unless you manually add it to the template context. You can get the host id via `access` instead. – Alasdair Jan 09 '18 at 23:36
  • access.host.pk was the solution, thanks a lot, you really helped me out :) – Gug Jan 10 '18 at 21:59