we have a django app with two objects, cities and events. a common url pattern for us would be:
app.com/city/name-of-city/event/name-of-event
where name-of-city
and name-of-event
are slugs. ex:
class City(models.Model):
name = models.CharField(max_length=100, unique=True)
slug = AutoSlugField(populate_from='name', always_update=True, unique=True, sep='-', max_length=255)
...
events get their slug the same way on the Event model:
slug = AutoSlugField(populate_from='name', always_update=True, unique_with='city', sep='-', max_length=255)
the issue I'm having difficulty sorting out is how to handle an instance where the same city has multiple events with the same name.
mixins.py
class CityMixin(object):
city_slug_url_kwarg = 'slug'
city = None
def fetch_city(self, request, *args, **kwargs):
if not self.city:
self.city = get_object_or_404(
City, slug=kwargs.get(self.city_slug_url_kwarg))
return self.city
def get_context_data(self, **kwargs):
kwargs.setdefault('city', self.city)
return super(CityMixin, self).get_context_data(**kwargs)
def dispatch(self, request, *args, **kwargs):
"""
Sets 'city' within the view
"""
self.city = self.fetch_city(request, *args, **kwargs)
return super(CityMixin, self).dispatch(request, *args, **kwargs)
class EventMixin(CityMixin):
city_slug_url_kwarg = 'city_slug'
event_slug_url_kwarg = 'slug'
event = None
def fetch_event(self, request, *args, **kwargs):
if not self.event:
event = get_list_or_404(
Event, slug=kwargs.get(self.event_slug_url_kwarg))
return self.event
def dispatch(self, request, *args, **kwargs):
"""
Sets 'city' and 'event' within the view
"""
user = request.user
self.city = self.fetch_city(request, *args, **kwargs)
self.event = self.fetch_event(request, *args, **kwargs)
if self.event.city != self.city:
raise Http404
return super(EventMixin, self).dispatch(request, *args, **kwargs)
if I request event with:
event = get_object_or_404(Event, slug=kwargs.get(self.event_slug_url_kwarg))
it will throw an err (MultipleObjectsReturned) if there are multiple identically-named events.
if I request event with:
event = get_list_or_404(Event, slug=kwargs.get(self.event_slug_url_kwarg))
and there are identical events the app doesn't know which obj or index in the list is the correct obj.
is there a method that will ensure the right obj is requested that can also handle the duplicate Event names case?
thanks
The slugs will always be unique per city, because you've set that unique_with
attribute. But you're not using the city in the query, so you'll get events for all cities - which can use the same slug. You need to use the city in the lookup:
event = get_list_or_404(
Event,
slug=kwargs.get(self.event_slug_url_kwarg),
city__slug=kwargs.get(self.city_slug_url_kwarg)
)