简体   繁体   中英

How to use Django url template tag with variable as url path

I encountered a No Reverse Match Error in trying to render a template. Can you explain what this No Reverse Match Error mean for easier understanding and how to solve the error?

models.py

from django.contrib.sites.models import Site
from django.contrib.gis.db import models
from django.utils.crypto import get_random_string
from django.contrib.gis.geos import GEOSGeometry,Point
from django.contrib.auth.models import AbstractUser
from django.shortcuts import render
# Create your models here.
class User(AbstractUser):
    pass

geos_pnt=Point(4314498.56, 1003834.600,srid=3857)
#pnt=GEOSGeometry('POINT(4314498.56, 1003834.600)').wkt
class Apartment(models.Model):
    SUBCITY_CHOICES = (
    ('ADK', 'Addis Ketema'), ('AKLTY', 'Akaki-Kality'), ('ARD', 'Arada'), ('BL', 'Bole'), ('GL', 'Gulele'),
    ('KLF', 'Kolfe-Keranio'), ('LDTA', 'Ledeta'), ('NFS', 'Nefas Silk'), ('YK', 'Yeka'))
    apt_id = models.CharField(str(SUBCITY_CHOICES)+"-"+get_random_string(length=4), max_length=8,primary_key=True)
    location = models.PointField(default=geos_pnt,extent=(4282586.10,996190.90,4346411.02,1011478.31),
                                    blank=True, null=True, srid=3857, help_text="Point(longitude latitude)")
    no_bedrooms= models.IntegerField(null=True)
    apt_area = models.IntegerField(default=0, null=True)
    apt_cost = models.IntegerField(default=0, null=True)
    apt_subcity = models.CharField(default='Nefas Silk',max_length=100, choices=SUBCITY_CHOICES,null=True)
    register_date = models.DateTimeField('Register Date',auto_now_add=True,null=True)
    slug = models.SlugField(unique=True)
    objects = models.Manager()
    sites =models.ManyToManyField(Site)

    #change points from apt_rent_db to kml
    def pointkml(self):
        points = Apartment.objects.kml()
        return render("placemarks.kml", {'places': points})
    def get_absolute_url(self):
        return reverse('apartment_create', kwargs={'pk': self.pk, 'apt_id': self.apt_id.pk})

    def save(self, *args, **kwargs):
        #self.Latitude = self..y
        #self.Longitude = self.location.x
        self.slug = slugify(self.apt_id)
        super(Apartment, self).save(*args, **kwargs)

    class Meta:
       # order of drop-down list items
       verbose_name = ("Apartment")
       verbose_name_plural = ("Apartments")
       ordering = ('apt_cost',)
       app_label = 'rent_app'

    def __unicode__(self):
        return self.apt_id

urls.py:

from django.urls import path
from . import views
app_name = 'rent_app'


    urlpatterns = [

            path('', views.IndexView.as_view(), name='index'),
            path('apartment_create/<slug:apt_id>)', views.ApartmentCreate.as_view(), name='apartment_create'),
            path('apartments/<int:pk>/', views.ApartmentUpdate.as_view(), name='apartment_update'),
            path('apartments/<int:pk>/delete/', views.ApartmentDelete.as_view(), name='apartment_delete'),
             ]

views.py:

from django.urls import reverse_lazy
from django.views import generic
from django.views.generic.edit import CreateView, DeleteView, UpdateView
from .models import Apartment
from .forms import ApartmentCreateForm


class IndexView(generic.ListView):

    template_name = 'djnago_leaflet.html'
    context_object_name = 'latest_apartments_list'

    def get_queryset(self):

        """Return the last five published apartments."""

        return Apartment.objects.order_by('-register_date')[:5]

class ApartmentCreate(CreateView):
    template_name = 'rent_app/apartment-create-success.html'
    form_class = ApartmentCreateForm
    fields = ['apt_id','location','apt_area','apt_cost']
    success_url= reverse_lazy('apartment-create')

class ApartmentUpdate(UpdateView):
    model = Apartment
    fields = ['apt_id','location','apt_area', 'apt_cost']
    template_name='index_leaflet.html'
    template_name_suffix='apartments'

class ApartmentDelete(DeleteView):
    model = Apartment
    template_name = 'index_leaflet.html'
    template_name_suffix='apartments'
    success_url = reverse_lazy('apartment-list')

the html:

<html>
  <head>
   {% leaflet_js plugins="forms" %}
   {% leaflet_css plugins="forms" %}
  </head>


  <body>

    {% leaflet_map "map" callback="window.map_init_basic" %}
    <h2>Edit Apartment ID {{ Apartment.apt_id }}</h2>
    <h2>Edit Apartment Location {{ Apartment.location }}</h2>
    <form action="{% url 'rent_app:apartment_create' apt_id %}" method="post">
        {% csrf_token %}
        {{ form }}
        <input type="submit"/>
    </form>
  </body>
</html>

I think there are a number of issues in your code.

First regarding the error you are seeing. In your urls you have defined a pattern with the name 'apartment_create' which expects a slug as a parameter. However, apt_id in your template is an empty field. So django cannot find a pattern with the name 'apartment_create' and a valid slug. To solve this change the url pattern to

path('apartment_create/', views.ApartmentCreate.as_view(), name='apartment_create')

And in your template either take out the apt_id from your action in the form (or take out the action all together.

However, in your ApartmenCreate view you are missing the model parameter. In addition the fields and the form parameter are redundant. And are you sure the template_name parameter in that view is correct?

In your model the field apt_id looks strange. You are creating a field with some very obscure verbose_name . If you want to have a choice field you have to set the choices parameter of the field, eg:

apt_id = models.CharField(choices=SUBCITY_CHOICES, max_length=8, primary_key=True)

Your get_absolute_url is also not correct: First of all there is no valid url matching that pattern and secondly a field ( apt_id ) does not have a pk.

In your template you have statements like {{ Apartment.apt_id }} . However, Apartment is a class. So in your views add context_object_name='apartment' so you can access the values in your template like so {{ apartment.apt_id }} .

There are probably some other issues which I have overlooked.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM