znawca
znawca

Reputation: 279

Global name 'pk' is not defined django

Hi i have a problem like in topic title.

I have my world detail - here i have a list of countries inside this world. I would like to delete a country only from only this world, not generally and after that automatically return to this world.

view my_world:

def my_world(request, pk):
    world = get_object_or_404(World, pk=pk)
    return render(request, 'game/my_world.html', {'world': world})

def delete_country(request, world_pk, country_pk):
    world = get_object_or_404(World, pk=pk)
    country = get_object_or_404(Country, pk=pk)
    world.country.remove(country)
    return redirect("my_world", pk=world.pk)

Error says it is about line

world = get_object_or_404(World, pk=pk)

in template

{% url 'game.views.delete_country' world_pk=world.pk country_pk=country.pk %}

url.py

url(r'^world/(?P<world_pk>\d+)/(?P<country_pk>\d+)/$', views.delete_country, name='delete_country'),

models.py

class Country(models.Model):
    name = models.CharField(verbose_name="Name of country", max_length=100, default="Australia")
    number = models.IntegerField(verbose_name="number of country", default="1")

    def __unicode__(self):
        return self.name

class World(models.Model):
    country = models.ManyToManyField(Country)
    name = models.CharField(verbose_name="New Map", max_length=100)

    def __unicode__(self):
        return self.name

How to repair this error?

edit:

NoReverseMatch at /world/31/12/

Reverse for 'my_world' with arguments '()' and keyword arguments '{'pk': 31}' not found. 0 pattern(s) tried: []

return redirect("my_world", pk=world.pk)

Upvotes: 3

Views: 3275

Answers (2)

Shang Wang
Shang Wang

Reputation: 25559

Of course, the error cannot be anymore obvious, in your function delete_country you don't have pk as a parameter, but you did:

def delete_country(request, world_pk, country_pk):
    world = get_object_or_404(World, pk=pk)

Maybe you try to do world = get_object_or_404(World, pk=world_pk)

Edit::

You are using the wrong way to return redirect. redirect is expecting a url that it can redirect to, but you are giving it a function name. If your my_world function is also have a url name as my_world, you should use reverse to derive the url from that:

from django.core.urlresolvers import reverse

def delete_country(request, world_pk, country_pk):
    world = get_object_or_404(World, pk=pk)
    country = get_object_or_404(Country, pk=pk)
    world.country.remove(country)
    return redirect(reverse('my_world', args=(world.pk,)))

Check out the redirect documentation and reverse documentation. It might/might not make sense immediately, but if they don't, try to slow down and read/search for some examples as well.

Upvotes: 5

Kaushal Kumar
Kaushal Kumar

Reputation: 1306

There is no variable named pk that's why it is throwing the error. Those methods are called in url. Only world_pk and and country_pk are defined.

Use world = get_object_or_404(World, pk=world_pk)

or world = get_object_or_404(World, pk=country_pk)

Upvotes: 2

Related Questions