Should I use slug field too in django URLs? - python

I am developing an blog like application where there are going to be posts with similar or sometimes same titles. Also users are able to edit the titles of their post whenever they want.
Currently my urls look like this.
{{post.title}}
Now I've read few answers where along with id they have passed slug too like url of this question.
Even with id the url is going to be unique, right? then why slug? and if it is for humanizing the url then should be store it too?
So to summarize:
If id is unique then why slug?
If its important then should we store it?
If it has anything to do with canonical-link please elaborate the working of canonical links & how slug can help it? or at least direct me to the source.
Reference:
when to store slugfield in database in django?
and this answer

If id is unique then why slug?
Slug is just a way for you to quickly get a sense of what this URL is about - the readability of it which is not guaranteed by only using id.
If its important then should we store it?
URL of this question could be Should I use slug field too in django URLs? and still it redirects to same post. But having said that it also depends on the implementation. In this case it could be that Stack Overflow checks for a valid slug corresponding to the post ID and if not found then redirects to the original one.
I just changed the title of the question and as a result the URL changed as well:
old => http://stackoverflow.com/questions/42407755/should-i-use-slug-field-too-in-django
new => http://stackoverflow.com/questions/42407755/should-i-use-slug-field-too-in-django-urls
So if you store the slug you need to make sure it is updated everytime title is changed.
If it has anything to do with canonical-link please elaborate the working of canonical links & how slug can help it?
Canonical links are used by Search Engines to identify duplicate URLs which lead to same content. YOu can view to source code of this post and you can find following canonical link in the HEAD:
<link rel="canonical" href="http://stackoverflow.com/questions/42407755/should-i-use-slug-field-too-in-django-urls">
A search engine will collect this URL and return it to you when you search for some keywords which matches this URL. One of the factors based on which the search engine ranks the pages is matching keywords in URL. A good slug helps the search engine to return the user best results based on the matched keywords in the URL.

You need to identify a post by exactly 1 unique identifier. That can be either the ID or the slug. Using both is pointless and prone to errors. You can include both a slug and an id in the title, in which case you should probably just ignore the slug entirely passed in the URL and use the ID.
You can ignore the slug and just use the ID like this:
url(r'^(?:[\w-]+)/(?<id>\d+)/$', BlogView.as_view(), name='blog-view')
If you do that you don't need to store the slug at all, just generate it from the title each time you use it.
Personally, I prefer slugs because they provide friendlier URLs which integrate well with Django. For example with a class based view you can create a URL that looks like this:
url(r'^(?P<slug>[\w-]+)/$', BlogView.as_view(), name='blog-view')
And your class based view is super clean:
class BlogView(DetailView):
model=BlogEntry
That's it! Django automagically knows to look the model up by the slug and assuming you have your template named properly you don't need to wire anything else up (Ok you probably do). There is a really helpful gist on github about this setup.
If you want to use slugs, generate it when you save the record and use some kind of automatic mangling to make it unique if there is a collision (or let the user manually override it). In one of my blogs I incorporate the date in the slug to make it more unique then use a recursive function to ensure it's unique. (here's an little tutorial someone made on making unique slugs). It is a good idea to include some way to manually over-ride the slug also.
In the above link he uses a for loop, personally I prefer a recursive function such as:
def autoslug(self, slug, attempt=1):
if MyModel.objects.filter(slug=slug).exists():
return autoslug(slug[:47]+"%d" % attempt, attempt + 1)
else:
return slug
You create a slug field on the model to store the slug. For example, Class Based views can pass a slug and it will magically figure out what you want. Django's has a variety of internal tools that reference it by that name so keep it simple and use the same name django expects.
Also, the URL for a given resource should be unchanging so links are persistent. Changing a slug when you change the title means the URL for the resource changes, IMO it's always a bad idea for the same resource to have a changing URL. It's bad for SEO and bad for anyone who links your resources externally.

Related

Django - giving an unique ID to a blog post/element so it could be used with http referer

I am currently creating my first project and I am using an HTML template that I found online. It is a social media application where you should be able to upload a photo, like the photo, leave a comment, etc.
The issue is that I implemented all those functions, but liking, commenting, copying the URL (share buttong) refreshes the whole page and you end up at the very beginning of the page, because I am not sure how to refer the user to the post they liked/commented.
I am using
return redirect(f'{request.META["HTTP_REFERER"]}#{photo_id}')
, but since my posts don't have an unique identifier, it does nothing.
Any tips would be greatly appreciated. Thanks in advance!
It's so bad that the post doesn't have a unique identifier but you can use other fields to do it without an id field.
you can use some fields like DateTime and title and author name for making a hash and use it instead of an id field.

flask's 2 different Variable Rules of URL Routing, what is the differences?

I am designing a blog web app, and I want to add comments on it. And I do not know which way is better, for action url of comment form.
Way 1
#app.route(/blog/<post_id>/comment/, methods=['POST'])
def comment(post_id):
# add comment to db
pass
way 2
#app.route(/blog/comment/<post_id>/,methods=['POST'])
def comment(post_id):
# add comment to db
pass
P.S.
/blog/<post_id>/ is the permanent url for posts
will there some conflicts when visit the post permanent url throught way1
Which one is legal? or which one is better? and why?
Both are legal. Which is better depends on what you are doing, which you don't mention.
The latter suggests to me that it refers to a specific comment uniquely identified by an id, e.g. /blog/comment/1234/ would mean comment with id 1234.
However, I guess that your intention is to reference the comment resource (multiple comments) associated with a post given by an id.

How to request URL of previous page visited and store parts of it as a ForeignKey?

I have a django application that has an architecture:
Myapp.com/< uniquepageURL>
For posting new things to the page:
Myapp.com/< uniquepageURL>/post
For commenting on a specific post on a page
Myapp.com/< uniquepageURL>/comment< ID# of the post>
For example, if you are commenting on the post that is stored in the database with an ID of 22 then the URL should look like:
Myapp.com/< uniquepageURL>/comment22
This is how I’ve decided to map my urls. Is there a better/simpler way to do it? The < uniquepageURL> is also the ForeignKey of the post object in my models. What I am having trouble with is figuring out how to use the request function in django to look at what the url was so as to gain information from it, namely for posts which uniquepage it is from so I can save the value into the foreignkey field and for comments which post ID it is a comment of. What would the views for each look like?
Here is my urls.py.
For posts:
url(r'^(?P<uniquepageURL>[a-zA-Z0-9_.-]*)/post/$', views.post, name='post')
for comments:
url(r'^(?P<uniquepageURL>[a-zA-Z0-9_./-]*)/comment(?P<post.pk>[0-9]*)/$', views.comment, name='comment')name='comment')ts:
I think the post.pk part is wrong since it returns an error. But I can fix that myself hopefully if I can figure out how to get the post section working at least.
Be aware that the ?P<uniquepageURL> syntax indicates a named group; Django will attempt to match that name to arguments in the view function (see https://docs.djangoproject.com/en/1.7/topics/http/urls/#named-groups).
So, to get that value passed to your view function, simply include a parameter uniquepageURL. Note that means post.pk won't work as a name; consider post_id as an alternative. (Though I supposed you could use a **kwargs construct and get at the value with kwargs['post.pk']).
That said, if you do need other information from the request URL, I think the value you are looking for is request.path (which presumes your signature is def comment(request, uniquepageURL, post_id) or similar.

What's the advantage or benefit of Slug field in Django?

What's the benefit of the slug field? Does it make the url more searching engine friendly? If it does, how? Isn't a meaningful title of the page searching engine friendly enough?
The slug provides a human-friendly url fragment for the page. This is often useful when people are deciding whether or not to click a link. There's one in the url of this page, for example:
http://stackoverflow.com/questions/6192655/whats-the-advantage-or-benefit-of-slug-field-in-django
You can actually get to this question without the slug (in StackOverflow's system), but a slug is a more friendly and more semantic way to address the page. Search engines do place some weight on words that appear in the address of the page.
One downside of using only the slug to address a page is that if you change the content of the page and wish to change the title, you have to decide between changing the slug, or leaving it as is (and thus not reflecting the content of the page). StackOverflow's compromise of having the slug but not relying on it is one solution.
Nothing in Django requires you to use slugs in your application, but it's a convenience that's present because many of us do.

Return template as string - Django

I'm still not sure this is the correct way to go about this, maybe not, but I'll ask anyway. I'd like to re-write wordpress (justification: because I can) albeit more simply myself in Django and I'm looking to be able to configure elements in different ways on the page. So for example I might have:
Blog models
A site update message model
A latest comments model.
Now, for each page on the site I want the user to be able to choose the order of and any items that go on it. In my thought process, this would work something like:
class Page(models.Model)
Slug = models.CharField(max_length=100)
class PageItem(models.Model)
Page = models.ForeignKey(Page)
ItemType = models.CharField(max_length=100) # tells me which model to display
InstanceNum = models.IntegerField() # tells me which instance of which model...
Then, ideally, my template would loop through all the PageItems in a page which is easy enough to do.
But what if my page item is a site update as opposed to a blog post? Basically, I am thinking I'd like to pull different item types back in different orders and display them using the appropriate templates. Now, I thought one way to do this would be to, in views.py, to loop through all of the objects and call the appropriate view function, return a bit of html as a string and then pipe that into the resultant template.
My question is - is this the best way to go about doing things? If so, how do I do it? If not, which way should I be going? I'm pretty new to Django so I'm still learning what it can and can't do, so please bear with me. I've checked SO for dupes and don't think this has been asked before...
I've also looked at Django-cms to see if that helps, but I couldn't get to grips with it.
Any suggestions?
First, some puzzelement.
InstanceNum = models.IntegerField() # all models have primary keys.
In Django, all model are assigned an integer primary key.
The comment doesn't make sense, since you don't need to add a primary key like this. The PageItem already has a primary key.
Also, please use lower case letters for attributes. Only Use Upper Case for Class Names. Please.
"But what if my page item is a site update as opposed to a blog post? Basically, I am thinking I'd like to
pull different item types back in
different orders and display them
using the appropriate templates"
Different types usually means different models. Rather than a vague "PageItem", you probably want to have "Site Update" and "Blog Post" as separate models.
You can then iterate through these various objects and display them in the template.
You can easily have your various Models defined with a method to return HTML information. You don't (generally) want to return fully-baked HTML. But CSS ID or Class information is sometimes helpful.
class SiteUpdate( models.Model ):
page = models.ForeignKey(Page)
item_text = models.CharField(max_length=100)
item_css_class = models.CharField(max_length=64)
Now you can generate this into the template with a simple <div class="{{item.item_css_class}}">{{item.item_text}}</div> and use CSS to handle the formatting details that distinguish site update as opposed to a blog post.
The include template tag can take a variable containing the template to include, so you could loop through a sequence containing the various sub-templates and include them in turn, maybe using a dict to map friendly names to template filenames.

Categories