Associating users by default and profile


#1

I successfully created the workflow of creating/viewing/editing a Thing and associating it with a user. However, I’d like to (advance it?) create a new model relationship and am struggling. Ideally the user creates a profile that identifies the Shelter they work for. And then the user creates a Thing, which corresponds with the Shelter–because I don’t want the user to have to fill in shelter fields every time they create a Thing.

So I created a second model and replicated the create/view/edit Thing templates and views. My model set up is below. But when I try to link the profile and thing in the same index I get the following error. What all am I missing here?

 NoReverseMatch at /
Reverse for 'shelter_detail' with keyword arguments '{'slug': ''}' not found. 1 pattern(s) tried: ['profile\\/(?P<slug>[^/]+)\\/$']

models.py

from django.db import models
from django.contrib.auth.models import User
    # Create your models here.
    class Shelter(models.Model):
    	name = models.CharField(max_length=255)
    	description = models.TextField()
    	slug = models.SlugField(unique=True)
    	website = models.URLField(max_length=200, default='')
    	user = models.ForeignKey(User, on_delete=models.CASCADE, blank=True, null=True)

	def __str__(self):
		return self.name
	
class Thing(models.Model):
	name = models.CharField(max_length=255) 
	description = models.TextField()
	slug = models.SlugField(unique=True)
	shelter = models.ManyToManyField(Shelter)

	def __str__(self):
		return self.name

from django.contrib.auth.views import (
	password_reset,
	password_reset_done, 
	password_reset_confirm,
	password_reset_complete,
)

urls.py

    from django.contrib import admin
    from django.urls import include, path
    from django.views.generic import TemplateView
    from collection import views
    from collection.backends import MyRegistrationView


    urlpatterns = [
    	path('', views.index, name='home'),
    	path('admin/', admin.site.urls), 


    	path('profile/<slug>/', views.shelter_detail, name='shelter_detail'),
    	path('profile/<slug>/edit/', views.edit_shelter, name='edit_shelter'),

    	
    	path('things/<slug>/', views.thing_detail, name='thing_detail'),
    	path('things/<slug>/edit/', views.edit_thing, name='edit_thing'),

    	# the new password reset URLs 
    	path('accounts/', include('registration.backends.simple.urls')),
    	path('accounts/create_thing/', views.create_thing, name='create_thing'),
    	path('accounts/password/reset/', password_reset,
    		{'template_name': 'registration/password_reset_form.html'}, name="password_reset"),
    	path('accounts/password/reset/done/', password_reset_done,
    		{'template_name': 'registration/password_reset_done.html'}, name="password_reset_done"),
    	path('accounts/password/reset/<uidb64>/<token>/', password_reset_confirm,
    		{'template_name': 'registration/password_reset_confirm.html'}, name="password_reset_confirm"),
    	path('accounts/password/done/', password_reset_complete,
    		{'template_name': 'registration/password_reset_complete.html'},
    		name="password_reset_complete"),
    	path('accounts/register/', MyRegistrationView.as_view(), name='registration_register'),


    ]

#2

This is an error I often get tripped up on too! It means that your front end interface is trying to link to a a shelter that doesn’t exist — specifically, it says the slug is empty, so you have a link on the front-end that is creating a link without a slug. Django’s front end URLs won’t allow you to make a link that would break.

So take a look at your template and how you’re creating the link, and see why it’s making a link with an empty slug. :)

(Sorry for delayed response, I just went on vacation!)


#3

Thank you! I kept thinking it had something to do with the slug creation and I was spinning on that.

If I wanted to show the url link if object existed, is it better to build in the view? So, for example, a user logs in. And if they haven’t created a Shelter yet, the link would go to create_shelter, otherwise it would go to shelter_detail.

I have something like this in the base.html template that’s not working.

		<li class="nav-item dropdown">
			<a class="nav-link dropdown-toggle" href="https://example.com" id="dropdown01" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">{{ user.username }}</a>
			<div class="dropdown-menu" aria-labelledby="dropdown01">
				{% if obj in thing.shelter %}
				<a class="dropdown-item" href="{% url 'shelter_detail' %}">My Organization</a>
				{% else %}
				<a class="dropdown-item" href="{% url 'create_shelter' %}">Create Organization</a>
				{% endif %}
				<a class="dropdown-item" href="{% url 'auth_logout' %}">Logout</a>
			</div>
		</li>

#4

(Again, sorry for slow responses, currently camping on vacation.)

What you could do is make sure that shelter_detail works with no slug specified (so you’d have to account for that in the view). When you’re checking if slug was applied or not, you can then redirect to the right page.

And what you said sounds good too, only show the link if someone is logged in. There is a way to do that with templates, I forgot the tag — it’s something like user.is_logged_in.

I think a combo of the above will help solve your problem. :)