在基于类的视图中使用多个 URL 参数来获取对象
Posted
技术标签:
【中文标题】在基于类的视图中使用多个 URL 参数来获取对象【英文标题】:Using Multiple URL Parameters to get_object in Class-Based-View 【发布时间】:2017-05-13 07:33:27 【问题描述】:好的,我对此很陌生,我已经在我的项目上工作了几个月,我想创建接受多个参数来调用视图的 URL。示例 URL 如下所示: http://www.sample.com/builders//m//
通过在我的 DetailView 中覆盖 get_object,我已经成功实现了这一点,但我想知道是否有更好/更简单的方法来实现这一点,或者这是否被认为是一种不好的做法。任何指导将不胜感激。
urls.py
urlpatterns = [
# url(r'^$', builder_list, name='list'),
# url(r'^create/$', builder_create, name='create'),
# url(r'^(?P<slug>[\w-]+)/$', builder_detail, name='detail'),
# url(r'^(?P<slug>[\w-]+)/edit/$', builder_update, name='update'),
# url(r'^(?P<slug>[\w-]+)/delete/$', builder_delete, name='delete'),
# url(r'^$', builder_list, name='sub_list'),
# url(r'^m/create/$', sub_create, name='sub_create'),
url(r'^(?P<builder>[\w-]+)/m/(?P<market>[\w-]+)/$', sub_detail, name='sub_detail'),
# url(r'^m/(?P<slug>[\w-]+)/edit/$', sub_update, name='sub_update'),
# url(r'^m/(?P<slug>[\w-]+)/delete/$', sub_delete, name='sub_delete'),
]
views.py
class BuilderSubDetailView(DetailView):
model = BuilderSub
template_name = "builders/sub_detail.html"
def get_context_data(self, **kwargs):
context = super(BuilderSubDetailView, self).get_context_data(**kwargs)
context['now'] = timezone.now()
print(context)
return context
def get_object(self, queryset=None):
if queryset is None:
queryset = self.get_queryset()
# Next, try looking up by primary key.
builder = self.kwargs['builder']
builder_id = Builder.objects.filter(slug=builder).first().pk
market = self.kwargs['market']
market_id = Market.objects.filter(slug=market).first().pk
if builder is not None and market is not None:
queryset = BuilderSub.objects.filter(parent=builder_id).filter(market=market_id)
# If none of those are defined, it's an error.
if builder is None or market is None:
raise AttributeError("Generic detail view %s must be called with "
"Builder and Market"
% self.__class__.__name__)
try:
# Get the single item from the filtered queryset
obj = queryset.get()
except queryset.model.DoesNotExist:
raise Http404("No %(verbose_name)s found matching the query") % \
'verbose_name': queryset.model._meta.verbose_name
return obj
还有 models.py 供参考——我的 get_absolute_url 函数也有问题吗?
class Builder(models.Model):
added_by = models.ForeignKey(settings.AUTH_USER_MODEL, default=1)
company_name = models.CharField(max_length=80, help_text="Full Company Name", unique=True)
short_name = models.CharField(help_text="Short Company Name", max_length=30)
slug = models.SlugField(unique=True)
website = models.CharField(max_length=80, help_text="Format: www.[website].com")
logo = models.ImageField(blank=True, null=True)
timestamp = models.DateTimeField(auto_now_add=True)
info = RedactorField(verbose_name=u'Company Info')
def show_website_url(self):
return format_html("<a href='url'>url</a>", url=self.website)
def __str__(self):
return self.short_name
class BuilderSub(models.Model):
parent = models.ForeignKey(Builder)
market = models.ForeignKey(Market, null=True, blank=True)
details = RedactorField(verbose_name=u'Details', blank=True, null=True)
main_contact = models.ForeignKey(Person, blank=True, null=True)
def __str__(self):
return ": - ".format(self.pk, self.market.name, self.parent.short_name)
def get_absolute_url(self):
return reverse('builders:sub_detail', kwargs='market': self.market.slug, 'builder': self.parent.slug)
def pre_save_builder_reciever(sender, instance, *args, **kwargs):
instance.slug = slugify(instance.short_name)
pre_save.connect(pre_save_builder_reciever, sender=Builder)
我不能 100% 确定我的 BuilderSub 模型是否适合处理整个 Builder(公司)与其所服务的市场之间的关系,因此我们也将不胜感激任何指导。
【问题讨论】:
我相信你可以创建多个具有不同参数的 url,然后将它们全部指向同一个视图。 【参考方案1】:是的,确实有一种更合乎道德的方式来做到这一点。 DetailView 仅用于处理一个对象。然而,ListView 可以完成工作!
我已将 builder 和 market 替换为 city 和 category。
我也是初学者。希望我已经回答了你的问题:)
views.py
class EntryListView(generic.ListView):
template_name = 'myapp/category.html'
context_object_name = 'entry'
def get_queryset(self):
city_id = self.kwargs['city']
category_id = self.kwargs['category']
entry = Entry.objects.all().filter(city=city_id).filter(category=category_id)
return entry
urls.py
url(r'^(?P<city>[0-9]+)/(?P<category>[0-9]+)/$', views.EntryListView.as_view(), name='entry'),
category.html
% extends 'myapp/base.html' %
% block body %
<table>
% for new in entry %
<tr>
<td>
<img src = "new.image_url">
<br>
<b>Name :</b> new.name<br>
% if new.phone %
<B>Phone No. :</B> new.phone<br>
% endif %
<b>Address :</b> new.address<br>
</td>
</tr>
% endfor %
% endblock %
models.py
class Entry(models.Model):
city = models.ForeignKey(City, on_delete=models.CASCADE)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
name = models.CharField(max_length=250)
phone = models.IntegerField(null=True)
address = models.CharField(max_length=250)
image_url = models.CharField(max_length=500)
def __str__(self):
return self.name
【讨论】:
以上是关于在基于类的视图中使用多个 URL 参数来获取对象的主要内容,如果未能解决你的问题,请参考以下文章
如何使基于类的视图接受来自 URL 的参数或在 URLconf 中硬编码