简体   繁体   中英

Display URL in Lower Case in Django

My model has a category for a retailer--example - "Walmart"

All of the retailers in my database have been entered with the first letter capitalized.

I am trying to show a list of products by retailer on my site.

My url looks like so:

path('retailer-deals/<str:retailer>', deals_by_retailer, name='retailer'),

and my view looks like this:

def deals_by_retailer(request,retailer):
    retailer_deals = Deal.objects.filter(retailer__company=retailer).order_by('expired','-date_added')
    retailer = retailer
    return render(request, 'deals/deal_by_retailer.html', {'retailer_deals': retailer_deals, 'retailer': retailer})

So if i go to retailer-deals/walmart nothing shows up...

but of course retailer-deals/Walmart works fine

i might be being nitpicky--but i think it looks more professional with the lower case walmart and just in case someone goes to enter the uppercase version, i want to make sure it populates correctly

I did see someone mention a (?i) for a similar problem,

and i tried changing my path to this:

path('(?i)retailer-deals/<str:retailer>', deals_by_retailer, name='retailer'),

but that doesn't seem to work....and also, if i go to list the retailers with associated links--the generated url will still have the uppercase url..

You can use iexact in your filter, A case-insensitive exact match.

retailer_deals = Deal.objects.filter(
        field_name__iexact=retailer).order_by('expired','-date_added')

As many of other people suggest, the best way is to do such query with slug, so you would have:

from django.template.defaultfilters import slugify
import uuid 
class YourModel(mdoels):
     slug = models.SlugField()
     name = models.CharField(max_mength=100)

     # override the save method to have slug automatically generated
     def save(self, *args, **kwargs):
         if self.pk is None:
             slug = slugify(self.name)
             while self.__class__.objects.filter(slug=slug).exists():
                  slug = "%s-%s" % (slug,str(uuid.uuid4())[:5])
             self.slug = slug
         super(YourModel, self).save(*args, **kwargs)

your url would become:

path('retailer-deals/<slug:slug>', deals_by_retailer, name='retailer'),

and your views:

def deals_by_retailer(request,slug):
    retailer_deals = Deal.objects.filter(retailer__slug=slug)
    ''' codes '''

I'm going to answer your question indirectly because I think doing an iexact filter in your routes is a code smell. It also opens you up to people typing paths like retailer-deals/WaLmArT which would then break if you switched to a setup with slugs down the road for simplicity.

The best practice is to use slugs to define URLs for longevity. Things like spaces, punctuation, and non-ASCII character encoding used in names can make for ugly or invalid URLs.

You can use a slug in urlpatterns like:

from django.urls import path

from . import views

urlpatterns = [
    ...
    path('widgets/<slug:slug>/', views.foo),
]

There's more info in the docs for this example.

Django has a built-in SlugField model field for this use case. You can also prepopulate it in the Django admin from another field such as title.

class WidgetAdmin(admin.ModelAdmin):
    prepopulated_fields = {"slug": ("title",)}

Your path is find.

path('retailer-deals/<str:retailer>', deals_by_retailer, name='retailer'),

your <str:retailer> is some arguments that your request get.

It means it's not fix one. You can attach anything you want - like pk , slug , title , uuid and so on.

So In your situation, if you want to use lowercase in your url, you can add your own slug to your model, and pass it to your url.

ie

Your urls will be

path('retailer-deals/<str:slug>', deals_by_retailer, name='retailer'),

And your views will be

def deals_by_retailer(request,slug):
    retailer_deals = Deal.objects.filter(retailer__slug=slug).order_by('expired','-date_added')
    retailer = retailer
    return render(request, 'deals/deal_by_retailer.html', {'retailer_deals': retailer_deals, 'retailer': retailer})

Also you have to add slug to your model

# maybe your Retailer model
Retailter(models.Model):
    ...
    slug = models.CharField(
        max_length=100,
        verbose_name="slug",
    )
    ...

    # You can save slug automaticall when saving 
    # using __save__ or signals

Using slug in url is good way for many reasons (url not support white space, and many other chars, but your company fields can get them). So you can make slug from your company - unique and well-fit to url.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM