Why do I need to use SlugField in Django? - python

I searched on google and found this: "SlugField is a field for storing URL slugs in a relational database. SlugField is a column defined by the Django ORM. SlugField is actually defined within the django.db."
But still, the definition sounds a little complicated to me. I don't even know what a slug is in this context and not sure about Django ORM.
I just need a reason why I should use SlugField in Django in simple terms.

You don't strictly need to use a SlugField.
"Slug" is a term borrowed from journalism that refers to a short version of a title. As mentioned in a comment to your answer, it's a way to make URLs more explicit while still keeping them somewhat short, instead of using, for example, the full title (which would often be too long), or an ID (which wouldn't be explicit or memorable at all: think of a user who wants to find an article they remember reading: if they start typing some keyword in their address bar, a URL that contains it will pop up, one with an ID will not).
If you wanted you could craft your own slug, by making it URL-friendly (remove any symbol that a URL wouldn't hold, converting anything that would need to be url-encoded, turning spaces into hyphens...) and removing anything unnecessary (e.g. removing words like the, a, an, is, are... or cropping lenghty titles to a maximum number of words or characters).
SlugField is simply a convenience you can use to automate that to some extent. It also comes with some extra features that you might need: for example it automatically generates a slug from a field of your choice, and it can add a unique number to the slug so that you don't accidentally end up with two identical URLs for two different articles that have the same title.
The reason it is a field is that, although you could, it's not smart to calculate a slug every time you access an object: the slug will only change when the title changes, meaning possibly never, so it makes sense to generate it only once and then store it in the database to use it next time, without having to produce it again. This has the added advantage of making a URL to a certain article permanent: you could make it so the slug won't change even if you change the title of the article, which would be a good thing.
Once you have it, since a slug refers unambiguously to a specific object, it acts as a sort of human-readable unique ID, and so it can be used to retrieve the object from the database as efficiently as an opaque numeric ID. It also obscures how many objects you have (if for some reason you want to do that), since a sequential ID of, say, 1543, tells anyone that you probably have 1542 other objects that came before that one.

Related

Sorted/searchable StackedInline options

I have three classes:
Person
Publication
AuthorOrder
Publication has a m2m field to Person through AuthorOrder. This is done to enable making it possible to set the order of authors, which matters for academic publications.
However, the list of Persons is getting long, and it would therefore be nice if it was searchable or at least sorted. However, if I use the obvious method of setting a Meta class to Person, this causes the Persons to be sorted everywhere, including where I don't want them to be.
Is there a way to make it searchable (best) or at least sorted without ruining the order elsewhere (ok)?
Looks like this:
There you go. This works well for us on several projects. https://github.com/and3rson/django-searchable-select

Number of attributes in Django Models

I searched a lot and did not find what I´am looking for.
What would be the best concept for a model class in django?
To extend User, would be better to have a class with several attributes, or break this class into several classes with few attributes? I´m using the django ORM now.
Say I have a class called Person that extends User, would be better:
class Person(models.Model):
user = foreingkey(User)
attribute1 =
...
attributeN =
Or, would it be better to do this:
class PersonContac(models.Model):
user = foreingkey(User)
attribute1 =
...
attribute3 =
class PersonAddress(models.Model):
user = foreingkey(User)
attribute1 =
...
attribute3 =
class PersonHobby(models.Model):
user = foreingkey(User)
attribute1 =
...
attribute3 =
My each of my views would use the data from the smaller classes (probably).
Over time, the atrribute number can expand.
I want to do is do it once, and touch the minimum possible.
Various attributes can be unfilled by the user, they are not required.
The number of user is indefinite (can be a lot).
I´m concerned in terms of long term performance and maintaining.
If someone can explain me, what would be better for my code, and why.
And what would be better in general (less classes/more attributes, or more classes/less attributes), using the Django ORM.
It is better if my views use the data of only one model class, or it makes no (or little) difference?
Edit:
On the rush for writing I used bad names on class. None of these attributes are many-to-many fields, the User will have only one value for each attribute, or blank.
The number of atributes can expand over time, but not in a great number.
Put any data that is specific to only one User directly in the model. This would probably be things like "Name", "Birthday", etc.
Some things might be better served by a separate model, though. For example multiple people might have the same Hobby or one User might have multiple Hobby(s). Make this a separate class and use a ForeignKeyField or ManyToManyField as necessary.
Whatever you choose, the real trick is to optimize the number of database queries. The django-debug-toolbar is helpful here.
Splitting up your models would by default result in multiple database queries, so make sure to read up on select related to condense that down to one.
Also take a look at the defer method when retrieving a queryset. You can exclude some of those fields that aren't necessary if you know you won't use them in a particular view.
I think it's all up to your interface.
If you have to expose ALL data for a user in a single page and you have a single, large model you will end up with a single sql join instead of one for each smaller table.
Conversely, if you just need a few of these attributes, you might obtain a small performance gain in memory usage if you join the user table with a smaller one because you don't have to load a lot of attributes that aren't going to be used (though this might be mitigated through values (documentation here)
Also, if your attributes are not mandatory, you should at least have an idea of how many attributes are going to be filled. Having a large table of almost empty records could be a waste of space. Maybe a problem, maybe not. It depends on your hw resources.
Lastly, if you really think that your attributes can expand a lot, you could try the EAV approach.

url design: ways to hide pk/id from url

To access the details page of an Item on my site, one would use the following url
<mydomain>/item/1
where 1 is the primary key of the Item
I am looking for a solution that allows me to redesign the url with the following requirements:
exclude pk or any sequential ids from the url
be able to uniquely access the Item details page
I intended to ask this as a general web design question, but just thought I should mention that I am working with Python/Django.
You need to have some kind of identifier in the URL, and this identifier:
must be unique (no two objects can have the same id)
must be permanent (the id for an object can never change)
so there aren't all that many options, and the object's primary key is the best choice. If for some reason you can't use that (why not?) you can encode or obfuscate it: see this question and its answers for some ideas about how to do that.
Stack Overflow's own URL design is worth a look. You can reach this question via any URL of the form
https://stackoverflow.com/questions/9897050/any-text-you-like-here!
This allows the URL to contain keywords from the question's title (for search engines) while also being able to change when the title changes without breaking old links.
I don't like the slugfield option because it adds an additional query to the database.
I did the following in a project:
My URL looks like this:
<domain>/item/5927/728e26e9464a171b228bc9884ba3e4f76e2f8866/
This is:
<domain>/item/<id>/<hash>/
If you don't know the hash you can't get to the item:
urls.py:
url(r'^item/(?P<id>\d+)/(?P<hash>\w+)/$', 'rwapp.views.item', name='item')
views.py:
from hashlib import sha1
def item(request,id=None,hash=None):
if not id:
return HttpResponseRedirect("/home")
if hash:
chash = sha1("secret_word%s"%id).hexdigest()
if not chash==hash:
return HttpResponseRedirect("/home")
else:
return HttpResponseRedirect("/home")
Of course, every time you render the URL you have to add the // part.
For Django, you can give your models a SlugField, then have the view look up the model using that.
MyModel.objects.filter(slug_field_name='some-slug-value')
Make sure some form of uniqueness constraint is on it.
Well there are a lot ways to do this. Since you are using django, take a look at SlugField. Or you generate UUID and store it on each item for access.
One dirty way of doing this would be to use a cookie to hold the id of the object being requested. I don't particularly like the idea and it might be very difficult to get a framework to support unless you have experience writing/extending frameworks.
Some frameworks support using an id= attribute instead of your URL path. If this is included as a POST parameter it will not be visible, but linking pages together with POST would be challenging as it is intended for the submission of form data.
The method I would suggest, is to use something besides ids to uniquely identify your objects if this is a real requirement. Then include that in your URL. While this is not an ideal design from the database perspective it does have benefits. First you must consider why you want to hide this information. If it is for SEO purposes, using a name of the item rather than its id is what you want in the URL. The real problem is that if you just hide this information in some other data channel you then have the same URL for different resources. This is sub-par for many reason not the least of which is SEO and user bookmarks. Using a human readable key resolves both situations and others, while infuriating your DBA. Using this method should also work easily into a framework either directly or by using additional code in the controller to make the translation, which might set you right with the DBA.

Display custom labels for values in the Django Admin Site

One of my models has a 'status' field which is only ever modified in code. It is an integer from 1 to 6 (although this may change in the future).
However, in the Admin site, I would like to display a label for this data. So, instead of displaying '5', I would like it to say 'Error'. This means I would be able to easily filter the objects in the database that have the status 'Error' and also my colleagues who don't know what each status means as they are not involved in coding, can use the admin site to its full.
I don't know if I am going the right way about this or if it is even possible, but I would appreciate any help you can give. I would rather not change how the status is stored as it would require a big re-write of some parts of our system. In hindsight I guess it was a bad way to do it, but I didn't think the field would matter as much as it does.
Consider to use choices. Anyway you can customize lots of things in django-admin, just read the docs:
http://docs.djangoproject.com/en/1.2/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_display
http://docs.djangoproject.com/en/1.2/ref/contrib/admin/#django.contrib.admin.ModelAdmin.form
You could create a custom field type that overrides to_python and get_prep_value to store integers in the db but use string values within Python:
http://docs.djangoproject.com/en/dev/howto/custom-model-fields/#django.db.models.django.db.models.Field

How do I form a URL in Django for what I'm doing

Desperate, please help. Will work for food :)
I want to be able to have pages at the following URLs, and I want to be able to look them up by their URL (ie, If somebody goes to a certain URL, I want to be able to check for a page there).
mysite.com/somepage/somesubpage/somesubsubpage/
mysite.com/somepage/somesubpage/anothersubpage/
mysite.com/somepage/somesubpage/somesubpage/
mysite.com/somepage/somepage/
Notice I want to be able to reuse each page's slug (ie, somepage/somepage). Of course each slug will be unique for it's level (ie, cannot have two pages with mysite.com/somepage/other/ and mysite.com/somepage/other/ because they would in essence be the same page). What is a good way to do this. I've tried to store the slug for a page ('somesubpage') in a field called 'slug', and make each slug unique for it's parent page so that the above circumstance can't happen. The problem with this is that if I try to look up a page by it's slug (ie, 'somepage'), and there happens to be a page at mysite.com/other/somepage/ and mysite.com/page/somepage/, how would my application know which one to get (they both have the same slug 'somepage').
You need to also store level and parent attributes, so that you can always get the right object.
The requirement to store hierarchical data comes up very frequently, and I always recommend django-mptt. It's the Django implementation of an efficient algorithm for storing hierarchical data in a database. I've used it on several projects. Basically, as well as storing level and parent, it also stores a left and right for each object, so that it can describe the tree and all its sub-elements uniquely. There are some explanatory links on the project's home page.
It sounds like you're looking for a CMS app. There's a comparison of several Django-based CMS. If you want a full-featured CMS at the center of your project, DjangoCMS 2 or django-page-cms might be the right fit. If you prefer a CMS that supports the basic CMS use cases but goes out of your way most of the time feincms could be something to look at.
edit: incidentally, most of the CMS on the comparision page use django-mptt that Daniel mentions.

Categories

Resources