In Django, why do I need __unicode__? - python

I'm starting to learn Django and I'm starting out with the Django book.
I came across this concept and I have a hard time understanding the logic..
The book says
"Django uses Unicode objects throughout the framework. Model objects are retrieved as Unicode objects, views interact with Unicode data, and templates are rendered as Unicode. Generally, you won’t have to worry about making sure your encodings are right; things should just work."
Then why do you need to do "def unicode()" to print in unicode? Shouldn't it just work with plain vanilla print()?

Have you tried just printing a model instance that doesn't have a __unicode__ method? You don't get anything really useful. That's where __unicode__ comes into play. You get to define how your model instances are displayed whenever you try to use them in a unicode context.
Try this experiment. Create a simple model. Now print it out:
class MyModel(models.Model):
name = models.CharField(max_length=20)
>>> obj = MyModel("foo")
>>> print obj
See what you get. Now add a __unicode__() method.
class MyModel(models.Model):
name = models.CharField(max_length=20)
def __unicode__(self):
return self.name
Run it again:
>>> obj = MyModel("foo")
>>> print obj

Did you read https://docs.djangoproject.com/en/dev/ref/models/instances/#unicode ? It explains why we needs unicod well. Because python 2.x is not using unicode basically, django needs to handle unicode.

Related

How can I override __str__ in models.py?

Apologies if this is a silly question, I am pretty new to python and django.
I am following along with a django tutorial, and we are creating a fake movie site that lists movies by genre, title, etc.
I am currently trying to override the __str__ function in the models.py file, so rather than displaying Genre (1), it displays the actual genre (ex. "Action").
Here's how my models.py looks currently:
from tkinter import CASCADE
from django.db import models
from django.utils import timezone
# Create your models here.
class Genre(models.Model):
name = models.CharField(max_length=255)
def __str__ (self):
return self.name
class Movie(models.Model):
title = models.CharField(max_length=255)
release_year = models.IntegerField()
number_in_stock = models.IntegerField()
daily_rate = models.FloatField()
genre = models.ForeignKey(Genre, on_delete=models.CASCADE)
date_created = models.DateTimeField(default=timezone.now)
However, vscode is underlining the
def __str__ (self):
When I hover over it, it tells me:
str does not return str pylint(E0307: invalid -str- returned
I tried looking at other solutions, but I could not find one that seemed to match my scenario, so I do apologize if this has been solved elsewhere, and I am too incompetent to understand the problem.
Thanks for your patience!
This question has a couple of good illustrations of why it's important to understand your code before you rely too heavily on IDEs and tools like pylint. I've two suggestions:
The pylint error is just a warning to indicate that your code might have a problem - it is not an absolute fact. The E0307 error says:
Used when a __str__ method returns something which is not a string.
It would be more accurate if it had said "when the pylint checker cannot be sure that you're returning a string". In this case, it's because it doesn't recognise that a Django CharField will in fact return a valid string instance. Your existing __str__ method would work perfectly fine if you ran the code - regardless of what pylint thinks.
You can work around this by forcing the return value to look like a string, e.g., with:
return str(self.name)
or
return f"{self.name}"
But it would be equally valid to disable the check for this line in pylint, with the understanding of why it reported the error. Just applying a fix found on Stack Overflow without understanding the issue is going to make it hard to debug your code in future.
There is a second, completely unrelated issue in your code which will cause you problems later, and that is this line:
from tkinter import CASCADE
I am pretty confident that this has been inserted by your IDE, without your explicitly adding it, because you tried to use CASCADE in your ForeignKey. This is the IDE trying to be helpful - unfortunately it has imported something completely useless, that can cause you problems when you try to deploy your code.
Both of these highlight an important principle: don't rely on IDEs or linters. They are not a substitute for understanding your own code.

Django documentation reference

I am quite new to Django and I really don't get the documentation. For example in my code I query all available pages with Page.objects.public(). This gives me objects of type cms.models.pagemodel.Page. To use this in a template I need to know which methods I can use on this but I just cannot find the documentation and I cannot believe that I have to browse the Django source code to get to know the interface.
So does anyone know where I can find the available methods?
The Django model instance reference has some helpful stuff, but generally when working with model instances, we tend to access their data as attributes (which will be in the model definition) and we call the save method after updating these attributes.
The data types you'll get back from Django model instance attributes are all going to be Python objects, so it's usually more important to understand how to interact with those than to understand all the methods available on an instance.
To get to know a Django model, you should look at its definition. Here's an example:
class Page(models.model):
publication_date = models.DateTimeField(null=True)
name = models.CharField(max_length=255, blank=True)
For example, here, if you had a Page object with a publication_date, and that attribute was stored as a DateTimeField, then Django is going to give you a datetime object when you do:
>>> page = Page.objects.first()
>>> pubdate = page.publication_date
>>> type(pubdate)
<type 'datetime.datetime'>
Similarly, the name attribute is simply a Python string:
>>> page.name = "New page name"
>>> page.save()
# New page name is stored in the db and will be there when queried next.
Lastly, to output these things in a template, you would just refer to them in the same way:
Assuming you have a `page` variable here that is an instance...
Page Name is: {{ page.name }}
The Django book may be more helpful to familiarize yourself with interacting with Django models.

Django models and Python properties

I've tried to set up a Django model with a python property, like so:
class Post(models.Model):
_summary = models.TextField(blank=True)
body = models.TextField()
#property
def summary(self):
if self._summary:
return self._summary
else:
return self.body
#summary.setter
def summary(self, value):
self._summary = value
#summary.deleter
def summary(self):
self._summary = ''
So far so good, and in the console I can interact with the summary property just fine. But when I try to do anything Django-y with this, like Post(title="foo", summary="bar"), it throws a fit. Is there any way to get Django to play nice with Python properties?
Unfortunately, Django models don't play very nice with Python properties. The way it works, the ORM only recognizes the names of field instances in QuerySet filters.
You won't be able to refer to summary in your filters, instead you'll have to use _summary. This gets messy real quick, for example to refer to this field in a multi-table query, you'd have to use something like
User.objects.filter(post___summary__contains="some string")
See https://code.djangoproject.com/ticket/3148 for more detail on property support.

Need some explanation regarding BaseCommentAbstractModel of django comment app

class BaseCommentAbstractModel(models.Model):
"""
An abstract base class that any custom comment models probably should
subclass.
"""
# Content-object field
content_type = models.ForeignKey(ContentType,
verbose_name=_('content type'),
related_name="content_type_set_for_%(class)s")
object_pk = models.TextField(_('object ID'))
content_object = generic.GenericForeignKey(ct_field="content_type", fk_field="object_pk")
# Metadata about the comment
site = models.ForeignKey(Site)
class Meta:
abstract = True
def get_content_object_url(self):
"""
Get a URL suitable for redirecting to the content object.
"""
return urlresolvers.reverse(
"comments-url-redirect",
args=(self.content_type_id, self.object_pk)
)
I have two questions related to this model code.
models.TextField(_('object ID')) Object ID which probably is the verbose Name of this TextField ,How does it reflect in the database?
Why do Django relies on field abstract of Meta innerclass instead of using abc(AbstractBaseClass) module?
That is indeed that verbose name. I assume you understand that _ is the call to ugettext_lazy which is for localizing strings. This is the verbose name of the field. The verbose name is not represented in the database. The name of the field in the database would be object_pk.
I'm not a django dev so I can't speak with authority, but some things are obvious. ABC is new in Python 2.6. This is an issue because as of the most recent release the minimum python version was finally moved to 2.5. This has been being bumped quite quickly as of late. For example it was only on django 1.2 that python 2.4 became required. Abstract models have existed at least as far back as django 1.0 and I think even further back then that (though I can't recall for sure) So even if ABC would be suitable (which I'm not sure it is since the behavior of models is kinda complex), it wouldn't be suitable for django at this point due to the required python version.
Additionally there is some complexity in managing classes that represent the database rather than just data structures. I'm not sure how much this impacts abstract models but for example you can't perform field hiding on django attributes that are Field instances.

Use of unicode in Django

Why is a unicode function required in models.py?
i.e,
def __unicode__(self)
return sumid;
It's not. If you define a __unicode__() method, Django will call it when it needs to render an object in a context where a string representation is needed (e.g. in the model's admin pages).
The documentation says:
The __unicode__() method is called
whenever you call unicode() on an
object. Since Django's database
backends will return Unicode strings
in your model's attributes, you would
normally want to write a __unicode__()
method for your model.
I'm a bit new to Django, but I think I can help you.
First, it isn't exactly required, but it's a really good idea. The field is used to create representations of your objects in the Django admin (otherwise they all have the same name :-P) and when you print out an object to your terminal window to see what's going on (otherwise you get a generic mostly useless message).
Second, from what you wrote, it looks like you're new to Python. I recommend reading some Python tutorials on class syntax. Also, semicolons aren't necessary in this language. The correct syntax for creating the unicode method is:
class Foo(models.Model):
# Model fields go here
def __unicode__(self):
return u"%i" % self.sumid
The __unicode__ method has double underscores because it is a special function, namely when the builtin function unicode( obj ) is called on it, it returns a unicode string representation of that object (sort of like java's ToString).
I hope this helps :-)
I think the others have given some detailed explanations that should be more than enough for you. But here's a straightforward answer: __unicode__() is equivalent to toString() in Java (and many other languages)

Categories