在基于类的视图中使用多个URL参数来获取get_object

时间:2016-12-29 01:02:17

标签: django django-views django-urls django-class-based-views

好吧,我对此很新,我已经在我的项目上工作了几个月了,我想创建接受多个参数来调用View的URL。示例网址如下所示: http://www.sample.com/builders/ /米//

我通过覆盖我的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(公司)与他们所服务的市场之间关系的合适方式,因此任何指导都会受到赞赏。

1 个答案:

答案 0 :(得分:0)

是的确有更道德的方式来做到这一点。 DetailView仅用于处理一个对象。然而,ListView完成了工作!

我已经用城市和类别取代了建筑商和市场。

我也是初学者。希望我已经回答了你的问题:)

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